aminadav / node-run-middleware Goto Github PK
View Code? Open in Web Editor NEWNodeJS Express module to simulate URL requests, for internal executing REST API's
Home Page: https://github.com/aminag/node-run-middleware
License: ISC License
NodeJS Express module to simulate URL requests, for internal executing REST API's
Home Page: https://github.com/aminag/node-run-middleware
License: ISC License
This module do not really need Lodash, it use Lodash only for one or two functions. If you want me to remove this dependency please comment.
I want that the new middleware will get the same cookies & headers
RunMiddleware creates a strimmed down response object that prevents SSR applications from forwarding a HTTP status code. We hit a case with Angular, where setting the correct status code for some pages works in Express, but fails when the same resource is retrieved via runMiddleware.
In general, I don't think supporting a full Response object would slow down or add excessive complexity to RunMiddleware, but at least provide methods and entries for statusCode and statusMessage.
function createRes(callback) {
var res = {
_removedHeader: {},
_statusCode: 200,
statusMessage: 'OK'
get statusCode() {
return this._statusCode
},
set statusCode(status) {
this._statusCode = status
this.status(status)
}
};
// some code has been left out
res.status = res.sendStatus = function(number) {
console.log('[runMiddleware] res.status', number, res);
code = number;
return res;
};
If use node-run-middleware and with helmet or cors or other which get/ remove header ( helmet remove header: res.removeHeader("X-Powered-By") or res.getHeader('Vary') I get errors:
(node:23833) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'etag' of undefined
at ServerResponse.getHeader (_http_outgoing.js:490:24)
at ServerResponse.res.get (/var/www/html/selbi.test/node_modules/express/lib/response.js:789:15)
at IncomingMessage.fresh (/var/www/html/selbi.test/node_modules/express/lib/request.js:478:19)
at ServerResponse.send (/var/www/html/selbi.test/node_modules/express/lib/response.js:206:11)
at ServerResponse.json (/var/www/html/selbi.test/node_modules/express/lib/response.js:267:15)
at ServerResponse.send (/var/www/html/selbi.test/node_modules/express/lib/response.js:158:21)
(node:23833) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 3)
TypeError: Cannot read property 'vary' of undefined
at ServerResponse.getHeader (_http_outgoing.js:490:24)
at vary (/var/www/html/selbi.test/node_modules/vary/index.js:140:17)
at applyHeaders (/var/www/html/selbi.test/node_modules/cors/lib/index.js:151:11)
at applyHeaders (/var/www/html/selbi.test/node_modules/cors/lib/index.js:149:11)
at applyHeaders (/var/www/html/selbi.test/node_modules/cors/lib/index.js:149:11)
at cors (/var/www/html/selbi.test/node_modules/cors/lib/index.js:187:7)
The readme has:
//We use res.runMiddleware instead of app.runMiddleware. All the cookies & other data (like socket.io session) will be pass to the second middle ware
res.runMidleware(...)
There's a small typo runMidleware()
is missing an l
, but also looking at the code it looks like this function is defined on the req
object not the res
object.
Hello. I'm testing this module to be able to have single api called by socket and by http, but I'm getting this error:
ERROR TypeError: Cannot read property 'remoteAddress' of undefined at forwarded (/Users/osoverflow/IdeaProjects/domitai/dokku/node_modules/forwarded/index.js:31:35) at alladdrs (/Users/osoverflow/IdeaProjects/domitai/dokku/node_modules/proxy-addr/index.js:57:15) at proxyaddr (/Users/osoverflow/IdeaProjects/domitai/dokku/node_modules/proxy-addr/index.js:231:15) at IncomingMessage.ip (/Users/osoverflow/IdeaProjects/domitai/dokku/node_modules/express/lib/request.js:351:10) at getip (/Users/osoverflow/IdeaProjects/domitai/dokku/node_modules/morgan/index.js:466:14) at logger (/Users/osoverflow/IdeaProjects/domitai/dokku/node_modules/morgan/index.js:107:26) at Layer.handle [as handle_request] (/Users/osoverflow/IdeaProjects/domitai/dokku/node_modules/express/lib/router/layer.js:95:5) at trim_prefix (/Users/osoverflow/IdeaProjects/domitai/dokku/node_modules/express/lib/router/index.js:317:13) at /Users/osoverflow/IdeaProjects/domitai/dokku/node_modules/express/lib/router/index.js:284:7 at Function.process_params (/Users/osoverflow/IdeaProjects/domitai/dokku/node_modules/express/lib/router/index.js:335:12) at next (/Users/osoverflow/IdeaProjects/domitai/dokku/node_modules/express/lib/router/index.js:275:10) at app.use (/Users/osoverflow/IdeaProjects/domitai/dokku/node_modules/run-middleware/index.js:16:5) at Layer.handle [as handle_request] (/Users/osoverflow/IdeaProjects/domitai/dokku/node_modules/express/lib/router/layer.js:95:5) at trim_prefix (/Users/osoverflow/IdeaProjects/domitai/dokku/node_modules/express/lib/router/index.js:317:13) at /Users/osoverflow/IdeaProjects/domitai/dokku/node_modules/express/lib/router/index.js:284:7 at Function.process_params (/Users/osoverflow/IdeaProjects/domitai/dokku/node_modules/express/lib/router/index.js:335:12) +6ms 500 '<h1>Cannot read property 'remoteAddress' of undefined</h1>\n<h2></h2>\n<pre></pre>\n' { 'X-Powered-By': 'Express', 'x-powered-by': 'Express' }
When trying to use PassPort sessions middleware app.runMiddleware()
results in failure due to problems with getting headers. A similar problem was encountered in Issue #39 with a partial workaround.
Error seen:
node:_http_outgoing:721
const entry = headers[StringPrototypeToLowerCase(name)];
^
TypeError: Cannot read properties of undefined (reading 'set-cookie')
at ServerResponse.getHeader (node:_http_outgoing:721:24)
at setcookie (/node_modules/express-session/index.js:661:18)
at ServerResponse.<anonymous> (/node_modules/express-session/index.js:243:7)
at ServerResponse.writeHead (/node_modules/on-headers/index.js:35:16)
at ServerResponse._implicitHeader (node:_http_server:338:8)
at writetop (/node_modules/express-session/index.js:276:15)
at ServerResponse.end (/node_modules/express-session/index.js:343:16)
at allFailed (/node_modules/passport/lib/middleware/authenticate.js:177:11)
at attempt (/node_modules/passport/lib/middleware/authenticate.js:183:28)
at strategy.fail (/node_modules/passport/lib/middleware/authenticate.js:305:9)
References for above error:
Adding the following into createRes()
seems to fix the issue while restoring the ability for res.getHeader()
to work.
Proposed Solution (submitted in PR #57):
res.getHeader = function(name) {
if ( 'undefined' !== typeof headers[name] ) {
return headers[name];
}
return null;
};
The current implementation executes the callback as soon as the the first res.send
or res.write
or res.end
In ExpressJS, it is possible, to execute multi res.write
, but this module not support it yet.
If someone need it please comment, and I will implement it.
I am not sure that developers understand, what this module do. I think it needs better name & desription & documentation.
Please suggest here for names, and description.
Thanks
I am trying to use run-middleware within an angular-fullstack application.
My application is using express for managing sessions and passport.js for authentication (stored in Mongodb). When a user logins in, I want to check if that user already has a living session. I want to use run-middleware to programmatically query mongodb for all the live sessions.
'use strict';
import path from 'path';
import passport from 'passport';
import {Strategy as LocalStrategy} from 'passport-local';
import express from 'express';
import session from 'express-session';
import _ from 'lodash';
import Session from '../../api/session/session.model';
var app = express();
require('run-middleware')(app);
function localAuthenticate(User, email, password, done, req) {
User.findOne({
email: email.toLowerCase()
}).exec()
.then(user => {
if (!user) {
return done(null, false, {
message: 'This email is not registered.'
});
}
// HERE is where I am trying to use the runMiddleware
app.runMiddleware('/sessions',{},function(code,data){
console.log(code) // 200
console.log(data) // { user: '20', name: 'Moyshale' }
});
user.authenticate(password, function(authError, authenticated) {
if (authError) {
return done(authError);
}
if (!authenticated) {
return done(null, false, { message: 'This password is not correct.' });
} else {
return done(null, user);
}
});
})
.catch(err => done(err));
}
export function setup(User, config) {
passport.use(new LocalStrategy({
passReqToCallback: true,
usernameField: 'email',
passwordField: 'password' // this is the virtual field on the model
}, function(req, email, password, done) {
return localAuthenticate(User, email, password, done, req);
}));
}
The error I am getting is:
if (state.pipesCount === 0)
^
TypeError: Cannot read property 'pipesCount' of undefined
at IncomingMessage.Readable.unpipe (_stream_readable.js:634:12)
at unpipe (/home/enview/node_modules/unpipe/index.js:47:12)
at send (/home/enview/node_modules/finalhandler/index.js:184:3)
at Immediate.<anonymous> (/home/enview/node_modules/finalhandler/index.js:113:5)
at Immediate.<anonymous> (/home/enview/node_modules/express/lib/router/index.js:618:15)
at runCallback (timers.js:568:20)
at tryOnImmediate (timers.js:546:5)
at processImmediate [as _immediateCallback] (timers.js:525:5)
If so would you be willing to show me a quick example and how to require it correctly? Thanks!
Just in case anyone's using this and trying to run in modern Node, the callbacks aren't standard so promisify requires some work to get it behaving.
Not perfect but it's a start if you're trying to reuse connect style middleware with direct calls in something like a cron.
require('run-middleware')(server);
server.runMiddleware[util.promisify.custom] = (path, options) => {
return new Promise((resolve, reject) => {
server.runMiddleware(path, options, function (code,data,headers) {
let payload = {code: code, data: data, headers: headers};
resolve(payload);
});
});
};
const runMiddlewarePromise = util.promisify(server.runMiddleware);
const runMiddlewareAsync = async (path, options) => {
try {
const middlewareRes = await runMiddlewarePromise(path, options);
return middlewareRes;
} catch(e) {
console.error("NOT IMPLEMENTED: ", e);
return false;
}
};
// ======= Execute with the following ==============
let resTest = await runMiddlewareAsync('/my/url',{
secure: true,
connection: {},
method:'GET'
});
console.log("res Test: ", resTest);
Express does not populate req.cookies by default. This break the popular "cookie-parse" middleware package as it sees the empty object and does not parse cookies. Removing this empty object default fixes the problem.
Here is a PR which fixes this problem:
#58
for tests, I'm thinking of using this package to mock client-side fetch calls to direct calls to express. Is there a recipe for that?
The new version is passing the header object to the runMiddleware function.
See example.js for more details
If you do something like res.status(200).set('Content-Type', 'text/plain').send('Done!').end();
it doesn't work as .send() doesn't return anything inside the middleware
I guess it doesn't matter too much since I assume calling .end()
isn't needed
There is no typescript support for this module
I can add Mocha+ChaiJS tests to this module. If you need it, just let me know by comment.
See this code for example:
app.get('/middleware1',function(req,res){
/*
use req object instead of app object
*/
req.runMiddleware('middleware2',{},function (){})
})
Almost all of my controllers return res.json(...).
run-middleware does not appear to correctly support this.
In express/lib/response.js it tries to see if Content-Type is set as a header, eventually through the getHeader(...) call.
getHeader is implemented a little poorly, expecting "this[kOutHeaders]" to equal null, but instead it is undefined.
That means all res.json(...) calls will fail. I haven't looked at your code, but is your response not extending OutgoingMessage ?
As a workaround, after I did runMiddleware(app), I added this little gem:
app.response.getHeader = (name) => {
return null;
};`
I am not sure that this module works well when the original middleware uses Express Steram and buffers.
If you need it in your projects, let me know by comment, and I will check it out.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.