I've been trying to handle HTTP error in restify. these are the codes i've been trying so far :
function send403(req, res, err, cb) {
console.log('Forbidden');
res.end();
}
And then i use that function in ForbiddenError event :
server.on('ForbiddenError', send403);
I'm expecting that function to be executed everytime server receive a request without authorization header
server.get('/resource', function (req, res, next) {
if(typeof req.headers['authorization'] === 'undefined') {
return next(new restify.ForbiddenError());
}
else {
// HTTP 200
}
});
Everytime i try to access the url i keep getting that default restify JSON message.
FYI i've tried the same method for 404 error and it works
server.on('NotFound', send404);
Everytime i try to send a request to a non-existing url, the send404 function will be executed.
I think this might be what you are looking for. I noticed that in the "server.on" statement restify doesn't want the "Error" part. The following is a complete working example.
'use strict';
var restify = require('restify');
var server = restify.createServer();
server.on('Forbidden', send403);
server.get('/resource', function(req, res, next){
if(typeof req.headers['authorization'] === 'undefined') {
next(new restify.ForbiddenError());
}
else {
// HTTP 200
}
});
function send403(req, res, err, cb){
console.log('Log something here');
return cb();
}
server.listen(9000);
console.log('listening on port 9000');
Related
My client given me requirement to encrypt decrypt all request response. So for all encrypted request we wrote down the express middleware to get decrypted request. which is the simple part but while sending response we also have to encrypt response.
One way to do write common function to encrypt data and call that function from all routes. which is time consuming part because we have more than 50+ routes in project. So i was thinking to write middleware like we have done for request which capture response before we send and then we encrypt response after that we send encrypt response to client.
I have searched for solution in google not got any proper solution which worked for me.
routes.js
router.post('/getUserData', verifyApiKey, async function (req, res, next) {
let user = await getUserData();
res.status(200).send(user)
});
middlware.js
class EncryptDecryptRequestResponse {
async encryptResponse(req, res, next) {
console.log('Called encryptResponse');
console.log('res.body', res.body);
res.body = encryptData(res.body)
next();
}
}
App.js
// Middleware to decrypt request
app.use(decryptRequest);
app.use('/', indexRouter);
// Middleware to encrypt response
app.use(encryptResponse);
but the problem is that i am not getting any console.log from middleware. this is the solution which i used
I tried to reproduce the problem you're having with overwriting res.send(), but it works fine for me. You need to make sure to setup the interceptor middleware before you define your routes. Consider this simple example:
const express = require('express');
const app = express();
function encryptResponseInterceptor(req, res, next) {
const originalSend = res.send;
res.send = function () {
arguments[0] = encryptResponse(arguments[0]);
originalSend.apply(res, arguments);
};
next();
}
function encryptResponse(originalData) {
// place your encryption logic here, I'm just adding a string in this example
return originalData + " modified";
}
// fake method that returns resolves after 1s just for testing
function getUserData() {
return new Promise(resolve => {
setTimeout(() => {
resolve();
}, 1000)
})
}
app.use(encryptResponseInterceptor);
app.get("/test", async (req, res, next) => {
await getUserData();
res.status(200).send("will be changed");
})
app.listen(3000, () => {
console.log("server started on 3000");
});
my web site sometimes raise 404 error even though there is correct path in my index file.
When occurs 404 error, I reload the page and the page correctly uploaded.
even though by reloading the page successfully page uploaded, I think it's not stable...
Do you have any idea? I don't know why it happens.
This is my route and handler to main page!
And I used vhost to connect domain
app1.get('/',(req,res)=>{
var arr = poplist;
var type = 'recommended';
var session = null;
if(req.session.user){
session = req.session;
}
if (req.session.series_id){ /*5*/
var search_car = req.session.series_id;
arr.unshift({'id':req.session.series_id,'series_name':req.session.manu_name + ' ' + req.session.series_name});
type = 'mycar';
} else {
var search_car = recommend_car(arr).id; /*4*/
}
get_recommend_container(arr,function(err,recommend_container){
if (err) { res.send('err') }
else {
get_best_reviews_container(function(err,best_reviews_container){
if (err) { res.send('err') }
else {
/*search_car for query in menubar*/
res.render('main', {'type':type,'poplist':poplist,'recommend_container':recommend_container,'best_reviews_container':best_reviews_container,'search_car':search_car,'session':session});
}
});
}
});
});
....
app.use(vhost('mysite.com', app1));
app.use(function(req, res, next) {
res.status(404).send('Sorry cannot find the page!');
});
app.listen(8000,'myip',function(){
console.log("Connected to 8000 port!..")
});
You explicitely define a "404 middleware" :
app.use(function(req, res, next) {
res.status(404).send('Sorry cannot find the page!');
});
This means that every time your app will receive any request, it will execute that middleware that will send back a 404.
Documentation : https://expressjs.com/en/guide/using-middleware.html
This example shows a middleware function with no mount path. The
function is executed every time the app receives a request.
var app = express()
app.use(function (req, res, next) {
console.log('Time:', Date.now())
next()
})
I have the following node-mitm code.
mitm = Mitm();
mitm.on("request", function(req, res) {
const body = req.body; //body is null
})
I feel this has to do with reading node's IncomingMessage events, but I don't know how to do it.
Mitm.js's request handler is just like the one you're used to on Node's side. That is, it doesn't do anything special with req.body and leaves it as a ReadableStream.
You could either get its contents with the classical on("data") pattern:
mitm.on("request", function(req, res) {
req.on("data", function(data) { data == "Hello" })
})
If you want to fake a larger service, I've sometimes used Express to create routes and then pass Express's route handler to Mitm:
var Router = require("express").Router
var router = Router().use(require("body-parser").text())
router.get("/", function(req, res) { req.end() })
mitm.on("request", route.bind(null, router))
function route(router, req, res) {
router(req, res, function(err) {
if (err == null) return
res.writeHead(502)
throw err
})
}
The last example is a summary of the pattern I've also got publicly visible at the Rahvaalgatus open source repository: https://github.com/rahvaalgatus/rahvaalgatus.
Specifically, look at the controller test of https://github.com/rahvaalgatus/rahvaalgatus/blob/6dc91b026d75879cdc552bd2e63f220235b786c0/test/controllers/home_controller_test.js and see the this.router definition at https://github.com/rahvaalgatus/rahvaalgatus/blob/6dc91b026d75879cdc552bd2e63f220235b786c0/test/mitm.js.
I am trying to create a module which can log some certain params for the request and print them to the page which can be checked online, the page will use the socket.io to load the latest logs.
And I want this module can worked as a plugin which means you just call this module, and initialize it, then an extra entry point /_logger will be added to you application, once you visit the page, the latest logs will be updated in real-time. So the module have to intercept the requests:
function setup(httpServer) {
//page
httpServer.on("request", function (request, response) {
var pathname = url.parse(request.url).pathname;
if (pathname === '/_logger') {
fs.readFile(__dirname + '/logger.html', (err, data) => {
response.writeHead(200, { 'Content-Type': 'text/html' });
response.write(data);
response.end();
});
}else{
// how to give up the control for this requset
}
});
var io = require('socket.io')(httpServer);
io.on('connection', function (socket) {
//TO BE DONE
socket.on('event', function (data) { });
socket.on('disconnect', function () { });
});
}
module.exports = {
setup: setup
}
Usage:
var logger= require("./logger/index");
var server = require('http').createServer();
logger.setup(server);
server.on("request", function(req,res){
//Normal logic for different application
});
server.listen(3333);
Now the problem is that once the requested url is not /_logger, I should release the control of this request.
if (pathname === '/_logger') {
//take control
}else{
// Nothing should be done here, it should go to the next request chain.
}
After read the documents, I can not find the right way to make it.
Any ideas?
Assuming that you want to use low-level NodeJS HTTP API. You can compose several handlers into one handler using function composition. Each handler should yield the execution to the next handler, if the req.url doesn't matches.
var http = require('http');
var handler1 = function(req, res) {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.write('/');
res.end();
}
var handler2 = function(req, res) {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.write('/Hello');
res.end();
}
var middleware = compose([wrapHandler('/', handler1),
wrapHandler('/hello', handler2)]);
http.createServer(middleware).listen(3000);
function wrapHandler(path, cb) {
return function (req, res, next) {
if (req.url === path) {
cb(req, res);
} else {
next();
}
};
}
function notFoundHandler(req, res) {
res.writeHead(404, { 'Content-Type': 'text/html' });
res.write('No Path found');
res.end();
};
// adapted from koa-compose
function compose(middleware) {
return function (req, res){
let next = function () {
notFoundHandler.call(this, req, res);
};
let i = middleware.length;
while (i--) {
let thisMiddleware = middleware[i];
let nextMiddleware = next;
next = function () {
thisMiddleware.call(this, req, res, nextMiddleware);
}
}
return next();
}
}
In your case, you can write.
var loggerHandler = wrapHandler('/_logger', logger.handler);
httpServer.on('request', compose(loggerHandler, handler2, handler3));
httpServer.on("request", ...) is just one request listener. It is under no obligation to process the request if it doesn't need to. Even if it does nothing, any other request listeners will still get notified of this request.
If there are other request listeners (which you are implying that there are), then you can just do nothing in the request listener you show and the other listeners will also get a shot at the particular request. This allows you to add your own request listener to a working http server and your listener only has to pay attention to the new route that it wants to support and can just ignore all the other routes and they will get handled by the other listeners that are already in place.
Now, there are frameworks built to make this both simpler and to give you more control. In general, these frameworks use one listener and they provide a means for you to handle the request OR explicitly tell the framework that you have not handled the request and would like other route handlers to have a shot at handling the request. This is a bit more flexible than just have multiple listeners, all of which will get notified of the same route.
For example, using the Express framework, you can do this:
var express = require('express');
var app = express();
// route handler for / request only when a user=xxx is in the query string
app.get('/', function(req, res, next) {
// if user was included in query parameter
if (req.query.user) {
// do something specific when ?user=xxxx is included in the URL
} else {
// pass handling to the next request handler in the chain
next();
}
});
// route handler for / request that wasn't already handled
app.get('/', function(req, res) {
// handle the / route here
});
app.listen(80);
I'm somewhat new to NodeJS, and current I used Express and Request ( https://github.com/request/request ) to forward my app request to REST api server, current my code shown below:
app.use('/rest/*', function(req, res) {
req.pipe(request('http://ipaddress/api')).pipe(res);
});
this code works when the REST API server is OK, but if the rest api server goes down, my nodejs app also goes down, because request stream will fail and the error is not caught by my app.
I checked the Request github page, it provides one way to handle the stream error, like
app.use('/rest/*', function(req, res) {
req.pipe(request('http://ipaddress/api').on('error', function(err) {
console.log(err);
})).pipe(res);
});
this can only log the error and prevent my NodeJS app crashing, but I want to change the response when error occurred so that the changed response can be piped to final one, for example, what I want to do in pseudocode:
app.use('/rest/*', function(req, res) {
req.pipe(request('http://ipaddress/api').on('error', function(err) {
console.log(err);
// what I want to do in pseudocode
response.statusCode = 500;
response.json = {
reason: err.errno
};
})).pipe(res);
});
Are there any ways to solve my problems? Thanks for any ideas!
Untested but could you pass the error back to middleware to handle the reponse?
app.use('/rest/*', function(req, res, next) {
req.pipe(request('http://ipaddress/api').on('error', function(err) {
return next(err)
})).pipe(res);
});
Handled like so
// Exception handling
app.use(function (error, req, res, next) {
console.log(error);
res.status(500).send(JSON.stringify(error));
next();
});