| 
									
										
										
										
											2018-08-14 01:47:54 +02:00
										 |  |  | import * as https from 'https'; | 
					
						
							|  |  |  | import * as plugins from './smartrequest.plugins'; | 
					
						
							|  |  |  | import * as interfaces from './smartrequest.interfaces'; | 
					
						
							| 
									
										
										
										
											2017-01-29 00:51:47 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-14 01:47:54 +02:00
										 |  |  | import { IncomingMessage } from 'http'; | 
					
						
							| 
									
										
										
										
											2018-06-13 22:34:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-16 23:39:25 +02:00
										 |  |  | export interface IExtendedIncomingMessage extends IncomingMessage { | 
					
						
							| 
									
										
										
										
											2018-07-15 23:21:07 +02:00
										 |  |  |   body: any; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-06-13 22:34:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-16 23:39:25 +02:00
										 |  |  | const buildUtf8Response = ( | 
					
						
							| 
									
										
										
										
											2019-06-12 15:16:27 +02:00
										 |  |  |   incomingMessageArg: IncomingMessage, | 
					
						
							|  |  |  |   autoJsonParse = true | 
					
						
							| 
									
										
										
										
											2018-07-16 23:39:25 +02:00
										 |  |  | ): Promise<IExtendedIncomingMessage> => { | 
					
						
							|  |  |  |   let done = plugins.smartpromise.defer<IExtendedIncomingMessage>(); | 
					
						
							| 
									
										
										
										
											2017-06-05 19:09:40 +02:00
										 |  |  |   // Continuously update stream with data
 | 
					
						
							| 
									
										
										
										
											2018-08-14 01:47:54 +02:00
										 |  |  |   let body = ''; | 
					
						
							|  |  |  |   incomingMessageArg.on('data', function(chunkArg) { | 
					
						
							| 
									
										
										
										
											2018-06-13 22:34:49 +02:00
										 |  |  |     body += chunkArg; | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-14 01:47:54 +02:00
										 |  |  |   incomingMessageArg.on('end', function() { | 
					
						
							| 
									
										
										
										
											2019-06-12 15:16:27 +02:00
										 |  |  |     if (autoJsonParse) { | 
					
						
							|  |  |  |       try { | 
					
						
							|  |  |  |         (incomingMessageArg as IExtendedIncomingMessage).body = JSON.parse(body); | 
					
						
							|  |  |  |       } catch (err) { | 
					
						
							|  |  |  |         (incomingMessageArg as IExtendedIncomingMessage).body = body; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2018-07-16 23:39:25 +02:00
										 |  |  |       (incomingMessageArg as IExtendedIncomingMessage).body = body; | 
					
						
							| 
									
										
										
										
											2017-06-05 19:09:40 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-07-16 23:39:25 +02:00
										 |  |  |     done.resolve(incomingMessageArg as IExtendedIncomingMessage); | 
					
						
							| 
									
										
										
										
											2018-06-13 22:34:49 +02:00
										 |  |  |   }); | 
					
						
							|  |  |  |   return done.promise; | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2017-01-29 00:51:47 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-16 23:39:25 +02:00
										 |  |  | /** | 
					
						
							|  |  |  |  * 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] | 
					
						
							| 
									
										
										
										
											2018-08-14 01:47:54 +02:00
										 |  |  |   }; | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2018-07-16 23:39:25 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-13 22:34:49 +02:00
										 |  |  | export let request = async ( | 
					
						
							|  |  |  |   domainArg: string, | 
					
						
							|  |  |  |   optionsArg: interfaces.ISmartRequestOptions = {}, | 
					
						
							|  |  |  |   streamArg: boolean = false | 
					
						
							| 
									
										
										
										
											2018-07-16 23:39:25 +02:00
										 |  |  | ): Promise<IExtendedIncomingMessage> => { | 
					
						
							| 
									
										
										
										
											2018-07-15 23:21:07 +02:00
										 |  |  |   let done = plugins.smartpromise.defer<any>(); | 
					
						
							| 
									
										
										
										
											2018-07-16 23:39:25 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-12 15:16:27 +02:00
										 |  |  |   // merge options
 | 
					
						
							|  |  |  |   const defaultOptions: interfaces.ISmartRequestOptions = { | 
					
						
							|  |  |  |     autoJsonParse: true | 
					
						
							| 
									
										
										
										
											2019-08-16 21:38:50 +02:00
										 |  |  |   }; | 
					
						
							| 
									
										
										
										
											2019-06-12 15:16:27 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   optionsArg = { | 
					
						
							|  |  |  |     ...defaultOptions, | 
					
						
							|  |  |  |     ...optionsArg | 
					
						
							| 
									
										
										
										
											2019-08-16 21:38:50 +02:00
										 |  |  |   }; | 
					
						
							| 
									
										
										
										
											2019-06-12 15:16:27 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-16 23:39:25 +02:00
										 |  |  |   // parse url
 | 
					
						
							| 
									
										
										
										
											2018-06-13 22:34:49 +02:00
										 |  |  |   let parsedUrl: plugins.url.Url; | 
					
						
							| 
									
										
										
										
											2018-07-16 23:39:25 +02:00
										 |  |  |   parsedUrl = plugins.url.parse(domainArg); | 
					
						
							|  |  |  |   optionsArg.hostname = parsedUrl.hostname; | 
					
						
							|  |  |  |   if (parsedUrl.port) { | 
					
						
							|  |  |  |     optionsArg.port = parseInt(parsedUrl.port); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   optionsArg.path = parsedUrl.path; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // determine if unixsock
 | 
					
						
							| 
									
										
										
										
											2018-08-14 01:47:54 +02:00
										 |  |  |   if (testForUnixSock(domainArg)) { | 
					
						
							|  |  |  |     const detailedUnixPath = parseSocketPathAndRoute(optionsArg.path); | 
					
						
							| 
									
										
										
										
											2018-07-16 23:39:25 +02:00
										 |  |  |     optionsArg.socketPath = detailedUnixPath.socketPath; | 
					
						
							|  |  |  |     optionsArg.path = detailedUnixPath.path; | 
					
						
							| 
									
										
										
										
											2017-06-05 19:09:40 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-08-14 01:47:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-16 23:39:25 +02:00
										 |  |  |   // lets determine the request module to use
 | 
					
						
							|  |  |  |   const requestModule = (() => { | 
					
						
							| 
									
										
										
										
											2018-08-14 01:47:54 +02:00
										 |  |  |     if (parsedUrl.protocol === 'https:') { | 
					
						
							| 
									
										
										
										
											2018-07-16 23:39:25 +02:00
										 |  |  |       return plugins.https; | 
					
						
							| 
									
										
										
										
											2018-08-14 01:47:54 +02:00
										 |  |  |     } else if (parsedUrl.protocol === 'http:') { | 
					
						
							| 
									
										
										
										
											2018-07-16 23:39:25 +02:00
										 |  |  |       return plugins.http; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       throw new Error(`unsupported protocol: ${parsedUrl.protocol}`); | 
					
						
							| 
									
										
										
										
											2017-01-29 00:51:47 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-07-16 23:39:25 +02:00
										 |  |  |   })() as typeof plugins.https; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // lets perform the actual request
 | 
					
						
							| 
									
										
										
										
											2018-07-19 16:16:02 +02:00
										 |  |  |   let request = requestModule.request(optionsArg); | 
					
						
							| 
									
										
										
										
											2018-07-16 23:39:25 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // lets write the requestBody
 | 
					
						
							|  |  |  |   if (optionsArg.requestBody) { | 
					
						
							| 
									
										
										
										
											2018-08-14 01:46:12 +02:00
										 |  |  |     if (!(optionsArg.requestBody instanceof plugins.formData)) { | 
					
						
							| 
									
										
										
										
											2018-08-14 01:47:54 +02:00
										 |  |  |       if (typeof optionsArg.requestBody !== 'string') { | 
					
						
							| 
									
										
										
										
											2018-08-14 01:46:12 +02:00
										 |  |  |         optionsArg.requestBody = JSON.stringify(optionsArg.requestBody); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2018-07-19 16:16:02 +02:00
										 |  |  |       request.write(optionsArg.requestBody); | 
					
						
							| 
									
										
										
										
											2018-07-19 23:22:11 +02:00
										 |  |  |       request.end(); | 
					
						
							| 
									
										
										
										
											2018-07-19 16:16:02 +02:00
										 |  |  |     } else if (optionsArg.requestBody instanceof plugins.formData) { | 
					
						
							| 
									
										
										
										
											2018-07-20 00:50:36 +02:00
										 |  |  |       optionsArg.requestBody.pipe(request).on('finish', event => { | 
					
						
							|  |  |  |         request.end(); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2017-01-29 00:51:47 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-07-19 23:22:11 +02:00
										 |  |  |   } else { | 
					
						
							|  |  |  |     request.end(); | 
					
						
							| 
									
										
										
										
											2017-06-05 19:09:40 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-07-19 16:16:02 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // lets handle an error
 | 
					
						
							| 
									
										
										
										
											2018-08-14 01:47:54 +02:00
										 |  |  |   request.on('error', e => { | 
					
						
							| 
									
										
										
										
											2018-07-16 23:39:25 +02:00
										 |  |  |     console.error(e); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2018-07-19 16:16:02 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // lets handle the response
 | 
					
						
							| 
									
										
										
										
											2018-08-14 01:47:54 +02:00
										 |  |  |   request.on('response', async response => { | 
					
						
							| 
									
										
										
										
											2018-07-19 16:16:02 +02:00
										 |  |  |     if (streamArg) { | 
					
						
							|  |  |  |       done.resolve(response); | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2019-06-12 15:16:27 +02:00
										 |  |  |       const builtResponse = await buildUtf8Response(response, optionsArg.autoJsonParse); | 
					
						
							| 
									
										
										
										
											2018-07-19 16:16:02 +02:00
										 |  |  |       done.resolve(builtResponse); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-16 23:39:25 +02:00
										 |  |  |   const result = await done.promise; | 
					
						
							|  |  |  |   return result; | 
					
						
							| 
									
										
										
										
											2018-06-13 22:34:49 +02:00
										 |  |  | }; |