Node.js as a forwarding proxy but changing the URL path? - javascript

How do i let node.js act as a proxy and forward all requests sent from one server to another server but stripping /couchdb/ from the url path so that for example POST /couchdb/mydatabase will be POST /mydatabase. And when it receives the response it should send it to the first server.
All I have done is this (using express) to get all requests where the URL path starts with /couchdb/
app.all(/^\/couchdb\/(?:.)*/, function(req, res) {
});
Could someone guide me through. Thanks

have a look at node-http-proxy. you can use it like this:
var http = require('http'),
httpProxy = require('http-proxy');
httpProxy.createServer(function (req, res, proxy) {
// Put your custom server logic here (eg rewrite url/header,...)
proxy.proxyRequest(req, res, {host: 'localhost', port: 9000});
}).listen(8000);

Related

Calling nodeJS HTTP server from Javascript

I am trying to setup a very simple nodeJS HTTP server. When I call it from the browser, like this http://localhost:8081, it works fine, but when I call is using a JS fetch() method, I get a 404 error:
GET http://localhost/:8081?q=hi
JS:
fetch(":8081/?q=hi")
NODE JS:
const requestListener = function (req, res) {
res.writeHead(200);
res.end('Hello, World!');
}
const server = http.createServer(requestListener);
server.listen(8081);
Every thing is fine, you just need to enable cors that's it, use the below code
const http = require('http')
const requestListener = function (req, res) {
const headers = {
'Access-Control-Allow-Origin': '*', /* #dev First, read about security */
'Access-Control-Allow-Methods': 'OPTIONS, POST, GET',
'Access-Control-Max-Age': 2592000, // 30 days
/** add other headers as per requirement */
};
res.writeHead(200, headers);
res.end(JSON.stringify({"key":"value"}));
}
const server = http.createServer(requestListener);
server.listen(8081);
If you are running both frontend and backend code on the same server then you don’t have to use complete url while if you are running fronted and backed on different server you need to enable cors and use complete url.
When you're calling your local server through JS fetch, you don't need to add the port number you can call it like below:
fetch('/?q=hi')
the URL handed to fetch function looks wronge, it would work if you adjust it to:
fetch('http://localhost:8081/?q=hi');
// or
fetch('/?q=hi');
it should work just fine,
and ensure that you enable the cors if you need to works from any domain

How to access body of request made with nodejs http library

I'm trying to make a post request passing json data. When the request arrives on my express server, it does not have a body. What am I doing wrong?
const http = require('http');
const req = http.request({
hostname: 'localhost',
port: 8080,
path: '/',
method: 'POST'
}, (res) => {
res.on('end', () => {
//
});
});
req.write(JSON.stringify({ something: 'something' }));
req.end();
const express = require('express');
const app = express();
app.use(express.json());
app.post('/', (req, res) => {
console.log(req.body); // undefined
res.send();
});
app.listen(8080);
I have to use the http library of nodejs.
You should:
Move the line where you register the JSON parsing middleware so it appears before the line where you register the / handler. Handlers are called in order so with your current approach, the / will fire and end the chain without reaching the middleware.
Add a Content-Type: application/json request header to the client-side code so that the body parser will not skip over it because it doesn't recognise the (un)declared data type.
8bitIcon could be right. This behavior could be the result of not using a middle ware that parses the body of your request. Check out this post, might help you to solve the problem.
Thank you.

Clone/relay exact request to another URL (nodejs)

I'd like to clone/relay the exact request to another URL in native NodeJs. For example, if you send a POST request to my site "example.com", it will send the exact same request you sent to another URL "example2.com" (data, headers etc). How could I achieve that?
You can use proxy middleware to duplicate the request. For example http-proxy-middleware will allow you to proxy the request to another server, but from what I can tell, you can only modify the response. Which isn't optimal if you don't want to wait on the proxy. You might just grab the main proxy library itself, something like:
const httpProxy = require('http-proxy');
const proxyMiddleware = httpProxy.createProxyMiddleware({
target: 'http://www.example2.com',
selfHandleResponse: true
});
const customProxyMiddleware = (req, res, next) => {
proxy.web(req, res);
next();
};
// This passes all incoming requests to the proxy but does not handle
// any of them. It simply passes it along.
app.use('/', customProxyMiddleware);
This code may not work exactly as intended but it should be a good starting point for what you are attempting.

express-http-proxy still gets blocked by CORS policy

