I am running static pages via connect
var connect = require('connect');
connect.createServer(
connect.static(__dirname)).listen(8080);
I have to add a response header to the above code to bypass the access control
response.writeHead(200, {
'Content-Type': 'text/html',
'Access-Control-Allow-Origin' : '*'});
How do I add it to the above connect code.
I answered this question here
Relevant code
var http = require("http");
var connect = require('connect');
var app = connect()
.use(connect.logger('dev'))
.use(connect.static('home'))
.use(function(req, res){
res.setHeader("Access-Control-Allow-Origin", "http://example.com");
res.end('hello world\n');
});
var server = http.createServer(app);
server.listen(9999, function () {
console.log('server is listening');
});
Enable cors provides excellent resource for adding cors to your server.
If you got to send the cors headers with every static file that you serve and you have to use connect then do this
navigate to connect\node_modules\send\lib\send.js
look for the setHeader function in the file. This is the function that actually sets header to your static resources. Just add
res.setHeader("Access-Control-Allow-Origin", "your domain");
and all of your files will have the cors header in them
If you are just using connect to serve static files and don't require any of the other functionality consider using send instead. This way you will have access to all of it's methods directly and won't need to edit files. You can simply add headers from your create server method. Here is the sample code
var http = require("http");
var connect = require('connect');
var send = require('send');
var url = require('url');
var app = http.createServer(function(req, res){
// your custom error-handling logic:
function error(err) {
res.statusCode = err.status || 500;
res.end(err.message);
}
// your custom directory handling logic:
function redirect() {
res.statusCode = 301;
res.setHeader('Location', req.url + '/');
res.end('Redirecting to ' + req.url + '/');
}
function setRoot(){
res.setHeader("Access-Control-Allow-Origin",
"http://example.com");
return './public';
}
function setIndex(){
res.setHeader("Access-Control-Allow-Origin",
"http://example.com");
return '/index.html';
}
send(req, url.parse(req.url).pathname)
.root(setRoot()).index(setIndex())
.on('error', error)
.on('directory', redirect)
.pipe(res);
}).listen(3000);
Related
I want to write a simple Node Js application which will capture and re-transmit http/https request to Browser?
I have written the below code, but it works only for http request.
var server = http.createServer(function (req,res) {
console.log("start request:", req.url);
var option = url.parse(req.url);
option.headers = req.headers;
var proxyrequest = http.request(option, function (proxyresponce) {
proxyresponce.on('data', function (chunk) {
console.log("proxy responce length" ,chunk.length);
res.write(chunk,'binary');
});
proxyresponce.on('end',function () {
console.log("proxy responce ended");
res.end();
});
res.writeHead(proxyresponce.statusCode, proxyresponce.headers);
});
});
I want to pull a URL from the DB and use it as the proxied URL. However the setup I've come up with initializes a new BrowserSync server for each URL, using incrementing port numbers.
Is there a way to accomplish this without initializing a new BrowserSync server every time?
Or should I be using another approach?
var bs = require("browser-sync");
var express = require("express");
var router = express.Router();
var app = express();
router.get("/", function(req, res){
var proxyUrl = getUrl() //get url from db (www.example.com)
bs.create("bs1").init({
notify: false,
open: false,
ui: false,
port: 10000,
proxy: proxyUrl
});
res.send();
});
app.use(router);
app.listen(8080, function(){
console.log('listening on *:8080');
});
The above is fine(ish) but is it good practice to be initializing a new server for every URL (potentially thousands)?
And is it safe to be exposing a new port number to every user of the system? (Can I mask this with a subdomain?)
Update
My end goal is to use a unique subdomain to refer to each proxy url.
For example:
sub1.mysite.com proxies www.example.com,
sub2.mysite.com proxies www.example2.com
Browser-sync will not work as the proxy is tie to server setup.
I use following packages:
express
express-http-proxy
vhost (express vhost)
const port = 8080;
var app = require('express')();
var proxy = require('express-http-proxy');
var url = require('url');
var vhost = require('vhost');
app.listen(port);
/* Assuming getUrl() will return an array of sites */
// var sites = getUrl();
// DO NOT put '/' at the end of site
var sites = [
'http://www.bing.com',
'http://samanthagooden.com',
'http://www.courtleigh.com'
];
var i = 0;
sites.forEach(site => {
i++;
var subDomain = 'sub' + i + '.mysite.com';
app.use(vhost(subDomain, proxy(site, {
forwardPath: (req, res) => url.parse(req.url).path,
intercept: (rsp, data, req, res, callback) => {
if (res._headers['content-type']) {
var contentType = res._headers['content-type'];
if (
contentType.indexOf('text') !== -1 ||
contentType.indexOf('javascript') !== -1
) {
// Replace link if content-type = text or javascript
var reg = new RegExp(site, 'g');
res.send(data.toString().replace(reg, ''));
} else {
res.send(data);
}
} else {
res.send(data);
}
}
})));
console.log(subDomain + ':' + port + ' proxy: ' + site);
});
The above example will create following proxies:
sub1.mysite.com:8080 proxy: www.bing.com
sub2.mysite.com:8080 proxy: www.example.com
Maybe I'm misunderstanding what you are trying to do, but Browsersync and express seems a bit overkill in this case, why not just use node-http-proxy with the native http module?
var http = require('http')
var httpProxy = require('http-proxy')
var options = ...
var proxy = httpProxy.createProxyServer(options)
var server = http.createServer(function (req, res) {
var proxyUrl = getUrl()
proxy.web(req, res, { target: proxyUrl })
})
server.listen(8080, function () {
console.log('listening on *:8080')
})
As per me If you want SAAS service using proxy is not the good idea to go is what am thinking.. if you are going with proxy for each client will create process with new port... My Solution is to create node server with listen localhost and map *.domain.com to the server..
If you are using individual database for each client :-
in node logic get cname from request host and use that reference to connect database.
Final Controller code would be..
var express = require('express');
var router = express.Router();
var MongoClient = require('mongodb').MongoClient;
/* GET home page. */
router.get('/', function(req, res, next) {
var client = req.subdomains[0];
console.log(client);
MongoClient.connect('mongodb://localhost:27017/'+client, function(err, db) {
if (err) {
throw err;
}
db.collection('app1').find().toArray(function(err, result) {
if (err) {
throw err;
}
console.log('data');
console.log(result);
});
});
res.render('index', { title: 'Express' });
});
module.exports = router;
~
~
In future if you get more clients you can implement node cluster or standard Ubuntu cluster using webservice
I'm trying to build a reverse proxy in front of a Couchbase SyncGateway. Before sending requests to the sync gateway, I'd like to send them to an authentication server for authentication, then if all is good, send the request on (unmodified from original) to the sync gateway. The database is not staying up to date with the client modifications and I believe this is because I am not successfully proxying PUT/POST requests. Here is the code I have:
var http = require('http');
var httpProxy = require('http-proxy');
var apiProxy = httpProxy.createProxyServer();
var request = require('request').defaults({json: true});
var authServer = 'http://authserverdns:5000';
var syncGateway = 'http://syncgatewaydns:4984';
http.createServer(function (req, res) {
if (req.method == 'POST' || req.method == 'PUT') {
req.body = '';
req.addListener('data', function(chunk) {
req.body += chunk;
});
req.addListener('end', function() {
processRequest(req, res);
});
} else {
processRequest(req, res);
}
}).listen(8080);
function processRequest(req, res) {
request(authServer, function(error, response, body) {
if (body.authenticated) {
console.log('authenticated !!!');
apiProxy.web(this.req, this.res, {target: this.sg});
} else {
console.log('request denied !!!');
}
}.bind({req: req, res: res, sg: syncGateway}));
}
At first I was using an express server and having same issue. As I looked into the problem, it looks like maybe there is an issue with Express and proxying PUT/POST requests. So, I attempted to use some examples out there and this is what I've ended up with, but still not working. Any ideas as to where I'm going wrong here? Authenticated prints, so I know I'm getting to the point of proxying. And the sync gateway seems to be fine with the GET requests.
Thanks
ugh. I wasn't adding the rest of the URL to the forwarding address for the Sync Gateway. The post here helped.
how can i display the request.url into the console.log to see, which url someone called?
So i want to see into console for each call a line with the url.
Sorry, i'm a very beginner with node.js ;-)
Thanks for help.
//Lets require/import the HTTP module
var http = require('http');
//Lets define a port we want to listen to
const PORT=8083;
//We need a function which handles requests and send response
function handleRequest(request, response){
response.end('It Works!! Path Hit: ' + request.url);
}
//Create a server
var server = http.createServer(handleRequest);
//Lets start our server
server.listen(PORT, function(){
//Callback triggered when server is successfully listening. Hurray!
console.log("Server listening on: http://localhost:%s", PORT);
console.log("URL:%s");
});
If you are using express you can setup a custom middleware, that gets called for every request.
// logging middleware
var num = 0;
app.use(function (req, res, next) {
var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
var method = req.method;
var url = req.url;
console.log((++num) + ". IP " + ip + " " + method + " " + url);
next();
});
But you can do the same with your http module server :)
I created a proxy server in node.js using the node-http-proxy module.
Looks like this:
var http = require('http'),
httpProxy = require('http-proxy'),
io = require("socket.io").listen(5555);
var proxy = new httpProxy.RoutingProxy();
http.createServer(function (req, res) {
proxy.proxyRequest(req, res, {
host: 'localhost',
port: 1338
});
}).listen(9000);
So, I need, before sending the response back to the client to get the body from the server that I proxy and analyze it.
But I can't find event or attribute, where I can get this data. I tried:
proxy.on('end', function (data) {
console.log('end');
});
But I can't figure our how to get the mime body from it.
If all you want to do is examine the response (read-only) , you could use :
proxy.on('proxyRes', function(proxyRes, req, res){
proxyRes.on('data' , function(dataBuffer){
var data = dataBuffer.toString('utf8');
console.log("This is the data from target server : "+ data);
});
});
But , note that the 'proxyRes' event is emitted after the response is sent.
Reference in :
https://github.com/nodejitsu/node-http-proxy/issues/382
I found answer:
I rewrite response function for body -
var http = require('http'),
httpProxy = require('http-proxy'),
io = require("socket.io").listen(5555);
var proxy = new httpProxy.RoutingProxy();
http.createServer(function (req, res) {
console.log(req.url);
res.oldWrite = res.write;
res.write = function(data) {
/* add logic for your data here */
console.log(data.toString('UTF8'));
res.oldWrite(data);
}
proxy.proxyRequest(req, res, {
host: 'localhost',
port: 1338
});
}).listen(9000);
This code will console all url request and response form this endpoint.
Based on the answer of #Psycho, following code can be used to modify headers as well
var server = http.createServer(function(req, res) {
res.oldWrite = res.write;
res.write = function(data) {
console.log(data.toString('UTF8'));
res.oldWrite(data);
}
res.oldSetHeader = res.setHeader
res.setHeader = function(k,v) {
console.log(k,v)
res.oldSetHeader(k,v)
}
proxy.web(req, res, { target: proxyPool[key]}); })