├── .gitignore ├── .github └── FUNDING.yml ├── .travis.yml ├── package.json ├── LICENSE ├── example.js ├── test └── test1.test.js ├── index.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: aminadav 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "8" 4 | cache: 5 | directories: 6 | - "node_modules" 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "run-middleware", 3 | "version": "0.6.6", 4 | "description": "NodeJS module to execute your Express endpoints (middlewares) from your code. This module will let you laucnch manually all your middleware. It is simulate a client calling to your rest API's. It is not using a network connections", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "jest" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "lodash": "" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/aminag/node-run-middleware" 17 | }, 18 | "devDependencies": { 19 | "express": "^4.16.3", 20 | "jest": "^23.0.1" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright (c) 2018, Aminadav Glickshtein 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | -------------------------------------------------------------------------------- /example.js: -------------------------------------------------------------------------------- 1 | /* 2 | Manual pass cookies to middleware 3 | Any property you pass to runMiddleware options argument, will be passed to the middleware request variable. 4 | 5 | In this example we passing cookies 6 | */ 7 | app.get("/see_cookie", function(req, res) { 8 | // This route show cookie1 9 | res.send({ cookie_status: req.cookies.cookie1 }); 10 | }); 11 | app.runMiddleware( 12 | "/see_cookie", 13 | { cookies: { cookie1: "this-is-the-cookie" } }, 14 | function(code, data, headers) { 15 | console.log(data); // it will be show 'this-is-the-cookie' 16 | } 17 | ); 18 | 19 | /* 20 | For automatically pass all the arguments from current middleware, 21 | to other middleware, you can call `req.runMiddleware` inside a middleware 22 | As you can see, the module keep the cookies and the header 23 | */ 24 | 25 | app.get("/runItInsideMiddleware", function(req, res) { 26 | console.log( 27 | "we simulate a cookies from the client, and call to another middle ware" 28 | ); 29 | req.cookies.cookie1 = true; 30 | 31 | /* when executing req.runMiddleware: cookies & and other data will be forwarded by default */ 32 | req.runMiddleware("/see_cookie", (code, data) => { 33 | res.send(data); // The cookie will be true 34 | }); 35 | }); 36 | 37 | app.runMiddleware("/runItInsideMiddleware", function(code, data, headers) { 38 | console.log(data); // it will be show true 39 | }); 40 | 41 | /* For more examples, and question, please use the issues tab in GitHub 42 | https://github.com/AminaG/node-run-middleware/issues 43 | */ 44 | -------------------------------------------------------------------------------- /test/test1.test.js: -------------------------------------------------------------------------------- 1 | var express = require("express"); 2 | var AddRunMiddleware = require("../"); 3 | 4 | test("test redirect", done => { 5 | var app = express(); 6 | AddRunMiddleware(app); 7 | app.get("/customRedirectCode", function(req, res) { 8 | res.redirect("http://github.com"); 9 | }); 10 | app.runMiddleware("/customRedirectCode", {}, function callback( 11 | code, 12 | data, 13 | headers 14 | ) { 15 | try { 16 | expect(code).toEqual(301); 17 | expect(headers.location).toEqual("http://github.com"); 18 | done(); 19 | } catch (err) { 20 | done(err); 21 | } 22 | }); 23 | }); 24 | 25 | test("test custom redirect", done => { 26 | var app = express(); 27 | AddRunMiddleware(app); 28 | app.get("/customRedirectCode", function(req, res) { 29 | res.redirect(302, "http://github.com"); 30 | }); 31 | app.runMiddleware("/customRedirectCode", {}, function callback( 32 | code, 33 | data, 34 | headers 35 | ) { 36 | try { 37 | expect(code).toEqual(302); 38 | expect(headers.location).toEqual("http://github.com"); 39 | done(); 40 | } catch (err) { 41 | done(err); 42 | } 43 | }); 44 | }); 45 | 46 | test("test route with id", done => { 47 | var app = express(); 48 | AddRunMiddleware(app); 49 | app.get("/get-user/:id", function(req, res) { 50 | res.send({ user: req.params.id, name: "Moyshale" }); 51 | }); 52 | 53 | app.runMiddleware("/get-user/20", {}, function(code, data) { 54 | try { 55 | expect(code).toEqual(200); 56 | expect(data).toEqual({ user: "20", name: "Moyshale" }); 57 | done(); 58 | } catch (err) { 59 | done(err); 60 | } 61 | }); 62 | }); 63 | 64 | test("test passing cookies", done => { 65 | var app = express(); 66 | AddRunMiddleware(app); 67 | 68 | app.get("/see_cookie", function(req, res) { 69 | // This route show cookie1 70 | res.send({ cookie_status: req.cookies.cookie1 }); 71 | }); 72 | app.runMiddleware( 73 | "/see_cookie", 74 | { cookies: { cookie1: "this-is-the-cookie" } }, 75 | function(code, data, headers) { 76 | try { 77 | expect(data).toEqual({ cookie_status: "this-is-the-cookie" }); 78 | done(); 79 | } catch (err) { 80 | done(err); 81 | } 82 | } 83 | ); 84 | }); 85 | 86 | test("test res.set", done => { 87 | var app = express(); 88 | AddRunMiddleware(app); 89 | 90 | app.get("/stuff", function(req, res) { 91 | res.set({ 'cache-control': 'free for all' }).send(); 92 | }); 93 | app.runMiddleware( 94 | "/stuff", 95 | {}, 96 | function(code, data, headers) { 97 | try { 98 | expect(headers['cache-control']).toEqual("free for all"); 99 | done(); 100 | } catch (err) { 101 | done(err); 102 | } 103 | } 104 | ); 105 | }); -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var _ = require("lodash"); 2 | 3 | var request = require("express/lib/request"); 4 | 5 | module.exports = function(app) { 6 | app.use((req, res, next) => { 7 | req.runMiddleware = (path, options, callback) => { 8 | if (_.isFunction(options)) { 9 | callback = options; 10 | options = {}; 11 | } 12 | options.original_req = req; 13 | options.original_res = res; 14 | app.runMiddleware(path, options, callback); 15 | }; 16 | next(); 17 | }); 18 | if (app.runMiddleware) return; // Do not able to add us twice 19 | 20 | app.runMiddleware = function(path, options, callback) { 21 | if (callback) callback = _.once(callback); 22 | if (typeof options == "function") { 23 | callback = options; 24 | options = null; 25 | } 26 | options = options || {}; 27 | options.url = path; 28 | var new_req, new_res; 29 | if (options.original_req) { 30 | new_req = options.original_req; 31 | for (var i in options) { 32 | if (i == "original_req") continue; 33 | new_req[i] = options[i]; 34 | } 35 | } else { 36 | new_req = createReq(path, options); 37 | } 38 | new_res = createRes(callback); 39 | app(new_req, new_res); 40 | }; 41 | 42 | /* end - APP.runMiddleware*/ 43 | }; 44 | 45 | function createReq(path, options) { 46 | if (!options) options = {}; 47 | var req = _.extend( 48 | { 49 | method: "GET", 50 | host: "", 51 | cookies: {}, 52 | query: {}, 53 | url: path, 54 | headers: {}, 55 | }, 56 | options 57 | ); 58 | req.method = req.method.toUpperCase(); 59 | // req.connection=_req.connection 60 | return req; 61 | } 62 | function createRes(callback) { 63 | var res = { 64 | _removedHeader: {}, 65 | _statusCode: 200, 66 | statusMessage: 'OK', 67 | get statusCode() { 68 | return this._statusCode 69 | }, 70 | set statusCode(status) { 71 | this._statusCode = status 72 | this.status(status) 73 | } 74 | }; 75 | // res=_.extend(res,require('express/lib/response')); 76 | 77 | var headers = {}; 78 | var code = 200; 79 | res.set = res.header = (x, y) => { 80 | if (arguments.length === 2) { 81 | res.setHeader(x, y); 82 | } else { 83 | for (var key in x) { 84 | res.setHeader(key, x[key]); 85 | } 86 | } 87 | return res; 88 | } 89 | res.setHeader = (x, y) => { 90 | headers[x] = y; 91 | headers[x.toLowerCase()] = y; 92 | return res; 93 | }; 94 | res.getHeader = (x) => headers[x]; 95 | // res.get=(x) => { 96 | // return headers[x] 97 | // } 98 | res.redirect = function(_code, url) { 99 | if (!_.isNumber(_code)) { 100 | code = 301; 101 | url = _code; 102 | } else { 103 | code = _code; 104 | } 105 | res.setHeader("Location", url); 106 | res.end(); 107 | // callback(code,url) 108 | }; 109 | res.status = res.sendStatus = function(number) { 110 | code = number; 111 | return res; 112 | }; 113 | res.end = res.send = res.write = function(data) { 114 | if (callback) callback(code, data, headers); 115 | // else if (!options.quiet){ 116 | // _res.send(data) 117 | // } 118 | }; 119 | return res; 120 | } 121 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NodeJS run-middleware 2 | 3 | NodeJS module to execute your Express endpoints (middlewares) from your code. This module will let you manually launch all your middleware. It is simulating a client calling your rest APIs, without using a network connection (your server does not even need to listen on a port). 4 | 5 | [![npm](https://img.shields.io/npm/dt/run-middleware.svg?maxAge=2592000)](https://www.npmjs.com/package/run-middleware) 6 | [![npm version](https://badge.fury.io/js/run-middleware.svg)](https://badge.fury.io/js/run-middleware) 7 | [![Join the chat at https://gitter.im/node-run-middleware/Lobby](https://badges.gitter.im/node-run-middleware/Lobby.svg)](https://gitter.im/node-run-middleware/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 8 | [![Build Status](https://travis-ci.org/Aminadav/node-run-middleware.svg?branch=master)](https://travis-ci.org/Aminadav/node-run-middleware) 9 | 10 | ## Why? 11 | 12 | Many times, your server and your client, need to execute the same functions. For example here is an endpoint to get user details: 13 | 14 | ```js 15 | app.get('/get-user/:id', (req, res) => { 16 | mysql.query('select * from users where id=?', [req.params.id], (err, rows) => { 17 | res.send({ 18 | user: rows[0] 19 | }); 20 | }); 21 | }); 22 | ``` 23 | 24 | Now you want to get the user details from your code. What should you do? 25 | 26 | ```js 27 | app.runMiddleware('/get-user/20', (_, body) => { 28 | console.log(`User details: ${body}`); 29 | }); 30 | ``` 31 | 32 | ## Installation 33 | 34 | ```sh 35 | npm i -S run-middleware 36 | ``` 37 | 38 | ```js 39 | const express = require('express'); 40 | const app = express(); 41 | const runMiddleware = require('run-middleware'); 42 | 43 | runMiddleware(app); 44 | ``` 45 | 46 | ## Support & Contributions 47 | 48 | * Pull requests, issues, and English proofreading are welcome on Github. 49 | * Question & support on StackOverflow using `run-middleware`tag. 50 | 51 | ## Change request paramaters 52 | 53 | As options you can pass the `query`, `body`, `method` and `cookies` parameters. 54 | 55 | ```js 56 | app.runMiddleware('/handler', { 57 | method: 'post', 58 | query: { 59 | token: 'tk-12345' 60 | }, 61 | body: { 62 | "action": "list", 63 | "path": "/" 64 | } 65 | }, (code, data) => { 66 | console.log(code, data); 67 | process.exit(0); 68 | }); 69 | ``` 70 | 71 | ## Auto pass cookies 72 | 73 | When you `runMiddleware` from another location, you don't have to pass all the parameters of the current middleware to the handler. 74 | 75 | ```js 76 | app.get('/middleware1', (req, res) => { 77 | req.runMiddleware( /* ... */ ); 78 | }) 79 | ``` 80 | 81 | ## Redirecting 82 | 83 | You can check if the middleware executed will redirect the request by checking the `code` and the `headers.location` fields. 84 | 85 | ```js 86 | app.runMiddleware('/this-middleware-will-response-as-redirect', (code, body, headers) => { 87 | if (code === 301 || code === 302) { // Redirect HTTP codes 88 | console.log('Redirect to:', headers.location); 89 | } 90 | }); 91 | ``` 92 | 93 | ## Changelog 94 | 95 | * v1.0.0 (25 June 2018) - 96 | * v0.6.1 (9 Sep 2016) - Supports response.redirect 97 | * v0.6.2 (10 Sep 2016) - Supports passing cookies and other variables to runMiddleware 98 | * v0.6.3 (11 Sep 2016) - Supports running middleware from others middleware, for automatically passing cookies and headers between middlewares. 99 | * v0.6.4 (13 Sep 2016) - Better documentation and examples 100 | 101 | ## Examples 102 | 103 | See the tests for further examples. 104 | 105 | - [Control V](https://ctrl.vi), [המבוך של שירת](https://maze.boti.bot) 106 | --------------------------------------------------------------------------------