How to emulate traffic in express.js - node.js

I have a node express server responding to http traffic:
const http = require("http");
const express = require("express");
const app = express();
const server = http.createServer(app);
app.use(function(req,res,next){
console.log(`logging: req: ${util.inspect(req)}`);
next();
});
and all that works fine. I'd like to have a program on my node server inject emulated http traffic into the express stack, without a network connection. I can't just magic up a (req,res) pair and call a middleware function like the one in app.use above, because I don't have a next to give it, and my req and res will not be the ones next passes on to the next middleware in the stack.
Edit: What I actually have is a websocket connection sending data packets of a different format, different data contents from http traffic that can also carry the same information. I can take those websocket packets and build from those a request that is in the same format that the http traffic uses. I would like to pass that transformed request through the express http middleware stack and have it processed in the same way. Going all the way back to create an http request having just dealt with a ws request seems a bit far.
What's the simplest way to emulate some traffic, please? Can I call a function on app? Call some express middleware, or write a middleware of my own to inject traffic? Call a function on server?
Thanks!

Emulation traffic by calling some Express.js internal functions isn't the right way. Much easier is to trigger the server by HTTP request from the same process
const http = require('http');
const util = require('util');
const express = require('express');
const app = express();
const server = http.createServer(app);
app.use(function(req, res, next) {
console.log(`logging: req: ${util.inspect(req)}`);
next();
});
const port = 8081;
server.listen(port);
http.request({ port }).end();
From your question
I'd like to have a program on my node server inject emulated http traffic into the express stack, without a network connection
Can you clarify, why without a network connection?