I have an express server statically serving my Polymer project. I have a REST API query that I need to make, but if I make it from the client it will be blocked by CORS. So I used express-http-proxy to try to get around that; I send my request to it, and it redirects to the server that has the REST API endpoint on it. This is the entirety of my server code that's running with node server.js:
var express = require('express');
var proxy = require('express-http-proxy');
var server = express();
server.use('/', express.static(__dirname + '/'));
server.listen(8080);
server.use('/rest/api/2/search', proxy('restserver:8877'));
console.log("Server listening on localhost:8080");
When I access restserver:8877/rest/api/2/search in a browser it returns a bunch of json as a 'default' search.
On the client side, I have iron-ajax making this request:
<iron-ajax
id="getBugs"
url="/rest/api/2/search"
params=''
on-response="handleResponse"
debounce-duration="300">
</iron-ajax>
And in the script section, I'm using this.$.getBugs.generateRequest() in the ready function to send the request. So I load this up, expecting the request to not be blocked by CORS, since... it's being proxied by the server. Instead, Chrome devtools gives me this:
XMLHttpRequest cannot load http://restserver:8877/secure/MyJiraHome.jspa. Redirect from 'http://restserver:8877/secure/MyJiraHome.jspa' to 'http://restserver:8877/secure/Dashboard.jspa' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.
I don't understand why it's giving me those URLs, since I never reference them, and why it's blocking due to CORS, since it's going from the server, not the client, that being the whole point of the proxy.
It may be that express-http-proxy simply forwards the Origin header coming from your client which is http://localhost:8080, causing the end server to reject it.
Try modifying it with proxyReqOptDecorator:
server.use('/rest/api/2/search', proxy('restserver:8877', {
proxyReqOptDecorator(proxyReqOpts) {
proxyReqOpts.headers['Origin'] = 'http://accepted.origin.com';
return proxyReqOpts;
}
}));
Never used express-http-proxy and did not test it tho, so tell me if it's not a solution. Also I think using cors as other people suggested may simplify things a lot. But I don't know your development constraints, so I could be wrong.
Server is probably returning a 302 redirect which is not handled correctly in the used middleware.
Read more how the redirect works: https://en.wikipedia.org/wiki/HTTP_location
You can modify the Location response header to overcome the CORS issue or you can try:
var proxy = require('http-proxy-middleware');
var restServerProxy = proxy({target: 'http://restserver:8877', autoRewrite: true});
server.use('/rest/api/2/search', restServerProxy);
The above example should handle redirects automatically.
You don't need any proxy. Since you are calling endpoint on your server, you can just whitelist your client side for calling your server. You can do that with cors package.
https://www.npmjs.com/package/cors
First, define your CORS policy logic in one file (let's name it cors-policy-logic.js), and then export it so you can use it in other files.
const cors = require('cors');
const whitelist = ['http://localhost:8080', 'http://localhost:your_client_url'];
var corsOptionsDelegate = (req, callback) => {
var corsOptions;
if (whitelist.indexOf(req.header('Origin')) !== -1) {
corsOptions = { origin: true };
} else {
corsOptions = { origin: false };
}
callback(null, corsOptions);
};
exports.cors = cors();
exports.corsWithOptions = cors(corsOptionsDelegate);
Now, import it and use it anywhere were you define some endpoint:
var express = require('express');
const cors = require('./cors-policy-logic.js');
var server = express();
server.use('/', express.static(__dirname + '/'));
server.listen(8080);
server.route('/rest/api/2/search')
.options(cors.corsWithOptions, (req, res) => { res.sendStatus(200); })
.get(cors.cors, (req, res, next) => {
//Your business logic
});
console.log("Server listening on localhost:8080");
Alternative solution would be to use http-proxy-middleware as mentioned by #chimurai.
If you want to proxy to an https server to avoid CORS:
const proxy = require('http-proxy-middleware');
app.use('/proxy', proxy({
pathRewrite: {
'^/proxy/': '/'
},
target: 'https://server.com',
secure: false
}));
Here secure: false needs to be set to avoid UNABLE_TO_VERIFY_LEAF_SIGNATURE error.

node.js Check if payload header contains predefined sequence of characters, protocol - TLS

I need to check, does paket payload header contains some defined data sequence. let's say somethng like "0xABCDEF65432ZZZ". Could you please give me some tips, how to do that.
UPD: Protocol is TLS 1.2
Looks like you're probably trying to get the payload header from a TCP packet.
You should look into the raw-socket module.
The request: curl localhost:8080/url --data "{\"key\": \"keyValue\"}" --header "content-type:application/json"
It depends.. if you wanna do it with http only:
var http = require('http');
function listener(req, res){
switch(req.method){
case 'POST':
req.on('data', function(d){
var data = JSON.parse(d.toString())
console.log('data ', data.key); // output: data keyValue
res.end('processed...');
});
}
}
var server = http.createServer(listener);
server.listen(8080);
console.log('server started..');
As you can see, if you are going to develop something, is better to use a framework, I suggest express:
var express = require('express');
var bodyParser = require('body-parser');
var server = express();
server.use(bodyParser.json());
server.post('/url', function(req, res){
console.log(req.body.key); //outputs: keyValue
res.end('processed...');
});
server.listen(8080);
console.log('server started..');
Edit:
If you are using tls native module...
tls.createServer(options, function (socket) {
socket.addListener("data", function (data) {
//use the data as you want..
});
socket.pipe(socket);
}).listen(8000);
take a look to this document, is kind of old. But could be some help.
at the end, if you want to use a library to encapsulate this kind of works for you..
this seems to be a good choice...

Categories