Corrected rApp Catalogue image tag for d release test
[nonrtric.git] / test / http-https-proxy / http_proxy.js
1 //  ============LICENSE_START===============================================
2 //  Copyright (C) 2021 Nordix Foundation. All rights reserved.
3 //  ========================================================================
4 //  Licensed under the Apache License, Version 2.0 (the "License");
5 //  you may not use this file except in compliance with the License.
6 //  You may obtain a copy of the License at
7 //
8 //       http://www.apache.org/licenses/LICENSE-2.0
9 //
10 //  Unless required by applicable law or agreed to in writing, software
11 //  distributed under the License is distributed on an "AS IS" BASIS,
12 //  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 //  See the License for the specific language governing permissions and
14 //  limitations under the License.
15 //  ============LICENSE_END=================================================
16
17 // Basic http/https proxy
18 // Call the the proxy on 8080/8433 for http/https
19 // The destination (proxied) protocol may be http or https
20 // Proxy healthcheck on 8081/8434 for http/https - answers with statistics in json
21
22 const http = require('http');
23 const net = require('net');
24 const urlp = require('url');
25 const process = require('process')
26 const https = require('https');
27 const fs = require('fs');
28
29 // Proxy server port for http
30 const proxyport = 8080;
31 // Proxy server port for https
32 const proxyporthttps = 8433;
33 // Proyx server alive check, port for http
34 const aliveport = 8081;
35 // Proyx server alive check,  port for https
36 const aliveporthttps = 8434;
37
38 // Default https destination port
39 const defaulthttpsport = "443";
40
41 // Certs etc for https
42 const httpsoptions = {
43   key: fs.readFileSync('cert/key.crt'),
44   cert: fs.readFileSync('cert/cert.crt'),
45   passphrase: fs.readFileSync('cert/pass', 'utf8')
46 };
47
48 const stats = {
49   'http-requests-initiated': 0,
50   'http-requests-failed': 0,
51   'https-requests-initiated': 0,
52   'https-requests-failed': 0
53 };
54
55 // handle a http proxy request
56 function httpclientrequest(clientrequest, clientresponse) {
57   stats['http-requests-initiated']++;
58
59   if (clientrequest.url == "/" ) {
60     console.log("Catch bad url in http request: "+clientrequest.url)
61     clientresponse.end();
62     return;
63   }
64   // Extract destination information
65   const clientrequesturl = new URL(clientrequest.url);
66
67   var proxyrequestoptions = {
68     'host': clientrequesturl.hostname,
69     'port': clientrequesturl.port,
70     'method': clientrequest.method,
71     'path': clientrequesturl.pathname+clientrequesturl.search,
72     'agent': clientrequest.agent,
73     'auth': clientrequest.auth,
74     'headers': clientrequest.headers
75   };
76
77   // Setup connection to destination
78   var proxyrequest = http.request(
79     proxyrequestoptions,
80     function (proxyresponse) {
81       clientresponse.writeHead(proxyresponse.statusCode, proxyresponse.headers);
82       proxyresponse.on('data', function (chunk) {
83         clientresponse.write(chunk);
84       });
85       proxyresponse.on('end', function () {
86         clientresponse.end();
87       });
88
89     }
90   );
91
92   // Handle the connection and data transfer between source and desitnation
93   proxyrequest.on('error', function (error) {
94     clientresponse.writeHead(500);
95     stats['http-requests-failed']++;
96     console.log(error);
97     clientresponse.write("<h1>500 Error</h1>\r\n" + "<p>Error was <pre>" + error + "</pre></p>\r\n" + "</body></html>\r\n");
98     clientresponse.end();
99   });
100   clientrequest.addListener('data', function (chunk) {
101     proxyrequest.write(chunk);
102   });
103   clientrequest.addListener('end', function () {
104     proxyrequest.end();
105   });
106 }
107
108 // Function to add a 'connect' message listener to a http server
109 function addhttpsconnect(httpserver) {
110   httpserver.addListener(
111     'connect',
112     function (request, socketrequest, bodyhead) {
113
114
115       stats['https-requests-initiated']++;
116       // Extract destination information
117       var res = request['url'].split(":")
118       var hostname = res[0]
119       var port = defaulthttpsport;
120       if (res[1] != null) {
121         port = res[1]
122       }
123
124       // Setup connection to destination
125       var httpversion = request['httpVersion'];
126       var proxysocket = new net.Socket();
127
128       proxysocket.connect(
129         parseInt(port), hostname,
130         function () {
131           proxysocket.write(bodyhead);
132           socketrequest.write("HTTP/" + httpversion + " 200 Connection established\r\n\r\n");
133         }
134       );
135
136       // Handle the connection and data transfer between source and desitnation
137       proxysocket.on('data', function (chunk) {
138         socketrequest.write(chunk);
139       });
140       proxysocket.on('end', function () {
141         socketrequest.end();
142       });
143
144       socketrequest.on('data', function (chunk) {
145         proxysocket.write(chunk);
146       });
147       socketrequest.on('end', function () {
148         proxysocket.end();
149       });
150
151       proxysocket.on('error', function (err) {
152         stats['https-requests-failed']++;
153         console.log(err);
154         socketrequest.write("HTTP/" + httpversion + " 500 Connection error\r\n\r\n");
155         socketrequest.end();
156       });
157       socketrequest.on('error', function (err) {
158         stats['https-requests-failed']++;
159         console.log(err);
160         proxysocket.end();
161       });
162     }
163   );
164 }
165
166 function main() {
167
168   // -------------------- Alive server ----------------------------------
169   // Responde with '200' and statistics for any path on the alive address
170   const alivelistener = function (req, res) {
171     console.log(stats)
172     res.writeHead(200, { 'Content-Type': 'application/json' });
173     res.write(JSON.stringify(stats))
174     res.end();
175   };
176
177   // The alive server - for healthckeck
178   const aliveserver = http.createServer(alivelistener);
179
180   // The alive server - for healthckeck
181   const aliveserverhttps = https.createServer(httpsoptions, alivelistener);
182
183   //Handle heatlhcheck requests
184   aliveserver.listen(aliveport, () => {
185     console.log('alive server on: '+aliveport);
186     console.log(' example: curl localhost:'+aliveport)
187   });
188
189   //Handle heatlhcheck requests
190   aliveserverhttps.listen(aliveporthttps, () => {
191     console.log('alive server on: '+aliveporthttps);
192     console.log(' example: curl -k https://localhost:'+aliveporthttps)
193   });
194
195   // -------------------- Proxy server ---------------------------------
196
197   // The proxy server
198   const proxyserver  = http.createServer(httpclientrequest).listen(proxyport);
199   console.log('http/https proxy for http proxy calls on port ' + proxyport);
200   console.log(' example: curl --proxy http://localhost:8080 http://100.110.120.130:1234')
201   console.log(' example: curl -k --proxy http//localhost:8080 https://100.110.120.130:5678')
202
203   // handle a http proxy request - https listener
204   addhttpsconnect(proxyserver);
205
206   const proxyserverhttps = https.createServer(httpsoptions, httpclientrequest).listen(proxyporthttps);
207   console.log('http/https proxy for https proxy calls on port ' + proxyporthttps);
208   console.log(' example: curl --proxy-insecure --proxy https://localhost:8433 http://100.110.120.130:1234')
209   console.log(' example: curl --proxy-insecure --proxy https://localhost:8433 https://100.110.120.130:5678')
210
211   // handle a https proxy request - https listener
212   addhttpsconnect(proxyserverhttps);
213
214 }
215
216 //Handle ctrl c when running in interactive mode
217 process.on('SIGINT', () => {
218   console.info("Interrupted")
219   process.exit(0)
220 })
221
222 main();