You can hook an Express router into a plain node.js http server while still allowing other routing for routes that aren't handled by your router. You do, however, have to create an Express app and use that object, but that Express object doesn't have to take over the web server, it can just be used only for your route. Here's how it would work:
Code for a user of your API:
// generic node.js http server created by the user of your API
const http = require('http');
const server = http.createServer(function(request, response) {
// the user of your API has to insert a handler here
// that gives your API a first crack at handling the http request
libRouter(request, response, function() {
// if this callback is called, then your API did not handle the request
// so the owner of the web server can handle it
});
});
server.listen(80);
Your API code:
// you create your desired Express router
const express = require('express');
const router = express.Router();
// define the handlers for your router in the usual express router fashion
router.get("/test", function(req, res) {
res.send("Custom API handled this request");
});
// your create an Express instance
const app = express();
// hook your router into the Express instance in the normal way
app.use("/api", router);
// define a handler function that lets the express instance
// take a crack at handling an existing http request without taking over the server
function apiHandler(req, res, done) {
// call app.handle() to let the Express instance see the request
return app.handle(res, res, done);
}
In this manner, your use of Express and an express router is entirely internal to your code. All you need is for an existing node.js http server to call your function apiHandler(req, res, doneFn)
with the right arguments. The done
callback will be called only if your api did not handle the request in which case the user of your API should then handle the request.
This example defines a route for /api/test
and you can define as many /api/xxx
routes as you want. You can even use multiple routers on the app
object each with different prefix paths and it will check all of them.
For the record, I tried using only a router without the Express app object. I sort of got it to work, but there were issues because the req
and res
objects being passed to the router
are not the expected enhanced Express versions of req
and res
(with extra methods added by Express). This seemed likely to cause trouble. To get around that safely, you'd have to reverse engineer and then duplicate a bunch of Express app object code. Since I saw no reason to actually duplicate all that when you could just use the existing app
object and let it do it's normal thing, I figured it's best to do so. And, the use of Express or the Express router is entirely internal to your own API module, invisible to the outside world so there's no harm in using the existing code that works.