A few things:
You need to make an endpoint
You need to host your server somewhere
You need something to send requests to your server
Express provides you a way to receive requests (req, res) (might be from a browser, might not be), perform some operations, and return responses (req, res) to the requester.
The expression
app.use(function(req,res,next){
console.log(`logging: req: ${util.inspect(req)}`);
next();
});
is actually a middleware function. This will take every request to your server and change the request object created by express into a string, and print it in your server log.
If you want a testable endpoint, you would add this to the bottom of the snippet you posted
app.get('/test', function (req, res) {
res.json({success:true})
})
This tells your app to allow GET requests at the endpoint /test
Next you're going to need to host your express server somewhere you can send requests to it. Your local machine (localhost) is a good place to do that. That way, you don't need an internet connection.
Pick a port you want to host the server on, and then it will be reachable at http://localhost:<Your Port>.
Something like this will host a server on http://localhost:3000. Add this below the route we declared above:
server.listen(3000, function() {
console.log('Server running on port 3000');
});
Finally, you'll need a way to send requests to the server on localhost. Postman is a great tool for testing express routes.
I would suggest installing Postman and using that to emulate http traffic.
Once your server is running, open postman and send a GET request to your server by entering the server address and port, and hitting the blue send button (You'll be sending the request to http://localhost:3000/test).
Here's an image of what postman should look like if all goes well
You should also see your middleware fire and print out the request object in your terminal.
Good Luck!

Related

HTTP server gives error when responses some requests

I am making an express.js server to store pictures.
const express = require('express');
const app = express();
app.get('/*', (request, response) =>
{
response.sendFile(__dirname + '/data' + request.path);
});
app.listen(9999);
console.log('Server started on port 9999');
And I have a problem. If I type http://127.0.0.1:9999/vehicles/boats/dinghy.png into browser, I get a picture, but when I type https://127.0.0.1:9999/main/avatar.png I get This site can’t provide a secure connection 127.0.0.1 sent an invalid response. Both files do exist, but one of them is sent correctly, but another one gives an error. What can it be caused by?
Your second request is sent via https. As you're not providing a valid certificate for localhost at your express app, the browser will give you a hint about this.

what is the difference between using Express GET method and HTTPS GET method in the below code?

const express = require("express");
const app = express();
const https = require("https");
app.get("/", function (req, res){
var url = "https://***";
https.get(url, function(response){
console.log(response);
});
res.send("server running");
});
Express is really just a layer on top of http.
I reckon those following links might help you out, this question has been asked.
what's the technical difference between express and http, and connect for that matter
Difference between a server with http.createServer and a server using express in node js
app.get() registers a listener for a specific INCOMING http request path on a local Express server.
https.get() makes an OUTBOUND https request TO some other https server to fetch content from that other server.
And, obviously, the https.get() is using https, not http. The app.get() could be listening for either - it depends upon how the server it is part of is started (as an http server or an https server) which the code you have in your question does not show.

Proxy HTTPS with HTTP in Node.js express

I wrote an express app as an HTTP proxy, to intercept and analyse some of the network traffic. The parts of traffic my app is interested in are all HTTP, however I still want my app to proxy HTTPS so users can use it without extra setting.
My express app is created with a HTTP server. When testing, I changed the proxy setting in Chrome with SwitchyOmega, to proxy HTTPS connections with HTTP. HTTP works well, But my express app couldn't get these proxy requests for HTTPS.
So I wrote a simple TCP proxy to check on them, and find that they're like this:
CONNECT HOSTNAME:443 HTTP/1.1
Host: HOSTNAME
Proxy-Connection: keep-alive
User-Agent: MY_AGENT
ENCRYPTED HTTPS
I believe these requests are HTTP, but why express isn't receiving them?
For sure if I change the browser proxy setting to ignore HTTPS, the app works well. But I do want to know if there is any workaround that I can use to proxy all protocols with HTTP and only one port.
THX.
UPDATE- code from my express app
app.use('*', function (req, res, next) {
// print all the request the app receive
console.log('received:', req.url)
})
app.use(bodyParser.text({type: '*/*'}))
app.use(cookieParser())
app.use(logger('dev'))
app.use(express.static(path.join(__dirname, 'public')))
// serve web pages for my app, only the request targeting my server
// is handled here(right IP and port), proxy request gets handled after this.
app.use('/', internalRoute)
// analyse the part I want
app.use('/END_POINT_I_WANT', myRoute)
// handle proxy requests
app.use('*', function (req, res, next) {
// proxy the request here
})
The problem is, my first middleware, which is used to display all the requests the app receive, can't catch the HTTPS proxy requests wrapped in HTTP described above. And of course the middleware I used as proxy can't catch them either.
UPDATE-tried node-http-prxoy, no luck
var httpProxy = require('http-proxy')
, http = require('http')
, fs = require('fs')
var options = {target: 'http://127.0.0.1:8099'}
, proxy = httpProxy.createServer(options)
http.createServer(function (req, res) {
console.log(req.url)
proxy.web(req, res)
}).listen(5050)
With the above code, and browser setting to proxy all protocols with HTTP, it works the same as my express app. HTTPS proxy requests gets ERR_EMPTY_RESPONSE, and nothing on the console.
With the below options, it seems that I have to change the proxy protocol to HTTPS, which I'd rather not use, at least for now. And I get ERR_PROXY_CERTIFICATE_INVALID for my self-signed certs...
var options = { secure: true
, target: 'http://127.0.0.1:8099'
, ssl: { key: fs.readFileSync('cert/key.pem', 'utf8')
, cert: fs.readFileSync('cert/server.crt', 'utf8')
}
}
UPDATE- pin point the problem to the 'connect' event listener
Through some searching, I found this post helpful.
It pointed out that the http server doesn't have a listener for the connect event. I tried the code in the post, works. But as the last comment of that post mentioned, my app serves as a proxy in order to get the data, it then proxy the request to another proxy in order to go over the GreatFireWall.
The process is like : BROWSER -> MY_APP -> ANOTHER_PROXY -> TARGET.
Without the ANOTHER_PROXY, which is an HTTP proxy, it works well for both HTTP and HTTPS. However I failed to chain them all up. The ANOTHER_PROXY I use supports HTTPS over HTTP.
It's hard to see what might be wrong, since you haven't posted any code.
However, if you just want to create a simple proxy that supports HTTP and HTTPS, i think that you should consider using a module like node-http-proxy.
Their readme has example code for the most common scenarios, and it sounds like it will support your needs fine.

In Node.js is it possible to use parts of Connect with standard node HTTP server?

I have a node.js app which i need to add more complexity to at this point. Connects middleware is perfect for what I want to do and cleaner than "if else" logic BUT i dont want the level of abstraction Connect provides from a server perspective (i want very low level granular control over http headers and http response logic). So my question is can i use Connects middleware next() type functionality within a standard
http.createServer(function (req, res) {}).listen(port)
type block?
hope this makes sense. any simple example code would be great.
thx
Ok, so I guess I was looking at this the wrong way.
I can wrap my existing code inside a Connect server pretty easily and still use the http interface. i.e.
var connect = require('connect');
var http = require('http');
var app = connect()
app.use( function myMiddleWare(req, res, next ){
// my preexisting Node HTTP interface code.
//obviously I can use modules to make this cleaner
next();
});
var server = app.listen(port);

Use Node.js as workaround for Cors

Using Nodejs and Express 4, I am trying to do a post on
my express server which in turn will take inputs from browser
and do a post on external server as a CORS workaround.
This the route to my server:
app.post('/api', api.postme);
This is my api.js file.
exports.postme = function (req, res, next) {
res.send("hello Apis");
};
For Example an external server:
https://website/NoJSONPHere/
params: page=1, query="frogs"
Is it possible to do this??
Use a second node server, host it somewhere in the cloud.
Then have mobile (blocked) app make calls against your server.
So,
your app> your server > their server.
Avoids,
your app > their server.
The reason this works is server to server connections or not blocked.
Browser to server is sometimes blocked.

Resources