Mock Server
Get a full REST API with zero coding in less than 30 seconds (seriously)
Created with <3 for front-end developers who need a quick back-end for prototyping and mocking.
Now also available as a VSCodeExtension thinker.mock-server
.
Table of contents
Getting started
Install Mock Server
npm install -g @r35007/mock-server
Create a routes.json
file with mock data.
{
"/hello": {
"mock": "hello World",
},
};
Start Mock Server
mock-server ./mock.json
Now if you go to http://localhost:3000/hello, you'll get
Hello World
Advantages
- A single response can be point to multiple route paths.
- Any file can be send as a response. (json, image, txt, etc..)
- Can set any value to globals and can be accessed at any point of time which also helps to share data between routes.
- The mock data can be maintained in different json files and urls which helps to organize your mock data
- The return response can be manipulated or overridden for a specific route by a middleware method.
- proxy routes can be used
Using JS Module
First install nodemon for watching changes
npm install -g nodemon
Create server.js
File
const { MockServer } = require("@r35007/mock-server");
const routes = {
"/route/1": {
mock: {
data: "data 1",
},
middlewares: ["log"],
},
"/route/2": {
mock: {
data: "data 2",
},
},
};
const middlewares = {
log: (req, res, next) => {
console.log(new Date()), next();
},
};
const injectors = {
"/route/2": {
delay: 3000,
},
};
const config = {
port: 4000,
};
const mockServer = new MockServer(routes, config, middlewares, injectors);
mockServer.launchServer();
Now go to terminal and type the following command to start the Mock Server.
nodemon server.js
Route Config
Create a routes.json file. Pay attention to start every route with /.
For Example:
routes.json
{
"/routeName, /routeName2": {
"delay": 2000,
"statusCode": 200,
"middlewares": ["loopMock"],
"fetch": "./myFile.json",
"mock": [{ "name": "foo" }, { "name": "bar" }],
"mockFirst": false
},
"/routeName3": {
"name": "foo",
"age": "bar",
"description": "Note: If `fetch` or `mock` is not available then it sends this whole object as a response."
}
}
Note : fetch
can be either string
type or AxiosRouteConfig
type.
see Fetch Data From URL for more configuration.
Set Delay Response
delay
helps you to set a custom delay to your routes.
Note : The delay yo set must be in milliseconds and of type number
{
"/user/1": {
"mock": {
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere@april.biz"
},
"delay": 3000
}
}
The above /user/1
route returns the response in a delay of 3 seconds.
Set Custom StatusCode
statusCode
helps you set a custom statusCode to your routes.
It must be of type number and between 100 to 600.
{
"/user/1": {
"mock": {
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere@april.biz"
},
"statusCode": 500
}
}
The above /user/1
route returns the response with a 500
statusCode
Fetch Data From URL
fetch
helps you get data from url.
The url can either be a http server or a local file server.
Fetch File
Give a absolute or a relative path to fetch any file and get as a response.
Note: The given relative path will be relative to config.rootPath
.
{
"/banner": {
"fetch": "./assets/banner.jpg"
}
}
Custom Fetch Options
You can also give a fetch as a axios request object with custom options.
{
"/customUsers/:id": {
"fetch": {
"url": "https://jsonplaceholder.typicode.com/users",
"params": "$params",
"method": "GET"
}
}
}
Note: The to pass any options from the route set the option value as $<option Name>
Use Fetch as Proxy
By directly giving a url it acts like a proxy.
It sends all the options like prams, query params, headers, data etc.. from the mock route
{
"/customComments/:id?": {
"fetch": "https://jsonplaceholder.typicode.com/comments"
},
"/posts": {
"fetch": "https://jsonplaceholder.typicode.com/:routePath"
}
}
Note: /:routePath
will prepends the route to the url.
Now you could use any routing provided by the "https://jsonplaceholder.typicode.com/posts"
..
For example: You could use the following.
http://localhost:3000/customComments
http://localhost:3000/customComments/1
http://localhost:3000/customComments?postId=1
Custom Mock
By default the Mock Server try's to fetch the data from fetch
url.
If it fails then it tries to get it from mock
.
Set mockFirst
to true to get the mock first.
If the mock is not available then it tries a to get data from fetch
url.
{
"/customComments/:id?": {
"fetch": "https://jsonplaceholder.typicode.com/comments",
"mock": [
{ "id": 1, "username": "foo" },
{ "id": 2, "username": "bar" }
],
"mockFirst": true
}
}
Add Middlewares
You can add n number of middlewares to a route which helps you to manipulate or log the data.
First Create a middlewares.js
file.
exports.log = (req, res, next) => {
console.log(new Date());
next();
};
exports.wrapper = (req, res, next) => {
const wrapperResponse = {
message: "Successful",
result: res.local.data,
};
res.send(wrapperResponse);
};
routes.json
{
"/posts/:id": {
"fetch": "https://jsonplaceholder.typicode.com/posts",
"middlewares": ["log", "wrapper"]
},
"/comment": {
"fetch": { "url": "https://jsonplaceholder.typicode.com/comments/1" },
"middlewares": ["log"]
}
}
Note: A middleware must be available at the name of the middlewares given in routes.json
Now in server.js
const { MockServer } = require("@r35007/mock-server");
new MockServer("./routes.json", undefined, middlewares.js).launchServer();
Now when you go to http://localhost:3000/posts/1
, you can see the new data og in console and also wrap's the response with the object.
But When you go to http://localhost:3000/comment
, you can only see the date log and will not be wrapped with the object.
Default Middlewares
We also provide a two default middlewares.
loopMock
setting middleware to loopMock helps to send you a looped response one after the other in the mock array for each url hit.
example:
{
"/loopMock": {
"middlewares": ["loopMock"],
"mock": ["response1", "response2]
}
}
Now go and hit http://localhost:3000/loopMock
. For the first hit you get response1
as a response and for the second hit you get response2
as a response and its loops through each element in the mock array for each url hit.
groupMock
setting middleware to groupMock helps to send you a response that matched the route path from the mock
example:
{
"/name/:id": {
"middlewares": ["groupMock"],
"mock": {
"/name/1": "name1",
"/name/2": "name2"
}
}
}
Now go and hit http://localhost:3000/name/1
, you get name1
as a response.
Now go and hit http://localhost:3000/name/2
, you get name2
as a response.
Now go and hit http://localhost:3000/name/3
, since id 3
is not available it send you name1
as a response.
crudMock
This middleware handles all the crud operations of the given mock.
Note : the mock must of type Array of objects and must contain a unique value of attribute id
. Following are the operations performed by this method.
routes.json
{
"/posts/:id?": {
"mock": [
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident o",
"body": "quia et suscipit\nsuscipit recusandae "
},
{
"userId": 1,
"id": 2,
"title": "qui est esse",
"body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor"
}
],
"middleware": ["crudMock"]
}
}
api.http
## // returns all posts data
GET http://localhost:3000/posts
## // returns all posts data that has userId equals 1
GET http://localhost:3000/posts?userId=1
## // returns only post that has id equals 1
GET http://localhost:3000/posts/1
###
POST http://localhost:3000/posts
content-type: application/json
{
"userId": 2,
"title": "Galactic Star"
}
## // Note : `id` must not be provided. It will be auto generated
POST http://localhost:3000/posts
content-type: application/json
[
{
"userId": 2,
"title": "Star wars"
},
{
"userId": 2,
"title": "Avengers"
}
]
###
PUT http://localhost:3000/posts
content-type: application/json
{
"userId": 2,
"id": 1,
"title": "Updated title"
}
## // delete only post that has id equals 1
DELETE http://localhost:3000/posts/5
Injectors
Injectors helps to inject a Route Configs explicitly.
This also helps to provide a common route configs.
Injector uses path-to-regexp
pattern recognition to set config for multiple routes.
Inject Route Configs
Here we are explicitly injecting delay
, middlewares
, statusCode
to the /posts
route.
You can any route configs to a specific or to a group of routes using Injectors.
example :
routes.json
{
"/posts": {
"fetch": { "url": "https://jsonplaceholder.typicode.com/posts" }
},
"/comments/1": {
"fetch": { "url": "https://jsonplaceholder.typicode.com/comments/1" },
"middlewares": ["crudMock", "log"]
},
"/comments/2": {
"delay": 3000,
"fetch": { "url": "https://jsonplaceholder.typicode.com/comments/2" }
},
"/comments/3": {
"fetch": { "url": "https://jsonplaceholder.typicode.com/comments/3" }
}
}
injectors.json
{
"/posts": {
"delay": 2000,
"middlewares": ["log", "counter", "curdMock"],
"StatusCode": 300
},
"/comments/:id?": {
"delay": 2000,
"middlewares": ["log"]
}
}
Override Existing Route Configs
Setting override
flag to true helps to override the existing config of that route.
For example :
injectors.json
{
"/comments/1": {
"override": true,
"middlewares": ["...", "timer"]
},
"/comments/2": {
"override": true,
"delay": 2000
}
}
Note: Use ["..."]
If you want to add the existing middlewares in line when overriding.
Make sure the middlewares are available in the middlewares.js
in the given middlewares name.
Common Route Configs
Using wildcards you can set a common route configs to all the routes.
/(.*)
- matches all the routes.
For example :
injectors.json
{
"/posts": {
"delay": 2000
},
"/(.*)": {
"override": true,
"middlewares": ["log", "..."],
"statusCode": 200,
"delay": 1000
},
"/comments/1": {
"delay": 0,
"override": true
}
}
Now all the Routes will have a delay of 1 second, "log"
middleware is appended to all routes and statusCode
will be 200.
Make sure you give (.*)
at the end of the injectors.json
object to set route configs to all the routes.
Store Data
Using res.locals.store
you could store any value and can be shared across any routes.
This also helps to manipulate the response in many ways. Lets see a simple counter Example :
server.js
const { MockServer } = require("@r35007/mock-server");
const routes = {
"/counter": {
middleware: ["countIncrement"],
},
};
const middlewares = {
countIncrement: (req, res) => {
let count = res.locals.store.get(req.path);
res.locals.store.set(req.path, count++);
res.send(count);
},
};
const mockServer = new MockServer(routes, undefined, middlewares);
mockServer.setStore("count", 5);
mockServer.launchServer();
nodemon server.js
From the above the count increases on each hit of the endpoint.
Config
you can provide your own config by passing the config object in the MockServer
constructor. For Example :
server.js
:
const config = {
port: 3000,
rootPath: "./",
baseUrl: "/",
staticUrl: "",
routeRewrite: {},
excludeRoutes: [],
reverseRouteOrder: false,
throwError: false,
};
new MockServer("./routes.json", config).launchServer();
Default Routes
API
MockServer
This is a constructor to initialize the routes, config, middlewares, Injectors.
const { MockServer } = require("@r35007/mock-server");
const mockServer = new MockServer(
"./routes.json",
"./config.json",
"./middlewares.js",
"./injectors.json"
).launcherServer();
mockServer.launchServer();
Params
Name | Type | Required | Description |
---|
routes | string / object | No | This object generates the local rest api. |
config | string / object | No | This object sets the port, common middleware and delay |
middlewares | string / object | No | Here you initialize the needed custom middlewares |
injectors | string / object | No | Helps to inject a route configs for the existing routes |
launchServer
It validates all the params in the MockServer, loads the resources and starts the server.
mockServer.launchServer();
createExpressApp
Returns the instance of the express.Application - helps set any external routes or middleware.
const app = mockServer.createExpressApp();
startServer
Returns a Promise of Server
. - helps to start the app server externally
const server = await mockServer.startServer(3000);
stopServer
Returns a Promise of Boolean. - helps to stop the app server externally
const isStopped = await mockServer.stopServer();
resetServer
Clears out all values and resets the server for a fresh start
mockServer.resetServer();
loadResources
mockServer.loadResources();
createRoute
mockServer.createRoute(routePath, routeConfig);
Params
Name | Type | Required | Default | Description |
---|
routePath | string | YES | | Your custom Route Path |
routeConfig | object | NO | {} | Set your Mock data here |
createDefaultRoutes
Create a default home and routes list api
mockServer.createDefaultRoutes();
setData
set the routes, config, middlewares, injectors
mockServer.setData(routes, config, middlewares, injectors);
mockServer.setRoutes(routes);
mockServer.setConfig(config);
mockServer.setInjectors(injectors);
mockServer.setMiddlewares(middlewares);
Params
The same as the MockServer
Get Data
returns the valid Routes, config, injectors, middlewares
let { routes, config, injectors, middlewares } = mockServer.data;
routes = mockServer.routes;
config = mockServer.config;
injectors = mockServer.injectors;
middlewares = mockServer.middlewares;
Store
mockServer.setStore(key, value);
mockServer.getStore(key);
Variables
Other useful variables.
const app = mockServer.app;
const server = mockServer.server;
const router = mockServer.router;
const availableRoutes = mockServer.availableRoutes;
const isServerLaunched = mockServer.isServerLaunched;
const isExpressAppCreated = mockServer.isExpressAppCreated;
const isServerStarted = mockServer.isServerStarted;
const isResourcesLoaded = mockServer.isResourcesLoaded;
const isDefaultsCreated = mockServer.isDefaultsCreated;
Validators
These methods returns a valid data.
const valid_config = mockServer.getValidConfig(config);
const valid_injectors = mockServer.getValidInjectors(injectors);
const valid_routes = mockServer.getValidRoutes(routes);
const valid_middlewares = mockServer.getValidRoutes(middlewares);
const valid_routePaths = mockServer.getValidRoutePaths(routePaths);
const valid_routePath = mockServer.getValidRoutePath(routePath);
Path Check
These other useful methods.
const parsedUrl = mockServer.parseUrl(url);
const isPathExist = mockServer.isPathExist(path);
const isDirectoryExist = mockServer.isDirectoryExist(path);
const isFileExist = mockServer.isFileExist(path);
transformHar
The HTTP Archive format, or HAR, is a JSON-formatted archive file format for logging of a web browser's interaction with a site. The common extension for these files is .har. Wikipedia.
Using this now it is very much simpler to mock your prod data in ease. Follow the steps to mock your prod Data.
Step 1 : Open Chrome and developer tools
Step 2 : Start the network listening and run your app which you like to mock the data
Step 3 : click the export HAR download icon and save it as a localhost.json
.
Step 4 : Now do the following code in index.js
const { MockServer } = require("@r35007/mock-server");
const localhostData = require("./localhost.json");
const mockServer = new MockServer();
const mock = mockServer.transformHar(
"./localhost.har",
{routesToLoop:["*"], routesToGroup:["posts/:id"]}
(entry, statusCode, route, response) => {
return { [route]: response };
},
(generatedMock) => generatedMock
);
mockServer.setData(mock);
mockServer.launchServer();
Params
Name | Type | Required | Default | Description |
---|
harData | object/string | No | {} | This object generates the local rest api. |
config | object | No | {} | Here you can give list of routesToLoop and routesToGroup |
entryCallback | Function | No | undefined | This method is called on each entry of the har data |
finalCallback | Function | No | undefined | This method is at the end of the final generated mock |
getJSON
return all the json files data to a combined json data from the given path
const mock = mockServer.getJSON(directoryPath, excludeFolders, true);
Params
Name | Type | Required | Default | Description |
---|
directoryPath | string | NO | "./" | Provide the filepath or the directory path |
excludeFolders | object | No | [] | list of path or filename to exclude from requiring json files |
recursive | boolean | No | true | If true, it search's for all nested folder |
getFilesList
returns the list of all fileName, extension and its path from the given folder.
const mock = mockServer.getFilesList(directoryPath, excludeFolders, true);
Params
Name | Type | Required | Default | Description |
---|
directoryPath | string | NO | "./" | Provide the filepath or the directory path |
excludeFolders | object | No | [] | list of path or filename to exclude from requiring json files |
recursive | boolean | No | true | If true, it search's for all nested folder |
Author
Sivaraman - sendmsg2siva.siva@gmail.com
License
MIT