diff --git a/test/test.ts b/test/test.ts index 0899f0a..2b0b612 100644 --- a/test/test.ts +++ b/test/test.ts @@ -23,7 +23,10 @@ tap.test('should post a JSON document over http', async () => { }); tap.test('should deal with unix socks', async () => { - await expect(smartrequest.request('http://unix:/var/run/docker.sock:/containers')) + const socketResponse = await smartrequest.request('http://unix:/var/run/docker.sock:/containers'); + console.log(socketResponse.body); }); -tap.start(); +tap.start({ + throwOnError: true +}); diff --git a/ts/index.ts b/ts/index.ts index 28475ff..b1e8d20 100644 --- a/ts/index.ts +++ b/ts/index.ts @@ -1,4 +1,4 @@ -export { request, extendedIncomingMessage } from './smartrequest.request'; +export { request, IExtendedIncomingMessage } from './smartrequest.request'; export { ISmartRequestOptions } from './smartrequest.interfaces'; export * from './smartrequest.jsonrest'; diff --git a/ts/smartrequest.request.ts b/ts/smartrequest.request.ts index 4024ccd..0354a51 100644 --- a/ts/smartrequest.request.ts +++ b/ts/smartrequest.request.ts @@ -1,85 +1,112 @@ -import * as https from 'https'; -import * as plugins from './smartrequest.plugins'; -import * as interfaces from './smartrequest.interfaces'; +import * as https from "https"; +import * as plugins from "./smartrequest.plugins"; +import * as interfaces from "./smartrequest.interfaces"; -import { IncomingMessage } from 'http'; +import { IncomingMessage } from "http"; -export interface extendedIncomingMessage extends IncomingMessage { +export interface IExtendedIncomingMessage extends IncomingMessage { body: any; } -let buildResponse = (incomingMessageArg: IncomingMessage): Promise => { - let done = plugins.smartpromise.defer(); +const buildUtf8Response = ( + incomingMessageArg: IncomingMessage +): Promise => { + let done = plugins.smartpromise.defer(); // Continuously update stream with data - let body = ''; - incomingMessageArg.on('data', function(chunkArg) { + let body = ""; + incomingMessageArg.on("data", function(chunkArg) { body += chunkArg; }); - incomingMessageArg.on('end', function() { + incomingMessageArg.on("end", function() { try { - (incomingMessageArg as extendedIncomingMessage).body = JSON.parse(body); + (incomingMessageArg as IExtendedIncomingMessage).body = JSON.parse(body); } catch (err) { - (incomingMessageArg as extendedIncomingMessage).body = body; + (incomingMessageArg as IExtendedIncomingMessage).body = body; } - done.resolve(incomingMessageArg as extendedIncomingMessage); + done.resolve(incomingMessageArg as IExtendedIncomingMessage); }); return done.promise; }; +/** + * determine wether a url is a unix sock + * @param urlArg + */ +const testForUnixSock = (urlArg: string): boolean => { + const unixRegex = /^(http:\/\/|https:\/\/|)unix:/; + return unixRegex.test(urlArg); +}; + +/** + * determine socketPath and path for unixsock + */ +const parseSocketPathAndRoute = (stringToParseArg: string) => { + const parseRegex = /(.*):(.*)/; + const result = parseRegex.exec(stringToParseArg); + return { + socketPath: result[1], + path: result[2] + } +} + export let request = async ( domainArg: string, optionsArg: interfaces.ISmartRequestOptions = {}, streamArg: boolean = false -): Promise => { +): Promise => { let done = plugins.smartpromise.defer(); + + // parse url let parsedUrl: plugins.url.Url; - if (domainArg) { - parsedUrl = plugins.url.parse(domainArg); - optionsArg.hostname = parsedUrl.hostname; - if (parsedUrl.port) { - optionsArg.port = parseInt(parsedUrl.port); - } - optionsArg.path = parsedUrl.path; + parsedUrl = plugins.url.parse(domainArg); + optionsArg.hostname = parsedUrl.hostname; + if (parsedUrl.port) { + optionsArg.port = parseInt(parsedUrl.port); } - if (!parsedUrl || parsedUrl.protocol === 'https:') { - let request = plugins.https.request(optionsArg, response => { - if (streamArg) { - done.resolve(response); - } else { - buildResponse(response).then(done.resolve); - } - }); - if (optionsArg.requestBody) { - if (typeof optionsArg.requestBody !== 'string') { - optionsArg.requestBody = JSON.stringify(optionsArg.requestBody); - } - request.write(optionsArg.requestBody); - } - request.on('error', e => { - console.error(e); - }); - request.end(); - } else if (parsedUrl.protocol === 'http:') { - let request = plugins.http.request(optionsArg, response => { - if (streamArg) { - done.resolve(response); - } else { - buildResponse(response).then(done.resolve); - } - }); - if (optionsArg.requestBody) { - if (typeof optionsArg.requestBody !== 'string') { - optionsArg.requestBody = JSON.stringify(optionsArg.requestBody); - } - request.write(optionsArg.requestBody); - } - request.on('error', e => { - console.error(e); - }); - request.end(); - } else { - throw new Error(`unsupported protocol: ${parsedUrl.protocol}`); + optionsArg.path = parsedUrl.path; + + // determine if unixsock + if(testForUnixSock(domainArg)) { + const detailedUnixPath = parseSocketPathAndRoute(optionsArg.path) + optionsArg.socketPath = detailedUnixPath.socketPath; + optionsArg.path = detailedUnixPath.path; } - return done.promise; + + // lets determine the request module to use + const requestModule = (() => { + if (parsedUrl.protocol === "https:") { + return plugins.https; + } else if (parsedUrl.protocol === "http:") { + return plugins.http; + } else { + throw new Error(`unsupported protocol: ${parsedUrl.protocol}`); + } + })() as typeof plugins.https; + + + // lets perform the actual request + let request = requestModule.request(optionsArg, async response => { + if (streamArg) { + done.resolve(response); + } else { + const builtResponse = await buildUtf8Response(response) + done.resolve(builtResponse); + } + }); + + // lets write the requestBody + if (optionsArg.requestBody) { + if (typeof optionsArg.requestBody !== "string") { + optionsArg.requestBody = JSON.stringify(optionsArg.requestBody); + } + request.write(optionsArg.requestBody); + } + request.on("error", e => { + console.error(e); + }); + request.end(); + + const result = await done.promise; + return result; };