how to make a middleware based on koa, which is used for Intercept HTTP response? - koa

My project base on koa,I want to intercept HTTP response,when the response's message is "no promission",then excute 'this.redirect()'.

Your middleware (interceptor in my example) can access the response body after it yield next, so just place your logic after it yields.
var route = require('koa-route');
var app = require('koa')();
var interceptor = function*(next) {
// wait for downstream middleware/handlers to execute
// so that we can inspect the response
yield next;
// our handler has run and set the response body,
// so now we can access it
console.log('Response body:', this.body);
if (this.body === 'no promission') {
this.redirect('/somewhere');
}
};
app.use(interceptor);
app.use(route.get('/', function*() {
this.body = 'no promission';
}));
app.listen(3001, function() {
console.log('Listening on 3001...');
});

Related

Nextjs api resolving before form.parse completes so i cant send response back

I am trying to send an image to Next.js api and then use that image to upload to db.
I am using :
const body = new FormData();
body.append("file", prewiedPP);
const response = await fetch("/api/send-pp-to-server", {
method: "POST",
body ,
headers: {
iext: iExt,
name: cCtx.userDetail ,
},
});
Then in the api :
async function handler(req, res) {
if (req.method === "POST") {
console.log("In");
const form = new formidable.IncomingForm();
form.parse(req,
async (err, fields, files) =>
{
// console.log(req.headers.iext);
// console.log(req.headers.name);
const fdata = fs.readFileSync(files.file.filepath);
await delUserPP(req.headers.name , req.headers.iext);
await setUserPP(
fdata ,
req.headers.name ,
req.headers.iext ,
files.file.mimetype
);
fs.unlinkSync(files.file.filepath);
return;
});
console.log("out");
}
}
export default handler;
The callback function in the from.parse happens after the handler already resolved.
Is there anyway to make the api call only resolve after the setUserPP function is done?
I want to send a response back to the client but the api script finishes to "fast" and before the callback in form.parse runs.
Thanks

I have an error calling AWS API Gateway Websocket Route using wscat or via node.js

I create a websocket and then a custom route. Before publishing I need to select an integration for $disconnect and $default, for both I choose Mock (I have also tried default Lambda functions), this allows me to publish.
I then use wscat to call
wscat -c wss://t0p5b2xpm3.execute-api.us-east-1.amazonaws.com/prod
the socket connects successfully,then i try to call the route
{"action":"echo", "data":"test response body"}
and get the following error.
{"message": "Internal server error", "connectionId":"aDH97cQJoAMCI8Q=", "requestId":"aDIAhGE8oAMFoEg="}
anyone have any ideas please?
thanks,
Matt
For a lambda function, you need to return a statusCode of 200 for $connect, $disconnect, $default, and custom routes. A trivial javascript example:
module.exports.handler = async (event) => {
return {
statusCode: 200,
};
};
exports.handler = async (event) => {
// TODO implement
let time = "undefined";
let state = "undefined";
if (event.body !== null && event.body !== undefined) {
let body = JSON.parse(event.body);
if (body.time && body.state)
{
time = body.time;
state = body.state;
}
}
const response = {
statusCode: 200,
body: JSON.stringify({time:time, state: state}),
};
return response;
};
In case of API-Gateway you won't be able to modify the response as json as in Get and Post, so you can use this code to fetch time and state from the coming json object. Connect using wscat -c link and then send your json as {"time":"22:32","state":"LA"}
Try to put in $default to make sure that you are receiving the sending the right way.
Good luck!

AngularJS simple auth interceptor

I want to pass in the headers my token each time i make a request. the way i do it now is using:
$http.defaults.headers.common['auth_token'] = $localStorage.token;
How could i do that to make that sent to every request, and when it throws an error it should do a
$state.go('login')
If you want to add your token to each request, and respond to any errors, your best bet would be to use an Angular HTTP interceptor.
Subject to your needs, it might look something like this:
$httpProvider.interceptors.push(function ($q, $state, $localStorage) {
return {
// Add an interceptor for requests.
'request': function (config) {
config.headers = config.headers || {}; // Default to an empty object if no headers are set.
// Set the header if the token is stored.
if($localStorage.token) {
config.headers.common['auth_token'] = $localStorage.token;
}
return config;
},
// Add an interceptor for any responses that error.
'responseError': function(response) {
// Check if the error is auth-related.
if(response.status === 401 || response.status === 403) {
$state.go('login');
}
return $q.reject(response);
}
};
});
Hope this helps.

