How to call Watson APIs with proxy set - node.js

I'm trying to call some API, and currently my server make request for firewall, and I need to set proxy to pass, because the with proxy works perfectly and for security reason's the Company can't release the firewall for me.
Summary: How to call this API setting my proxy server with code in my server to all requests using proxy?
I try use express-http-proxy and http-proxy and I try:
require('dotenv').config({silent: true});
var httpProxy = require('http-proxy');
var server = require('./app', httpProxy.createServer(function (req, res, proxy) {
var buffer = httpProxy.buffer(req);
proxy.proxyRequest(req, res, {
host: 'pxdproxy.com',
port: 8080,
buffer: buffer
});
});
var port = process.env.PORT || process.env.VCAP_APP_PORT || 443;
server.listen(port, function() {
// eslint-disable-next-line
console.log('Server running on port: %d', port);
});
and my call for API:
var conversation = watson.conversation({
url: 'https://gateway.watsonplatform.net/conversation/api',
username: 'xxxxxxxxxxxxxxxxxxxxx',
password: 'xxxxxxxxxxxxxxxxxxxxxxx',
version_date: '2017-12-03',
version: 'v1',
});
I need to call the Conversation API with proxy set.

The SDK you are using to call the Watson API from Node.JS uses the request library.
In order to use a proxy to call the services, you just need to define an environment variable called HTTPS_PROXY.
Based on your example you will use:
HTTPS_PROXY=pxdproxy.com:8080
More information here.

Related

Http proxy with https target

I'm trying to create my own proxy server in NodeJs with the library node-http-proxy the problem is that I want to create a http proxy server that will have the possibility to forward the request to a https target (ex. https://google.com).
I know it's possible, because there is already a library that does this called: proxy-chain
When I try to request a https target with node-http-proxy I get an error: ERR_EMPTY_RESPONSE.
It also states in the documentation that I need to add a PKCS12 client certificate, but the proxy-chain does not do this.
Is there a way I can replicate the proxy-chain library with the node-http-proxy library?
This is my code at the moment:
var proxy = httpProxy.createProxyServer({});
var server = http.createServer(function(req, res) {
// You can define here your custom logic to handle the request
// and then proxy the request.
proxy.web(req, res, {
target: {
hostname: 'github.com',
port: 433,
protocol: 'https',
},
secure: false,
changeOrigin: true
});
});
console.log("listening on port 5050")
server.listen(5050);

Proxying WebSockets through node-http-proxy doesn't work

These are the versions of node and required modules I am using:
Node.js: 0.10.16
Websocket Library: einaros/ws ws#0.4.28
Proxy server: nodejitsu/node-http-proxy http-proxy#0.10.3
When I run the following program my console output looks like this, and doesn't move beyond this point:
$ node app.js
proxy: got upgrade, proxying web request
wss: got connection
Here's the code:
// app.js
// A simple proxying example
//
// Setup websocket server on port 19000
// Setup proxy on port 9000 to proxy to 19000
// Make a websocket request to 9000
//
var WebSocket = require('ws'),
WebSocketServer = WebSocket.Server,
proxy = require('http-proxy');
// goes in a loop sending messages to the server as soon as
// the servers are setup
var triggerClient = function() {
var ws = new WebSocket('ws://localhost:9090/');
ws.on('open', function() {
console.log('ws: connection open');
setInterval(function() {
ws.send("Hello");
}, 1000);
});
ws.on('message', function(data) {
console.log('ws: got ' + data);
});
}
// setup websocket server and a proxy
//
var go = function() {
// setup a websocket server on port 19000
//
var wss = new WebSocketServer({ port: 19000 });
wss.on('connection', function(ws) {
console.log('wss: got connection');
ws.on('message', function(data) {
console.log('wss: got ' + data);
ws.send('wss response: ' + data);
});
});
// setup a proxy server
var server = proxy.createServer(function (req, res, proxy) {
proxy.proxyRequest(req, res, {
host: 'localhost',
port: 19000
});
});
server.on('upgrade', function (req, socket, head) {
console.log('proxy: got upgrade, proxying web request');
server.proxy.proxyWebSocketRequest(req, socket, head, {
host: 'localhost',
port: 19000
});
});
server.listen(9090, triggerClient);
};
process.nextTick(go);
My problem eventually started when I was trying to use hipache, I then simplified things to node-http-proxy and then finally to this piece of code.
If you change the port the WebSocket client is connecting to from 9090 to 19000 (thereby bypassing the proxy), things seem to work fine.
Any suggestions, pointers, feedback would be greatly appreciated.
Thanks!
The core problem is that the master branch of node-http-proxy is only compatible with node <= 0.8.x (see https://github.com/nodejitsu/node-http-proxy#when-to-use-node-http-proxy): there's a tree that implements support for 0.10.x (see https://github.com/nodejitsu/node-http-proxy/tree/caronte) but it isn't the mainline branch and I haven't found any indication of when it will be merged in and available.

Include subdomain when proxying in node

I've setup a simple HTTPS server to handle the following to situations:
Requests to https://localhost:5000/ that have a matching file in my directory are served via connect.static(__dirname). This works great for everything like my index.html and my CSS files and is working exactly as I need.
Requests to https://localhost:5000/api should redirect to https://subdomain.mydomain.com:443/api.
The proxy is properly transferring everything over HTTPS and the SSL handshake part seems to be working exactly as I would expect. The problem is that my API uses the subdomain to determine what database to connect to and what data to return. So, my API sees the request
https://localhost:5000/api/something
instead of
https://subdomain.mydomain.com/api/something
and is throwing an error telling me I have to supply the subdomain.
How can I tell the node proxy to forward (or use) the domain/subdomain when doing the proxy?
Here is my code:
var fs = require('fs');
var connect = require('connect'),
https = require('https'),
httpProxy = require('http-proxy'),
options = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem')
},
endpoint = {
host: 'subdomain.mydomain.com',
port: 443,
prefix: '/api',
target: { https: true }
};
var proxy = new httpProxy.RoutingProxy();
var app = connect()
.use(connect.logger('dev'))
.use(function(req, res, next) {
if (req.url.indexOf(endpoint.prefix) === 0) {
proxy.proxyRequest(req, res, endpoint);
} else {
next();
}
})
.use(connect.static(__dirname));
https.createServer(options, app).listen(5000);
console.log('Listening on port 5000');
Just in case someone bumps into this old question, you should use http-proxy's changeOrigin option.

node.js: proxy websockets to other port

I have written http proxy in node.js running on port 80. All I need is to redirect socket.io traffic to port 9090 and standard http traffic to Apache on 8080. This is my proxy code:
httpProxy = require('http-proxy');
httpProxy.createServer(function (req, res, proxy) {
if (req.url.match(/socket.io/)) {
proxy.proxyRequest(req, res, {
host: 'localhost',
port: 9090
});
} else {
proxy.proxyRequest(req, res, {
host: 'localhost',
port: 8080
});
}
}).listen(80);
Everything works, but io.socket falls back to xhr-polling.
http://localhost/client.htm - falls back to xhr-polling
file:///C:/.../client9090.htm - still uses websocket
socket.io app is running on port 9090, client.htm connects to 80 and client9090.htm connects directly to 9090.
It looks like a node-http-proxy makes socket.io app to work in xhr-polling mode.
Client is Chrome v.25
socket.io app code
var io = require('socket.io').listen(9090);
io.on('connection', function (socket) {
socket.on('hi!', function (data) {
console.log(data);
socket.emit('news');
});
socket.on('ahoj', function (data) {
console.log(data);
});
});
client.htm code
<script src="http://localhost/socket.io/socket.io.js"></script>
<script>
var chat = io.connect('http://localhost')
chat.on('connect', function () {
chat.emit('hi!');
});
chat.on('news', function () {
chat.emit('ahoj',{a:1,b:2});
});
</script>
client9090.htm is the same but localhost is replaced by localhost:9090
As I said, everythig works well, only problem is, that node-http-proxy makes to fall back from websockets to xhr-polling.
Can anyone help?
According to https://npmjs.org/package/http-proxy, when adding a callback to the httpProxy.createServer(), you have to manually proxy 'upgrade' events, so something like this:
httpProxy = require('http-proxy');
// added `var server =` here
var server = httpProxy.createServer(function (req, res, proxy) {
if (req.url.match(/socket.io/)) {
proxy.proxyRequest(req, res, {
host: 'localhost',
port: 9090
});
} else {
proxy.proxyRequest(req, res, {
host: 'localhost',
port: 8080
});
}
}).listen(80);
// added upgrade listener section here:
server.on('upgrade', function (req, socket, head) {
server.proxy.proxyWebSocketRequest(req, socket, head);
});
However, for the usage you described above, you don't even need the callback function - you could just as easily do something like this:
httpProxy = require('http-proxy');
var options = {
pathnameOnly: true,
router: {
'/wiki': '127.0.0.1:8001',
'/blog': '127.0.0.1:8002',
'/api': '127.0.0.1:8003'
}
}
var proxyServer = httpProxy.createServer(options);
proxyServer.listen(80);

Default route using node-http-proxy?

I want to do a simple node.js reverse proxy to host multiple Node.JS applications along with my apache server on the same port 80. So I found this example here
var http = require('http')
, httpProxy = require('http-proxy');
httpProxy.createServer({
hostnameOnly: true,
router: {
'www.my-domain.com': '127.0.0.1:3001',
'www.my-other-domain.de' : '127.0.0.1:3002'
}
}).listen(80);
The problem is that I want to have for example app1.my-domain.com pointing to localhost:3001, app2.my-domain.com pointing to localhost:3002, and all other go to port 3000 for example, where my apache server will be running. I couldn't find anything in the documentation on how to have a "default" route.
Any ideas?
EDIT I want to do that because I have a lot of domains/subdomains handled by my apache server and I don't want to have to modify this routing table each time I have want to add a new subdomain.
For nearly a year, I had successfully used the accepted answer to have a default host, but there's a much simpler way now that node-http-proxy allows for RegEx in the host table.
var httpProxy = require('http-proxy');
var options = {
// this list is processed from top to bottom, so '.*' will go to
// '127.0.0.1:3000' if the Host header hasn't previously matched
router : {
'example.com': '127.0.0.1:3001',
'sample.com': '127.0.0.1:3002',
'^.*\.sample\.com': '127.0.0.1:3002',
'.*': '127.0.0.1:3000'
}
};
// bind to port 80 on the specified IP address
httpProxy.createServer(options).listen(80, '12.23.34.45');
The requires that you do NOT have hostnameOnly set to true, otherwise the RegEx would not be processed.
This isn't baked into node-http-proxy, but it's simple to code:
var httpProxy = require('http-proxy'),
http = require('http'),
addresses;
// routing hash
addresses = {
'localhost:8000': {
host: 'localhost',
port: 8081
},
'local.dev:8000': {
host: 'localhost',
port: 8082
},
'default': {
host: 'xkcd.com',
port: 80
}
};
// create servers on localhost on ports specified by param
function createLocalServer(ports) {
ports.forEach(function(port) {
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('<h1>Hello from ' + port + '</h1');
}).listen(port);
});
console.log('Servers up on ports ' + ports.join(',') + '.');
}
createLocalServer([8081, 8082]);
console.log('======================================\nRouting table:\n---');
Object.keys(addresses).forEach(function(from) {
console.log(from + ' ==> ' + addresses[from].host + ':' + addresses[from].port);
});
httpProxy.createServer(function (req, res, proxy) {
var target;
// if the host is defined in the routing hash proxy to it
// else proxy to default host
target = (addresses[req.headers.host]) ? addresses[req.headers.host] : addresses.default;
proxy.proxyRequest(req, res, target);
}).listen(8000);
If you visit localhost on port 8000 it will proxy to localhost port 8081.
If you visit 127.0.0.1 on port 8000 (which is not defined in our routing hash) it will go to the default 'location', namely xkcd.com on port 80.

Resources