I attempting to use ASP and vb.net to run a node.js file that returns a port number from Bungie's API. The issue I am having is that I can use this application locally, but not if I were to publish and deploy the code. The way I do this in Visual Studio is open the Package Manager Console, type in "node proxy.js," and copy the returned value (proxy.js is the node file I'm executing). Then I'd take that port number and add it into my code.
Obviously, this isn't the ideal way to execute this file. So, my question is: is there a way I can execute this file from the code behind in VB.NET? Or, is there a way that I can take my node file and execute it in VB? Here is the proxy.js file I'm working with:
var https = require('https');
var http = require('http');
var BUNGIE = {
host: 'www.bungie.net',
port: 443
};
function copyHeaderFrom(source) {
return function (target, k) {
if (typeof target[k.toLowerCase()] === 'undefined') {
target[k] = source[k];
}
return target;
};
}
http.createServer(function (req, res) {
var outboundData = {
method: req.method,
host: BUNGIE.host,
port: BUNGIE.port,
path: req.url,
headers: req.headers
};
console.log('req.headers.cookie:', req.headers.cookie);
outboundData.headers.host = BUNGIE.host;
console.log('outbound request ========================');
console.log(outboundData);
if (outboundData.method === 'OPTIONS') {
res.writeHead(200, {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': outboundData.headers['access-control-request-headers'] || ''
});
return res.end();
}
https.request(outboundData, function (bungieRes) {
var initialHeaders = {
'access-control-allow-origin': '*',
'origin': outboundData.headers.origin
};
res.writeHead(
bungieRes.statusCode,
Object.keys(bungieRes.headers).reduce(copyHeaderFrom(bungieRes.headers), initialHeaders)
);
bungieRes.pipe(res);
}).end();
}).listen(process.argv[2], function () {
console.log('Bungie Proxy Server running on port %s', this.address().port);
});
Related
The Problem
I have a simple Nodejs Express Hello_World application up and running both locally and on a live server using Plesk-Onyx17.8.11. The app runs correctly on localhost:3000 in my browser:
But after I push the files to the server (using a Filezilla ftp client), my browser can't load the files in the public folder, so it won't load the CSS file:
As you can see the file http://shamimkeshani.ir/stylesheets/style.css cannot be downloaded. This is the correct URL, because we use app.use(express.static(path.join(__dirname, '/public'))); in the Express app. But hypothetically if we insert a wrong URL file of http://shamimkeshani.ir/public/stylesheets/style.css it would find the file and download it correctly from shamimkeshani.ir, which is not the correct behavior! Also, this will not work locally which is the right behavior!!
The codes
I used express-generator to create the default Hello_World Express application. The app.js file:
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
console.log(__dirname);
app.use(express.static(path.join(__dirname, '/public')));
app.use('/', indexRouter);
app.use('/users', usersRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
I use a server.js file to run the Nodejs application. This file is actually a copy of ./bin/www file that Express uses. I use npm start which runs this file locally. Also, the server.js file is set in the Plesk for starting the application on the server:
#!/usr/bin/env node
/**
* Module dependencies.
*/
var app = require('./app');
var debug = require('debug')('app:server');
var http = require('http');
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
/**
* Create HTTP server.
*/
var server = http.createServer(app);
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) {
var port = parseInt(val, 10);
if (isNaN(port)) {
// named pipe
return val;
}
if (port >= 0) {
// port number
return port;
}
return false;
}
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}
package.json file:
{
"name": "app",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./server.js"
},
"dependencies": {
"cookie-parser": "~1.4.3",
"debug": "~2.6.9",
"express": "~4.16.0",
"http-errors": "~1.6.2",
"morgan": "~1.9.0",
"pug": "2.0.0-beta11"
}
}
I also checked the Nodejs versions running locally and at the server and they both match (10.1.0).
I searched a lot and couldn't figure out how to solve this problem. I want for my Nodejs application to work the same locally and on the server. Any additional thoughts on the future problems that I may encounter and any further suggestions are appreciated. Thanks.
I have created a server side route (using iron-router). Code is as follows :
Router.route( "/apiCall/:username", function(){
var id = this.params.username;
},{ where: "server" } )
.post( function(req, res) {
// If a POST request is made, create the user's profile.
//check for legit request
console.log('post detected')
var userId = Meteor.users.findOne({username : id})._id;
})
.delete( function() {
// If a DELETE request is made, delete the user's profile.
});
This app is running on port 3000 on my local. Now I have created another dummy app running on port 5000. Frrom the dummy app, I am firing a http.post request and then listening it on the app on 3000 port. I fire the http.post request via dummy app using the below code :
apiTest : function(){
console.log('apiTest called')
HTTP.post("http://192.168.1.5:3000/apiCall/testUser", {
data: [
{
"name" : "test"
}
]
}, function (err, res) {
if(!err)
console.log("succesfully posted"); // 4
else
console.log('err',err)
});
return true;
}
But I get the following error on the callback :
err { [Error: socket hang up] code: 'ECONNRESET' }
Not able to figure out whats the problem here.
The server side route is successfully called, but the .post() method is not being entered.
Using meteor version 1.6
192.168.1.5 is my ip addr
Okay so if I use Router.map function, the issue is resolved.
Router.map(function () {
this.route("apiRoute", {path: "/apiCall/:username",
where: "server",
action: function(){
// console.log('------------------------------');
// console.log('apiRoute');
// console.log((this.params));
// console.log(this.request.body);
var id = this.params.username;
this.response.writeHead(200, {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
});
if (this.request.method == 'POST') {
// console.log('POST');
var user = Meteor.users.findOne({username : id});
// console.log(user)
if(!user){
return 'no user found'
}
else{
var userId = user._id;
}
}
});
});
It looks like the content type is not set the application/json. So you should do that...
Setting the "Content-Type" header in HTTP.call on client side in Meteor
Our web application is consuming a REST API that requires Basic Authentication.
I want to write the browser-sync gulp task like this:
gulp.task('browser-sync', function() {
browserSync({
server: {
baseDir: './'
},
authenticate: 'authentication-token-here-djfhjsdfjsgdf'
});
});
How might this be configured?
You can do it easily with the middleware option that processes each request:
gulp.task('browser-sync', function() {
browserSync({
server: {
baseDir: './'
},
middleware: [
function(req, res, next) {
const user = 'user';
const pass = 'pass';
let authorized = false;
// See if authorization exist in the request and matches username/password
if (req.headers.authorization) {
const credentials = new Buffer(req.headers.authorization.replace('Basic ', ''), 'base64').toString().split(/:(.*)/)
if (credentials[0] === user && credentials[1] === pass) {
authorized = true;
}
}
if (authorized) {
// Proceed to fulfill the request
next();
} else {
// Authorization doesn't exist / doesn't match, send authorization request in the response header
res.writeHead(401, {'WWW-Authenticate': 'Basic realm="Authenticate"'})
res.end();
}
}
]
});
});
I am developing a node.js proxy server application and I want it to support HTTP and HTTPS(SSL) protocols (as server).
I'm currently using node-http-proxy like this:
const httpProxy = require('http-proxy'),
http = require('http');
var server = httpProxy.createServer(9000, 'localhost', function(req, res, proxy) {
console.log(req.url);
proxy.proxyRequest(req, res);
});
http.createServer(function(req, res) {
res.end('hello!');
}).listen(9000);
server.listen(8000);
I setup my browser to use HTTP proxy on localhost:8000 and it works. I also want to catch HTTPS requests (ie. setup my browser to use localhost:8000 as HTTPS proxy as well and catch the requests in my application). Could you please help me how can I do that?
PS:
If I subscribe to upgrade event of httpProxy server object I can get the requests but I don't know how to forward the request and send response to client:
server.on('upgrade', function(req, socket, head) {
console.log(req.url);
// I don't know how to forward the request and send the response to client
});
Any helps would be appreciated.
Solutions barely exist for this, and the documentation is poor at best for supporting both on one server. The trick here is to understand that client proxy configurations may send https requests to an http proxy server. This is true for Firefox if you specify an HTTP proxy and then check "same for all protocols".
You can handle https connections sent to an HTTP server by listening for the "connect" event. Note that you won't have access to the response object on the connect event, only the socket and bodyhead. Data sent over this socket will remain encrypted to you as the proxy server.
In this solution, you don't have to make your own certificates, and you won't have certificate conflicts as a result. The traffic is simply proxied, not intercepted and rewritten with different certificates.
// Install npm dependencies first
// npm init
// npm install --save url#0.10.3
// npm install --save http-proxy#1.11.1
var httpProxy = require("http-proxy");
var http = require("http");
var url = require("url");
var net = require('net');
var server = http.createServer(function (req, res) {
var urlObj = url.parse(req.url);
var target = urlObj.protocol + "//" + urlObj.host;
console.log("Proxy HTTP request for:", target);
var proxy = httpProxy.createProxyServer({});
proxy.on("error", function (err, req, res) {
console.log("proxy error", err);
res.end();
});
proxy.web(req, res, {target: target});
}).listen(8080); //this is the port your clients will connect to
var regex_hostport = /^([^:]+)(:([0-9]+))?$/;
var getHostPortFromString = function (hostString, defaultPort) {
var host = hostString;
var port = defaultPort;
var result = regex_hostport.exec(hostString);
if (result != null) {
host = result[1];
if (result[2] != null) {
port = result[3];
}
}
return ( [host, port] );
};
server.addListener('connect', function (req, socket, bodyhead) {
var hostPort = getHostPortFromString(req.url, 443);
var hostDomain = hostPort[0];
var port = parseInt(hostPort[1]);
console.log("Proxying HTTPS request for:", hostDomain, port);
var proxySocket = new net.Socket();
proxySocket.connect(port, hostDomain, function () {
proxySocket.write(bodyhead);
socket.write("HTTP/" + req.httpVersion + " 200 Connection established\r\n\r\n");
}
);
proxySocket.on('data', function (chunk) {
socket.write(chunk);
});
proxySocket.on('end', function () {
socket.end();
});
proxySocket.on('error', function () {
socket.write("HTTP/" + req.httpVersion + " 500 Connection error\r\n\r\n");
socket.end();
});
socket.on('data', function (chunk) {
proxySocket.write(chunk);
});
socket.on('end', function () {
proxySocket.end();
});
socket.on('error', function () {
proxySocket.end();
});
});
Here is my NO-dependencies solution (pure NodeJS system libraries):
const http = require('http')
const port = process.env.PORT || 9191
const net = require('net')
const url = require('url')
const requestHandler = (req, res) => { // discard all request to proxy server except HTTP/1.1 CONNECT method
res.writeHead(405, {'Content-Type': 'text/plain'})
res.end('Method not allowed')
}
const server = http.createServer(requestHandler)
const listener = server.listen(port, (err) => {
if (err) {
return console.error(err)
}
const info = listener.address()
console.log(`Server is listening on address ${info.address} port ${info.port}`)
})
server.on('connect', (req, clientSocket, head) => { // listen only for HTTP/1.1 CONNECT method
console.log(clientSocket.remoteAddress, clientSocket.remotePort, req.method, req.url)
if (!req.headers['proxy-authorization']) { // here you can add check for any username/password, I just check that this header must exist!
clientSocket.write([
'HTTP/1.1 407 Proxy Authentication Required',
'Proxy-Authenticate: Basic realm="proxy"',
'Proxy-Connection: close',
].join('\r\n'))
clientSocket.end('\r\n\r\n') // empty body
return
}
const {port, hostname} = url.parse(`//${req.url}`, false, true) // extract destination host and port from CONNECT request
if (hostname && port) {
const serverErrorHandler = (err) => {
console.error(err.message)
if (clientSocket) {
clientSocket.end(`HTTP/1.1 500 ${err.message}\r\n`)
}
}
const serverEndHandler = () => {
if (clientSocket) {
clientSocket.end(`HTTP/1.1 500 External Server End\r\n`)
}
}
const serverSocket = net.connect(port, hostname) // connect to destination host and port
const clientErrorHandler = (err) => {
console.error(err.message)
if (serverSocket) {
serverSocket.end()
}
}
const clientEndHandler = () => {
if (serverSocket) {
serverSocket.end()
}
}
clientSocket.on('error', clientErrorHandler)
clientSocket.on('end', clientEndHandler)
serverSocket.on('error', serverErrorHandler)
serverSocket.on('end', serverEndHandler)
serverSocket.on('connect', () => {
clientSocket.write([
'HTTP/1.1 200 Connection Established',
'Proxy-agent: Node-VPN',
].join('\r\n'))
clientSocket.write('\r\n\r\n') // empty body
// "blindly" (for performance) pipe client socket and destination socket between each other
serverSocket.pipe(clientSocket, {end: false})
clientSocket.pipe(serverSocket, {end: false})
})
} else {
clientSocket.end('HTTP/1.1 400 Bad Request\r\n')
clientSocket.destroy()
}
})
I tested this code with Firefox Proxy Settings (it even asks for username and password!). I entered IP address of machine where this code is runned and 9191 port as you can see in the code. I also set "Use this proxy server for all protocols". I run this code locally and on VPS - in both cases works!
You can test your NodeJS proxy with curl:
curl -x http://username:password#127.0.0.1:9191 https://www.google.com/
I have created a http/https proxy with the aid of the http-proxy module: https://gist.github.com/ncthis/6863947
Code as of now:
var fs = require('fs'),
http = require('http'),
https = require('https'),
httpProxy = require('http-proxy');
var isHttps = true; // do you want a https proxy?
var options = {
https: {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('key-cert.pem')
}
};
// this is the target server
var proxy = new httpProxy.HttpProxy({
target: {
host: '127.0.0.1',
port: 8080
}
});
if (isHttps)
https.createServer(options.https, function(req, res) {
console.log('Proxying https request at %s', new Date());
proxy.proxyRequest(req, res);
}).listen(443, function(err) {
if (err)
console.log('Error serving https proxy request: %s', req);
console.log('Created https proxy. Forwarding requests from %s to %s:%s', '443', proxy.target.host, proxy.target.port);
});
else
http.createServer(options.https, function(req, res) {
console.log('Proxying http request at %s', new Date());
console.log(req);
proxy.proxyRequest(req, res);
}).listen(80, function(err) {
if (err)
console.log('Error serving http proxy request: %s', req);
console.log('Created http proxy. Forwarding requests from %s to %s:%s', '80', proxy.target.host, proxy.target.port);
});
The node-http-proxy docs contain examples of this. Look for "Proxying to HTTPS from HTTPS" at https://github.com/nodejitsu/node-http-proxy The configuration process is slightly different in every browser. Some have the option to use your proxy settings for all protocols; some you need to configure the SSL proxy separately.
I am testing an XML-RPC set up in node.js and would like to test the server receiving calls and responding as well as the client making calls to the server and receiving a response in the same node session. If I run http.createServer and http.request with the same host and port, I get:
Error: ECONNREFUSED, Connection refused
at Socket._onConnect (net.js:600:18)
at IOWatcher.onWritable [as callback] (net.js:186:12)
Test code that will generate the errror:
var http = require('http')
var options = {
host: 'localhost'
, port: 8000
}
// Set up server and start listening
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'})
res.end('success')
}).listen(options.port, options.host)
// Client call
// Gets Error: ECONNREFUSED, Connection refused
var clientRequest = http.request(options, function(res) {
res.on('data', function (chunk) {
console.log('Called')
})
})
clientRequest.write('')
clientRequest.end()
While the code above will work if separated into two files and run as separate node instances, is there a way to get the above to run on the same node instance?
As it was mentioned above your http-server may not be running at the time you make a request. Using setTimeout is completely wrong. Use the callback parameter in listen method instead:
var http = require('http')
var options = {
host: 'localhost'
, port: 8000
}
// Set up server and start listening
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'})
res.end('success')
}).listen(options.port, options.host, function() {
// Client call
// No error, server is listening
var clientRequest = http.request(options, function(res) {
res.on('data', function (chunk) {
console.log('Called')
})
})
clientRequest.write('')
clientRequest.end()
});
Your HTTP server probably isn't fully loaded and operational at the time when you are doing your request to it. Try wrap your client request with setTimeout to give your server a time to set up, for example like this:
var http = require('http')
var options = {
host: 'localhost'
, port: 8000
}
// Set up server and start listening
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'})
res.end('success')
}).listen(options.port, options.host)
setTimeout(function() {
// Client call
// Shouldn't get error
var clientRequest = http.request(options, function(res) {
res.on('data', function (chunk) {
console.log('Called')
})
})
clientRequest.write('')
clientRequest.end()
}, 5000);