Here is what i want:
I have an url "10.0.0.1/0000000/abctest/filedirectory/filename",
and with this url, I can read the file accordingly
Thus, i create a server with "http.createServer" and binded at 8001 port, and set nginx that whenever it read /0000000/abctest/, it will redirect to port 8001
After i added the nginx reverse proxy, I try to write my server code, and here is my http server code
var port = 8001;
var http = require('http');
var fs = require('fs');
var DefaultFileDir = '/home/ubuntu/Server/Proj/static';
var UrlPrefix = "/0000000/abctest"
var hostname = "127.0.0.1"
//var host = hostname+UrlPrefix
var server= http.createServer(function(req,res){
var url = req.url;
console.log(url);
var file = DefaultFileDir + url;
fs.readFile(file, function(err,data){
if(err){
console.log(err);
res.writeHeader(404,{
'content-type' : 'text/html;charset="utf-8"'
});
res.write('<h1>404</h1>');
res.end();
}else{
if(url.substr(url.length-3, 3) == ".gz"){
res.writeHeader(200,{
'Content-Encoding' : 'gzip',
'content-type' : 'application/octet-stream'
});
}else{
res.writeHeader(200,{
'content-type' : 'text/html;charset="utf-8"'
});
}
res.write(data);
res.end();
}
});
}).listen(port,hostname);
console.log("Static file server running at\n => http://localhost:" + port + "/\nCTRL + C to shutdown");
And the problem come out:
it dont know how to ignore the url prefix "/0000000/abctest"
Error: ENOENT: no such file or directory, open '/home/ubuntu/xxxxx/static/0000000/abctest/folder001/index.html'
However my actual file path shall be '/home/ubuntu/xxxxx/static/folder001/index.html'
is that http.createserver cannot ignore the url prefix? May i seek for some hints from that.
http://nginx.org/en/docs/http/ngx_http_rewrite_module.html
I finally bypass the problem by rewriting the url with the use of nginx reverse proxy
Related
Im self-educating Node.js. I have created two simple HTML files (summer.html and winter.html) and noded the JS on node.js. I went on localhost:5354/summer.html (and winter.html). Nothing is showing up and I got an error message
This site can’t be reached
The connection was reset.
Try:
Checking the connection
Checking the proxy and the firewall
Running Windows Network Diagnostics
ERR_CONNECTION_RESET
I have tested other lessons and was able to display results on localhost:5354/ but this one doesnt work. What did I do wrong?
JS
var http = require('http');
var url = require('url');
var fs = require('fs');
http.createServer(function (req, res) {
var q = url.parse(req.url, true);
var filename = "." + q.pathname;
fs.readFile(filename, function(err, data) {
if (err) {
res.writeHead(404, {'Content-Type': 'text/html'});
return res.end("404 Not Found");
}
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(data);
return res.end();
});
}).listen(5343);
Hit this URL
localhost:5343/summer.html
Because, You listen in 5343 PORT. But you hit 5354 Port
I'm trying to create an HTTP/S MitM forwarding proxy using Node.js.
The way I'm tackling this project is by reusing the solution found in ./lib/proxy.js file of the NPM Proxy Cache project created by #runk after he raised the issue on the Node HTTP Proxy project issue tracker.
My Proxy() class looks like this:
var request = require('request')
, https = require('https')
, http = require('http')
, net = require('net')
, url = require('url')
, os = require('os')
, fs = require('fs');
var SOCKET_PATH = os.tmpdir() + 'mitm.sock';
console.log('[SOCKET PATH] ' + SOCKET_PATH);
function Proxy (config) {
config = config || {};
if(fs.existsSync(SOCKET_PATH)) {
fs.unlinkSync(SOCKET_PATH);
}
var options = {
key: fs.readFileSync('./certs/dummy.key', 'utf8'),
cert: fs.readFileSync('./certs/dummy.crt', 'utf8')
};
// HTTPS Server
https.createServer(options, this.handler).listen(config.port + 1, this.hostname, function (e) {
if(e) {
console.log('[HTTPS] Server listen() error !');
throw e;
}
});
// HTTP Server
var server = http.createServer(this.handler);
server.listen(config.port, this.hostname, function (e) {
if(e) {
console.log('[HTTP] Server listen() error !');
throw e;
}
});
// Intercept CONNECT requests for HTTPS handshake
server.addListener('connect', this.httpsHandler);
}
Proxy.prototype.handler = function (req, res) {
var schema = !!req.client.pair ? 'https' : 'http'
, path = url.parse(req.url).path;
var dest = schema + '://' + req.headers['host'] + path;
console.log('(1) - [' + schema.toUpperCase() + '] ' + req.method + ' ' + req.url);
var params = {
rejectUnauthorized: false,
url: dest
};
if(req.method.toUpperCase() !== 'GET') {
return console.log('[HTTP] Request is not HTTP GET.');
}
var onResponse = function (e, response) {
if(e == null && response.statusCode === 200) {
return r.pipe(res);
}
var body = 'Status ' + response.statusCode + ' returned';
if(e) {
body = e.toString();
}
res.end(body);
};
var r = request(params);
r.on('response', onResponse.bind(null, null));
r.on('error', onResponse.bind(null));
};
Proxy.prototype.httpsHandler = function (request, socketRequest, bodyHead) {
var httpVersion = request['httpVersion']
, url = request['url'];
console.log('(2) - [HTTPS] ' + request['method'] + ' ' + request['url']);
var proxySocket = new net.Socket();
// ProxySocket event handlers
proxySocket.connect(SOCKET_PATH, function () {
proxySocket.write(bodyHead);
proxySocket.write('HTTP/' + httpVersion + ' 200 Connection established\r\n\r\n');
});
proxySocket.on('data', function (chunk) {
console.log('ProxySocket - "data"');
socketRequest.write(chunk);
});
proxySocket.on('end', function () {
console.log('ProxySocket - "end"');
socketRequest.end();
});
proxySocket.on('error', function (e) {
console.log('ProxySocket - "error"');
console.log(e);
console.log(e.stack);
socketRequest.write('HTTP/' + httpVersion + ' 500 Connection error\r\n\r\n');
socketRequest.end();
});
// SocketRequest event handlers
socketRequest.on('data', function (chunk) {
console.log('SocketRequest - "data"');
proxySocket.write(chunk);
});
socketRequest.on('end', function () {
console.log('SocketRequest - "end"');
proxySocket.end();
});
socketRequest.on('error', function (e) {
console.log('socketRequest - "error"');
console.log(e);
console.log(e.stack);
proxySocket.end();
});
};
module.exports = Proxy;
And my Index.js file that start my program looks like this:
var Proxy = require('./lib/proxy');
var proxy = new Proxy({
hostname: '127.0.0.1',
port: 8000
});
Here's my directory / file structure this:
/my_project
/certs
dummy.crt // Copied from the NPM Proxy Cache project
dummy.csr // Copied from the NPM Proxy Cache project
dummy.key // Copied from the NPM Proxy Cache project
/lib
proxy.js
index.js
I'm testing my program by setting (in Mac OSX Maverick) an HTTP and HTTPS proxy as IP address 127.0.0.1 and port 8000.
When browsing an HTTP only website everything works fine, but if I browse an HTTPS website I get the following error:
{[Error: connect ENOENT] code: 'ENOENT', errno: 'ENOENT', syscall: 'connect'}
Error: connect ENOENT
at errnoException (net.js:904:11)
at Object.afterConnect [as oncomplete] (net.js:895:19)
Any ideas from where this issue could come from and how to fix this ?
Thank you very much in advance !
(If you want to test my code, the NPM module request is the only dependency needed to run the code.)
EDIT: The certs can be downloaded from here : https://github.com/runk/npm-proxy-cache/tree/master/cert.
I'm an author of npm-proxy-cache. In fact I've created another project called thin https://www.npmjs.org/package/thin and I hope in future the npm proxy cache thing will utilize it. Despite the fact that it's still very rough it's usable and it does what you need.
E.g.
proxy code
var Thin = require('thin')
var proxy = new Thin;
// `req` and `res` params are `http.ClientRequest` and `http.ServerResponse` accordingly
// be sure to check http://nodejs.org/api/http.html for more details
proxy.use(function(req, res, next) {
console.log('Proxying:', req.url);
next();
});
// you can add different layers of "middleware" similar to "connect",
// but with few exclusions
proxy.use(function(req, res, next) {
if (req.url === '/foobar')
return res.end('intercepted');
next();
});
proxy.listen(8081, 'localhost', function(err) {
// .. error handling code ..
});
server code
var express = require('express'); // v3.4
var app = express();
app.use(express.urlencoded({limit: '10mb'}));
app.get('/test', function(req, res){
console.log(req.protocol, 'get req.query', req.query);
res.end('get: hello world');
});
app.post('/test', function(req, res) {
console.log(req.protocol, 'post req.query', req.query);
console.log(req.protocol, 'post req.body', req.body);
res.end('post: hello world');
});
app.listen(3000);
var fs = require('fs');
var https = require('https');
https.createServer({
key: fs.readFileSync('./cert/dummy.key'), // your mitm server keys
cert: fs.readFileSync('./cert/dummy.crt')
}, app).listen(3001);
You need to start proxy and server in two terminal sessions, then
curl -d "foo=baz" -k -x https://localhost:8081 https://localhost:3001/test?foo=bar
curl -d "foo=baz" -x http://localhost:8081 http://localhost:3000/test?foo=bar
After that you should be able to see following output from the server
https post req.query { foo: 'bar' }
https post req.body { foo: 'baz' }
http post req.query { foo: 'bar' }
http post req.body { foo: 'baz' }
Small example for interceptor
curl -d "foo=baz" -k -x https://localhost:8081 https://localhost:3001/foobar
It should return intercepted
Hope that helps :)
If I have two node.js servers running, how can I tell which server called the processRequest function?
var http = require('http');
var https = require('https');
function processRequest(req, res) {
res.writeHead(200);
res.end("hello world, I'm on port: " + ???.port + "\n");
}
var server1 = http.createServer(processRequest).listen(80);
var server2 = https.createServer(processRequest).listen(443);
Originally I wanted the port number, but couldn't find the object/variable to give it to me. Based on the below answer it makes more sense to determine encrypted vs non-encrypted since the point is to know which of the http servers the request came in on.
The req parameter is an instance of IncomingMessage from which you can access the socket.
From there you can access both the localPort and remotePort.
Something like:
console.log(req.socket.localPort);
console.log(req.socket.remotePort);
This way you get the port number:
var http = require('http');
var server = http.createServer().listen(8080);
server.on('request', function(req, res){
res.writeHead(200, {"Content-Type": "text/html; charset: UTF-8"});
res.write("Hello from Node! ");
res.write(" Server listening on port " + this.address().port);
res.end();
});
In case you are using http://localhost:<port_number>, then you can get the port number using req.headers.host property.
Example:
const http = require('http');
const server = http.createServer((req, res)=>{
console.log(req.headers.host); // localhost:8080
console.log(req.headers.host.split(':')[1]); // 8080
})
server.listen(8080);
Instead of checking port numbers, you can also check the server instance or the connection object:
var http = require('http'),
https = require('https');
function processRequest(req, res) {
var isSSL = (req.socket.encrypted ? true : false);
// alternate method:
// var isSSL = (this instanceof https.Server);
// or if you want to check against a specific server instance:
// var isServer1 = (this === server1);
res.writeHead(200);
res.end('hello world, i am' + (!isSSL ? ' not' : '') + ' encrypted!\n');
}
var server1 = http.createServer(processRequest).listen(80);
var server2 = https.createServer(processRequest).listen(443);
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);
I am trying to create a http caching proxy server using node.js , where i could forward to any webpages and cached them on my local disk !
The following is my first attempt code :
var http = require('http'),
url = require('url'),
sys = require('url');
var fs = require('fs');
var port = "9010";
// function notFound
function notFound(response){
response.writeHead(404, "text/plain");
response.end("404 : File not Found");
}
//create simple http server with browser requet and browser response
http.createServer(function(b_request, b_response){
//Parse the browser request'url
var b_url = url.parse(b_request.url, true);
if(!b_url.query || !b_url.query.url) return notFound(b_response);
//Read and parse url parameter (/?url=p_url)
var p_url = url.parse(b_url.query.url);
//Initialize Http client
var p_client = http.createClient(p_url.port || 80, p_url.hostname);
//Send request
var p_request = p_client.request('GET', p_url.pathname || "/", {
host: p_url.hostname
});
p_request.end();
//Listen for response
p_request.addListener('response', function(p_response){
//Pass through headers
b_response.writeHead(p_response.statusCode, p_response.headers);
//Pass through data
p_response.addListener('data', function(chunk){
b_response.write(chunk);
});
//End request
p_response.addListener('end', function(){
b_response.end();
});
});
}).listen(port);
console.log("Server running at http://127.0.0.1:" +port + "/");
i want to use any cached library for my app suchas : Node-static(https://github.com/cloudhead/node-static), Static cache, ....
if website that i visited is working fine , my app will forward to it . If not my app will get and return me data that cached on my disk .
is there any solutions for this works ?
thank !