1

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!

emrys57
  • 6,679
  • 3
  • 39
  • 49
  • With superagent or any other Node lib that does requests. *I can't just magic up a (req,res) pair* - no, you can, they could be mocked objects, but since the middleware is anonymous function, it's impossible to test it apart from Express. – Estus Flask Jun 14 '18 at 19:44
  • Yes, I can execute one middleware function alone with a magicked (req, res), but I cannot have that pass through the whole stack. Thanks. – emrys57 Jun 15 '18 at 07:30
  • Ok, let me rephrase your edit if I get it right. You want to reuse your application logic written in Express middleware/routes and call it from WebSocket handler. It seems to you, that creating HTTP request is overkill, but still, I strongly discourage you from interacting with Express else then via HTTP requests. – janfabian Jun 15 '18 at 08:21
  • Yes, you cannot pass through the stack. But it's unclear what is the purpose at all. The question doesn't say why you need that. Is it about testing? Then this is about testing methodology. Testing a function alone is unit test. Testing the server with fake requests is integration/e2e test. Usually you start with unit tests. – Estus Flask Jun 15 '18 at 08:50
  • @estus I think that emrys would like to call something this `websocket.on("message", data => app.passThroughMiddleware(transformFromWSformatToHTTP(data)))` – janfabian Jun 15 '18 at 08:55
  • 1
    @janfabian Makes sense, I had a suspicion that the mention of WS refer to that. It's a dupe of https://stackoverflow.com/questions/33090091/is-it-possible-to-call-express-router-directly-from-code-with-a-fake-request then. – Estus Flask Jun 15 '18 at 09:02
  • jestus, janfabian, thanks very much for your help. Yes, you are right, this is a duplicate of that question. I hadn't found that when I searched. I will investigate router.handle and decide whether to rely on the private interface or choose a different approach entirely. Janfabian, I ticked your answer. Estus, Thanks! – emrys57 Jun 15 '18 at 09:09

2 Answers2

1

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?

janfabian
  • 394
  • 2
  • 8
0

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!