refactor(DockerHost): Enhance request handling with fluent API and improved response parsing
This commit is contained in:
@@ -226,54 +226,143 @@ export class DockerHost {
|
||||
*/
|
||||
public async request(methodArg: string, routeArg: string, dataArg = {}) {
|
||||
const requestUrl = `${this.socketPath}${routeArg}`;
|
||||
const response = await plugins.smartrequest.request(requestUrl, {
|
||||
method: methodArg,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Registry-Auth': this.registryToken,
|
||||
Host: 'docker.sock',
|
||||
},
|
||||
requestBody: dataArg,
|
||||
keepAlive: false,
|
||||
});
|
||||
if (response.statusCode !== 200) {
|
||||
console.log(response.body);
|
||||
|
||||
// Build the request using the fluent API
|
||||
const smartRequest = plugins.smartrequest.SmartRequest.create()
|
||||
.url(requestUrl)
|
||||
.header('Content-Type', 'application/json')
|
||||
.header('X-Registry-Auth', this.registryToken)
|
||||
.header('Host', 'docker.sock')
|
||||
.options({ keepAlive: false });
|
||||
|
||||
// Add body for methods that support it
|
||||
if (dataArg && Object.keys(dataArg).length > 0) {
|
||||
smartRequest.json(dataArg);
|
||||
}
|
||||
return response;
|
||||
|
||||
// Execute the request based on method
|
||||
let response;
|
||||
switch (methodArg.toUpperCase()) {
|
||||
case 'GET':
|
||||
response = await smartRequest.get();
|
||||
break;
|
||||
case 'POST':
|
||||
response = await smartRequest.post();
|
||||
break;
|
||||
case 'PUT':
|
||||
response = await smartRequest.put();
|
||||
break;
|
||||
case 'DELETE':
|
||||
response = await smartRequest.delete();
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unsupported HTTP method: ${methodArg}`);
|
||||
}
|
||||
|
||||
// Parse the response body based on content type
|
||||
let body;
|
||||
const contentType = response.headers['content-type'] || '';
|
||||
if (contentType.includes('application/json')) {
|
||||
body = await response.json();
|
||||
} else {
|
||||
body = await response.text();
|
||||
// Try to parse as JSON if it looks like JSON
|
||||
if (body && (body.startsWith('{') || body.startsWith('['))) {
|
||||
try {
|
||||
body = JSON.parse(body);
|
||||
} catch {
|
||||
// Keep as text if parsing fails
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create a response object compatible with existing code
|
||||
const legacyResponse = {
|
||||
statusCode: response.status,
|
||||
body: body,
|
||||
headers: response.headers
|
||||
};
|
||||
|
||||
if (response.status !== 200) {
|
||||
console.log(body);
|
||||
}
|
||||
|
||||
return legacyResponse;
|
||||
}
|
||||
|
||||
public async requestStreaming(methodArg: string, routeArg: string, readStream?: plugins.smartstream.stream.Readable) {
|
||||
const requestUrl = `${this.socketPath}${routeArg}`;
|
||||
const response = await plugins.smartrequest.request(
|
||||
requestUrl,
|
||||
{
|
||||
method: methodArg,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Registry-Auth': this.registryToken,
|
||||
Host: 'docker.sock',
|
||||
},
|
||||
requestBody: null,
|
||||
keepAlive: false,
|
||||
},
|
||||
true,
|
||||
(readStream ? reqArg => {
|
||||
let counter = 0;
|
||||
const smartduplex = new plugins.smartstream.SmartDuplex({
|
||||
writeFunction: async (chunkArg) => {
|
||||
if (counter % 1000 === 0) {
|
||||
console.log(`posting chunk ${counter}`);
|
||||
}
|
||||
counter++;
|
||||
return chunkArg;
|
||||
|
||||
// Build the request using the fluent API
|
||||
const smartRequest = plugins.smartrequest.SmartRequest.create()
|
||||
.url(requestUrl)
|
||||
.header('Content-Type', 'application/json')
|
||||
.header('X-Registry-Auth', this.registryToken)
|
||||
.header('Host', 'docker.sock')
|
||||
.options({ keepAlive: false });
|
||||
|
||||
// If we have a readStream, use the new stream method with logging
|
||||
if (readStream) {
|
||||
let counter = 0;
|
||||
const smartduplex = new plugins.smartstream.SmartDuplex({
|
||||
writeFunction: async (chunkArg) => {
|
||||
if (counter % 1000 === 0) {
|
||||
console.log(`posting chunk ${counter}`);
|
||||
}
|
||||
});
|
||||
readStream.pipe(smartduplex).pipe(reqArg);
|
||||
} : null),
|
||||
);
|
||||
console.log(response.statusCode);
|
||||
console.log(response.body);
|
||||
return response;
|
||||
counter++;
|
||||
return chunkArg;
|
||||
}
|
||||
});
|
||||
|
||||
// Pipe through the logging duplex stream
|
||||
const loggedStream = readStream.pipe(smartduplex);
|
||||
|
||||
// Use the new stream method to stream the data
|
||||
smartRequest.stream(loggedStream, 'application/octet-stream');
|
||||
}
|
||||
|
||||
// Execute the request based on method
|
||||
let response;
|
||||
switch (methodArg.toUpperCase()) {
|
||||
case 'GET':
|
||||
response = await smartRequest.get();
|
||||
break;
|
||||
case 'POST':
|
||||
response = await smartRequest.post();
|
||||
break;
|
||||
case 'PUT':
|
||||
response = await smartRequest.put();
|
||||
break;
|
||||
case 'DELETE':
|
||||
response = await smartRequest.delete();
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unsupported HTTP method: ${methodArg}`);
|
||||
}
|
||||
|
||||
console.log(response.status);
|
||||
|
||||
// For streaming responses, get the Node.js stream
|
||||
const nodeStream = response.streamNode();
|
||||
|
||||
if (!nodeStream) {
|
||||
// If no stream is available, consume the body as text
|
||||
const body = await response.text();
|
||||
console.log(body);
|
||||
|
||||
// Return a compatible response object
|
||||
return {
|
||||
statusCode: response.status,
|
||||
body: body,
|
||||
headers: response.headers
|
||||
};
|
||||
}
|
||||
|
||||
// For streaming responses, return the stream with added properties
|
||||
(nodeStream as any).statusCode = response.status;
|
||||
(nodeStream as any).body = ''; // For compatibility
|
||||
|
||||
return nodeStream;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user