mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	initial commit
This commit is contained in:
		
				
					committed by
					
						 Nick O'Leary
						Nick O'Leary
					
				
			
			
				
	
			
			
			
						parent
						
							f215970649
						
					
				
				
					commit
					e3b052bc38
				
			| @@ -25,6 +25,7 @@ module.exports = function(RED) { | ||||
|     function HTTPRequest(n) { | ||||
|         RED.nodes.createNode(this,n); | ||||
|         var node = this; | ||||
|         var req; | ||||
|         var nodeUrl = n.url; | ||||
|         var isTemplatedUrl = (nodeUrl||"").indexOf("{{") != -1; | ||||
|         var nodeMethod = n.method || "GET"; | ||||
| @@ -41,7 +42,32 @@ module.exports = function(RED) { | ||||
|         if (process.env.no_proxy != null) { noprox = process.env.no_proxy.split(","); } | ||||
|         if (process.env.NO_PROXY != null) { noprox = process.env.NO_PROXY.split(","); } | ||||
|  | ||||
|         function handleMsg(msg) { | ||||
|             if (node.metric()) { | ||||
|                 // Calculate request time | ||||
|                 var diff = process.hrtime(preRequestTimestamp); | ||||
|                 var ms = diff[0] * 1e3 + diff[1] * 1e-6; | ||||
|                 var metricRequestDurationMillis = ms.toFixed(3); | ||||
|                 node.metric("duration.millis", msg, metricRequestDurationMillis); | ||||
|                 if (res.client && res.client.bytesRead) { | ||||
|                     node.metric("size.bytes", msg, res.client.bytesRead); | ||||
|                 } | ||||
|             } | ||||
|             if (node.ret === "txt") { | ||||
|                 msg.payload = msg.payload.toString(); | ||||
|             } | ||||
|             else if (node.ret === "obj") { | ||||
|                 try { msg.payload = JSON.parse(msg.payload); } | ||||
|                 catch(e) { node.warn(RED._("httpin.errors.json-error")); } | ||||
|             } | ||||
|             node.send(msg); | ||||
|             node.status({}); | ||||
|         } | ||||
|  | ||||
|         this.on("input",function(msg) { | ||||
|             var boundary = ""; | ||||
|             var chunkBuffer = Buffer.from(''); | ||||
|             var headerBodySeparator = ""; | ||||
|             var preRequestTimestamp = process.hrtime(); | ||||
|             node.status({fill:"blue",shape:"dot",text:"httpin.status.requesting"}); | ||||
|             var url = nodeUrl || msg.url; | ||||
| @@ -79,6 +105,7 @@ module.exports = function(RED) { | ||||
|             var opts = urllib.parse(url); | ||||
|             opts.method = method; | ||||
|             opts.headers = {}; | ||||
|             opts.encoding = null; // response body should be buffer, not string | ||||
|             var ctSet = "Content-Type"; // set default camel case | ||||
|             var clSet = "Content-Length"; | ||||
|             if (msg.headers) { | ||||
| @@ -160,36 +187,111 @@ module.exports = function(RED) { | ||||
|             if (tlsNode) { | ||||
|                 tlsNode.addTLSOptions(opts); | ||||
|             } | ||||
|             var req = ((/^https/.test(urltotest))?https:http).request(opts,function(res) { | ||||
|                 (node.ret === "bin") ? res.setEncoding('binary') : res.setEncoding('utf8'); | ||||
|             if (req) { | ||||
|                 req.abort();     | ||||
|             } | ||||
|             req = ((/^https/.test(urltotest))?https:http).request(opts,function(res) { | ||||
|                 //(node.ret === "bin") ? res.setEncoding('binary') : res.setEncoding('utf8'); | ||||
|                 msg.statusCode = res.statusCode; | ||||
|                 msg.headers = res.headers; | ||||
|                 msg.responseUrl = res.responseUrl; | ||||
|                 msg.payload = ""; | ||||
|                 msg.payload = Buffer.from(''); | ||||
|                 // msg.url = url;   // revert when warning above finally removed | ||||
|  | ||||
|                 res.setEncoding(null); | ||||
|                 delete res._readableState.decoder; | ||||
|  | ||||
|                 res.on('data',function(chunk) { | ||||
|                     msg.payload += chunk; | ||||
|                 }); | ||||
|                 res.on('end',function() { | ||||
|                     if (node.metric()) { | ||||
|                         // Calculate request time | ||||
|                         var diff = process.hrtime(preRequestTimestamp); | ||||
|                         var ms = diff[0] * 1e3 + diff[1] * 1e-6; | ||||
|                         var metricRequestDurationMillis = ms.toFixed(3); | ||||
|                         node.metric("duration.millis", msg, metricRequestDurationMillis); | ||||
|                         if (res.client && res.client.bytesRead) { | ||||
|                             node.metric("size.bytes", msg, res.client.bytesRead); | ||||
|                     var nextPart = 0; | ||||
|  | ||||
|                     if (!boundary) { | ||||
|                         var contentType = this.headers['content-type']; | ||||
|                         if (contentType) { | ||||
|                             // Automatically check whether multipart streaming is required | ||||
|                             if (/multipart/.test(contentType)) { | ||||
|                                 // Automatically detect the required boundary (that will be used between parts of the stream) | ||||
|                                 boundary = (contentType.match(/.*;\sboundary=(.*)/) || [null, null])[1]; | ||||
|  | ||||
|                                 if(!boundary) { | ||||
|                                     node.error(RED._("httpin.errors.no-boundary"),msg); | ||||
|                                     return; | ||||
|                                 } | ||||
|  | ||||
|                                 // A boundary needs to start with -- (even if not specified in the http header variable) | ||||
|                                 if (!boundary.startsWith('--')) { | ||||
|                                     boundary = '--' + boundary; | ||||
|                                 } | ||||
|  | ||||
|                                 // Every part contains of headers and a body (content) separated by two EOL (end of line) symbols. | ||||
|                                 // The end of line can be LF (linefeed \n), CR (carriage return \r), CRLF (carriage return linefeed \r\n). | ||||
|                                 // When the stream starts, the EOL should be determined. | ||||
|                                 var eolSymbols = (chunk.toString().match(/(?:\r\r|\n\n|\r\n\r\n)/g) || []); | ||||
|                                  | ||||
|                                 if (eolSymbols.indexOf('\r\n\r\n') >= 0) { | ||||
|                                     headerBodySeparator = '\r\n\r\n'; | ||||
|                                 } | ||||
|                                 else if (eolSymbols.indexOf('\r\r') >= 0) { | ||||
|                                     headerBodySeparator = '\r\r'; | ||||
|                                 } | ||||
|                                 else if (eolSymbols.indexOf('\n\n') >= 0) { | ||||
|                                     headerBodySeparator = '\n\n'; | ||||
|                                 } | ||||
|  | ||||
|                                 if(!headerBodySeparator) { | ||||
|                                     node.error(RED._("httpin.errors.no-separator"),msg); | ||||
|                                     return; | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                     if (node.ret === "bin") { | ||||
|                         msg.payload = new Buffer(msg.payload,"binary"); | ||||
|                   | ||||
|                     // Append the chunk to other (non-processed) chunk data | ||||
|                     chunkBuffer = Buffer.concat([chunkBuffer, chunk]); | ||||
|                     chunk = null;                    | ||||
|  | ||||
|                     if (boundary) { | ||||
|                         while(true) { | ||||
|                             // Parts are separated by boundaries, so try to isolate parts in the received chunks. | ||||
|                             var bodyEnd = chunkBuffer.indexOf(boundary, nextPart); | ||||
|  | ||||
|                             if (bodyEnd == -1) { | ||||
|                                 // Store the remaining (incomplete) part in the chunk buffer, to be processed when the next chunk arrives | ||||
|                                 chunkBuffer = chunkBuffer.slice(nextPart, chunkBuffer.length); | ||||
|                                 break; | ||||
|                             } | ||||
|  | ||||
|                             nextPart = bodyEnd + boundary.length; | ||||
|  | ||||
|                             // Find the part body (that arrives after the part header) | ||||
|                             // The header 'Content length' is optional, so it cannot be used here | ||||
|                             var bodyStart = chunkBuffer.indexOf(headerBodySeparator) + headerBodySeparator.length; | ||||
|  | ||||
|                             // Trim optional CR or LF characters at the start of the body | ||||
|                             for (var i = bodyStart; i <= bodyEnd; i++) { | ||||
|                                 if (chunkBuffer[i] !== '\n' && chunkBuffer[i] !== '\r') { | ||||
|                                     break; | ||||
|                                 } | ||||
|                                 bodyStart++; | ||||
|                             } | ||||
|  | ||||
|                             // Trim optional CR or LF characters at the end of the body | ||||
|                             for (var i = bodyEnd - 1; i >= bodyStart; i--) { | ||||
|                                 if (chunkBuffer[i] !== '\n' && chunkBuffer[i] !== '\r') { | ||||
|                                     break; | ||||
|                                 } | ||||
|                                 bodyEnd--; | ||||
|                             } | ||||
|  | ||||
|                             if (bodyEnd - bodyStart > 0) { | ||||
|                                 // Send the body to the output port of this node | ||||
|                                 msg.payload = chunkBuffer.slice(bodyStart, bodyEnd); | ||||
|                                 handleMsg(msg); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                     else if (node.ret === "obj") { | ||||
|                         try { msg.payload = JSON.parse(msg.payload); } | ||||
|                         catch(e) { node.warn(RED._("httpin.errors.json-error")); } | ||||
|                     } | ||||
|                     node.send(msg); | ||||
|                     node.status({}); | ||||
|                 }); | ||||
|                 res.on('end',function() { | ||||
|                     handleMsg(msg); | ||||
|                 }); | ||||
|             }); | ||||
|             req.setTimeout(node.reqTimeout, function() { | ||||
| @@ -224,3 +326,4 @@ module.exports = function(RED) { | ||||
|         } | ||||
|     }); | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user