Search code examples
node.jsjsonexpressjson-server

json-server does not use the code provided in the middleware file


I am using json-server to simulate some api calls responses for front-end development turns out that adding a middleware does not really work out in my case:

{
  "name": "my-app",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "concurrently -k \"json-server --watch api-faked/db.json --routes api-faked/routes.json --middlewares api-faked/middleware.js --ro\" \"vue-cli-service serve\"",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },

When starting:

[1]  INFO  Starting development server...
[0]
[0]   \{^_^}/ hi!
[0]
[0]   Loading api-faked/db.json
[0]   Loading api-faked/routes.json
[0]   Loading api-faked/middleware.js
[0]   Done
[0]

It seems that the middleware.js is considered by json-server, however, a simple example such as the middleware.js like below:

module.exports = (req, res, next) => {
    res.header('X-Hello', 'World')
    next()
}

Does not add any header to my response headers:

Request URL: http://localhost:3000/api/v1/operations/?code_like=adi
Request Method: OPTIONS
Status Code: 204 No Content
Remote Address: 127.0.0.1:3000
Referrer Policy: no-referrer-when-downgrade
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: authorization
Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE
Access-Control-Allow-Origin: http://localhost:8080
Connection: keep-alive
Content-Length: 0
Date: Thu, 18 Jul 2019 12:23:53 GMT
Vary: Origin, Access-Control-Request-Headers
X-Powered-By: Express

What am I missing here?

Side-note: actually removing the next from the middleware.js does not even alter anything, it's like even though the middlware has been added to the json-server configuration it seems not really run at any point in time.


Solution

  • The solution in my case was using the module style of json-server, which basically involves creating a js file and recreating router which is otherwise created automatically with the db.json and routes.json, unlike the automatic mode, it supports adding a middleware which can intercept pretty much everything.

    Example

    const fs = require('fs');
    const jsonServer = require('json-server');
    const path = require('path');
    const server = jsonServer.create();
    const defaultMiddleware = jsonServer.defaults();
    
    // It is recommended to use the bodyParser middleware before any other middleware in your application
    server.use(jsonServer.bodyParser);
    
    server.use(defaultMiddleware);
    
    // Define custom routes (routes.json)
    const routes = JSON.parse(fs.readFileSync(path.join(__dirname, 'routes.json')));
    server.use(jsonServer.rewriter(routes));
    
    // Add custom middleware before JSON Server router
    const customMiddleware = require(path.join(__dirname, 'middleware.js'));
    server.use(customMiddleware);
    
    // This is where `json-server`'s magic happens ;)
    const router = jsonServer.router(path.join(__dirname, 'db.json'));
    
    // Start the application by listening to port 3000,
    // Although this won't print the nice starting message you see when
    // running `json-server` as CLI command, it still runs the app correctly.
    server.use(router);
    server.listen(3000, () => {
        console.log('JSON Server is running')
    });
    

    With the structure of the folder api-faked being:

    • server.js
    • middleware.js
    • db.json
    • routes.json

    Instead of serving the application like that (in package.json):

    "serve": "concurrently -k \"json-server --watch api-faked/db.json --routes api-faked/routes.json --middlewares api-faked/middleware.js --ro\" \"vue-cli-service serve\"",

    it is now like this:

    "serve": "concurrently -k \"nodemon api-faked/server.js --watch api-faked/*.*\"

    I also use nodemon which restart the json-server if any change occurs in any of the given files (ie. --watch api-faked/*.*)

    I've been put on the right track thanks to the answer given in that GitHub issue: json-server does not use the code provided in the middleware file