SignalR not working with DelegatingHandler

We have a delegating-handler that catches requests with a certain url prefix, and then reroutes them behind the firewall with the fed auth cookie attached...
This is working for our WebApi layer, but SingalR is firing off requests on its own while it is trying to connect that doesn't follow the pattern... I can't figure out how to force it to use the proper url prefix.
This is the url that is generated from the post request when it is trying to do long-polling: https://localhost:44330/signalr/connect?transport=longPolling&
See that it hasn't put the '/qsixlsignalr' into the url, which my delegating handler will be looking for.
var signalRBaseURL = "/qsixlsignalr"
$(function () {
// http://stackoverflow.com/questions/15467373/signalr-1-0-1-cross-domain-request-cors-with-chrome
$.support.cors = false;
var connection = $.hubConnection(signalRBaseURL);
var myHub = connection.createHubProxy('xlHub');
myHub.on('notify', function (message) {
alertsViewModel.refreshActiveCount(localStorage.getItem(PROJECT_ID));
if (window.location.pathname == '/' || window.location.pathname == '') {
alertsViewModel.refresh(localStorage.getItem(PROJECT_ID));
}
toastr.success(message);
});
connection.disconnected(function () {
setTimeout(function () {
connection.start();
}, 3000);
});
connection.logging = true;
connection.start();
});
If I remember correctly you need to tell SignalR explicitly that you don't want to use the the default url
var connection = $.hubConnection(signalRBaseURL, { useDefaultPath: false });

Cannot submit form with supertest and mocha

I am using supertest and mocha to test a nodejs application. One of the things users can do is to submit a very simple form, which is picked up by the node server and parsed using formidable.
Here is the mocha test code:
var should = require('should'),
express = require('express'),
app = require('../app.js'),
request = require('supertest'),
csrfToken,
sessionId,
cookies = [];
describe('Post Handler', function(){
it('Uploads new post', function(done){
var req = request(app).post('/post?_csrf=' + csrfToken);
req.cookies = cookies;
req
.type('form')
.send({fieldTitle: 'autopost'})
.send({fieldContent: 'autocontent'})
.send({contentType: 'image/png'})
.send({blobId: 'icon_23943.png'})
.expect(200)
.end(function(error, res){
console.log('here');
done();
});
});
csrfToken retrieves a csrf token from the server, since I am using the csurf module and every POST method requires a csrf token. cookies stores the session cookie that is provided by the node server so I can persist the session between requests.
The form is processed by the following code:
//Takes HTTP form posted by client and creates a new post in the Db
exports.postPostUpload = function (req, res) {
var form = new formidable.IncomingForm();
form.parse(req, function (err, fields, files) {
console.log(err);
if (err) res.redirect(303, '/error');
else {
var new_post = new post_model.Post().createNewPost(fields);
new_post.setUserId(req.session.passport.user.userId);
new_post.uploadPostToDb(function (error, result) {
if (error) return res.status(500).end();
else {
if (new_post.media.contentType.indexOf('video') !== -1) {
addMessageToEncodingQueue(new_post, function (error, result, response) {
if (error) {
errorHelper.reportError({
stack: new Error().stack,
error: error
});
res.status(500).end();
}
else res.status(200).send(new_post.cuid);
});
}
else return res.status(200).send(new_post.cuid);
}
});
}
});
}
My current problem is, that once the form handler executes the line form.parse(req, function (err, fields, files) {, nothing happens. Formidable does not return error, it just does not return anything. Consequently, the mocha test never receives a reply from the server, and eventually the socket hangs and the test crashes. Needless to say, the form is successfully submit if you do it manually via the website.
There must be an error in the way supertest/mocha are executing this test, but I have not been able to find it. Any pointers are highly appreciated.

Resources