How to send json response back in adonis js with a status code like 401? - node.js

I am trying to send a json response back to the application with a status code. This what I tired but didn't work.
if (validation.fails()) {
console.log(validation.messages())
return response.json(validation.messages(),false,401)
// or return response.json(validation.messages(),401)
// It always sends 200 status code
}

Found the solution. I need to use like this return response.status(401).json(validation.messages())

One better solution is to use descriptive methods: https://adonisjs.com/docs/4.1/response#_descriptive_methods
Example:
response.unauthorized('Login First')

Related

Good practice to handle useless response in express js/nodejs?

Am using express js on node for my api service ! In which am using sequelize for query handling purposes !
So in some usecase like creating record, or updating record its simply returning "1" or sometimes nothing !
In this case , am just using
res.sendStatus(200);
or sometimes
res.send("success");
Is there any better way or this is the correct way to handle ? Or should in need .end() in order to end the process ??
which is a good way to handle these kind of useless responses which we dont need to send back ?
This is where Status 204 comes in to play: https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#2xx_success
It states: everything is OK (like in 200), but there is simple no need to send a body.
Using express, it's just as simple as: res.sendStatus(204)
Usually a json is send back to the client with different information in it that lets the client-side know that the operation that they request through the api is successfull or failed. for e.g. here, you can define a standard json response like this
//in case of success of the request
{
requestStatus: 1,
...other data if you want to like new Id of the created data/updated data or info about it if you want or depending upon use case
}
or
// in case of failure of the request
{
requestStatus: 0,
...other data if you want to like reason for failure, error message or depending upon your use case
}
Just add this line of code, should be fine:
//For all bad endpoints
app.use('*', (req, res) => {
res.status(404).json({ msg: 'Not a good endpoint, why are you here? Go play FIFA.'})
})
If you want you can generate an error HTML file, but since it's back-end, JSON format is strongly suggested. You can also add success: false for more clarity.

typescript fetch response streaming

i am trying to stream a response. But i want to be able to read the response (and work with the data) while it is still being sent. I basically want to send multiple messages in one response.
It works internally in node.js, but when i tried to do the same thing in typescript it doesnt work anymore.
My attempt was to do the request via fetch in typescript and the response is coming from a node.js server by writing parts of the response on the response stream.
fetch('...', {
...
}).then((response => {
const reader = response.body.getReader();
reader.read().then(({done, value}) => {
if (done) {
return response;
}
console.log(String.fromCharCode.apply(null, value)); //just for testing purposes
})
}).then(...)...
On the Node.js side it basically looks like this:
// doing stuff with the request
response.write(first_message)
// do some more stuff
response.write(second_message)
// do even more stuff
response.end(last_message)
In Node.js, like i said, i can just read every message once its sent via res.on('data', ...), but the reader.read in typescript only triggers(?) once and that is when the whole response was sent.
Is there a way to make it work like i want, or do i have to look for another way?
I hope it is kinda understandable what i want to do, i noticed while writing this how much i struggled explaining this :D
I found the problem, and as usual it was sitting in front of the pc.
I forgot to write a header first, before writing the response.

Behavior of expressjs next middleware when the response has gone

I am using express (v:4.17.1) and here is my code snippet:
//upload.array is for multer npm file uplaoding....
//LIMIT is how many files you can upload via multer ....
app.post('/processFiles', upload.array('myFile', LIMIT), (req, res, next) => {
if (!validEnv) {
res.setHeader('X-Correlation-ID', corrId);
res.status(400).json({'error':'invalid env'});
return next(); //A
}
//checking how many file hvae been uplaoded
if (totalFiles > LIMIT) {
res.status(400).json({'error':'Too many files uploaded'});
return next(); //B
}
//Some xml parsing code and later it inserts into db
}
Few questions on the way I have added 'return next();' in the routes. Please note that I have not added any explicit middleware, just relying on what express is providing:
If I keep [A] or [B] as it is, then it gives a proper error message to the browser if the conditions get TRUE and returns the response.
But if I comment the line //A or //B, it gives the error response back to browser but also prints few error logs as mentioned below:
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
I don't know why the above line is appearing when I comment the //A or //B (but wont complain if I keep as it is without commenting them) as the response was already out to the browser and the express will not execute any piece of code after the response has gone.
Please correct my understanding ?
Also, Is this the correct way to handle errors as I have coded? If No, what could be the proper way, please advice? Is there any way by which we can see the complete middleware execution in sequence until the last one via any debug flags
There are a several ExpressJS things to know that apply here:
next() tells Express to continue routing to other requests. Only call next() if you want other routes to continue to be able to process this request and send a response. Or the corallary, don't call next() if you've already sent a response.
You can only send one response for a given request. Once, you've called res.send() or .res.json() or any other way of sending a response, you should be completely done with your request processing and no other code should try to send a response.
res.send() and next() are not Javascript flow control. If you want to stop further processing of the request in your function, you need to code that with traditional Javascript flow control such as return, if/else, etc... to prevent the rest of your code from continuing to run or process the request.
To that end, your code should look like this:
//upload.array is for multer npm file uplaoding....
//LIMIT is how many files you can upload via multer ....
app.post('/processFiles', upload.array('myFile', LIMIT), (req, res, next) => {
if (!validEnv) {
res.setHeader('X-Correlation-ID', corrId);
res.status(400).json({'error':'invalid env'});
return;
}
//checking how many file hvae been uplaoded
if (totalFiles > LIMIT) {
res.status(400).json({'error':'Too many files uploaded'});
return;
}
// more code here that sends some other response
}
But if I comment the line //A or //B, it gives the error response back to browser but also prints few error logs as mentioned below: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
This error occurs when you attempt to send more than one response for the same request (e.g. call res.send(...) more than once. Your code should not allow that. Once you send a response, your code should use normal Javascript flow control (such as return or if/else) to avoid executing any more code that might send a response. Typically after you send a response, you are done processing the request and would just return from the request handler.
This is happening because of the //A. See, what is going on here in your code :
If you comment line //B it reaches the next if (totalFiles > LIMIT) which is sending another response but above the return next() is called. That is why it is generating error that once they are sent in if(!validEnv) how can Headers be sent again!
You have two if conditions that mean both might get executed, in both the conditions you are setting the headers and ending the request. Once the request is ended the headers cannot be set. So if you comment [A] which has the return statement and if the second condition is also satisfied, it will set the headers again after sending the request. so it has nothing to do with the next() function or express since there is no next middleware in the stack.
Also the error handling is looks fine. however you can use the node --inspect flag while starting the script and set breakpoint in your middleware to debug entire node code.

nodeJS prevent timeout on res.download

I have a POST call to my nodeJS server that searches for some data on the mongo database and returns a CSV file with the requested data. The problem is that the data search and processing exceeds the 2 minute nodeJS default timeout.
On a diferent scenario y used:
res.writeHeader(200,'application/json');
res.write('starting fetch .... ');
to keep alive the request and prevent the timeout from the client by sending some res.write(''); from time to time.
Now Im using res.download() to download the resulting csv file, so not just sending JSON as response.
Tried to use this solution like this:
res.writeHeader(200,'application/json');
res.write('starting fetch .... ');
res.download()
But i get the "headers already sent" error.
Any idea on how to prevent the timeout until the data is processed and the file download is done ?
Thanks in advance
A few small things first of all, i think it's supposed to be res.writeHead() instead of res.writeHeader(). Secondly once you send the headers you can not send them again. You are getting the error because res.download() uses res.sendFile() which re-sends the headers. You can't use res.download() or res.sendFile() or res.send() because all of these three methods implicitly set the headers and send as part of the response. You'll need to use a combination of res.writeHead() ,res.write() and res.end(). I am just GET so i can test it from the browser, you can use post obviously.
router.get('/test', function (req,res,next) {
res.writeHead(200, {'Content-Type': 'application/json',
'Content-Disposition': 'attachment',
'filename':'package.json'
});
fs.readFile("package.json",function (err,data) {
if (err) {
throw err;
}else{
setTimeout(function () {
res.write(data);
res.end()
},200000);
}
});
function keepBusy(){
if(!res.finished){
res.writeProcessing();
setTimeout(keepBusy,1000)
}
}
setTimeout(keepBusy,1000);
});
This works fine for me. res.writeProcessing() sends the 102 status code. It is recommended for requests that last greater than 20 second but this blog post says that
102 has been left out more recent revisions of HTTP specifications
but it works fine for me in most browsers. If you have some control over the client as well there can be a much better and reliable solution.

how to log js errors at server

I wanted to know does YUI3 provides any way to try and catch errors functionality, where in after the error is captured we can show some customized error alert and simultaneously log the error at server side with the error exceptions and other details.
Also if this functionality is not there in yui3 then which all frameworks do one need to use to do this and which all are compatible with YUI.
I'm not aware of YUI3 providing exactly what you're after out-of-the box.
You can split your question into two parts:
Capturing errors
You either wrap your code with try/catch blocks or use a global error handler. It looks like YUI3 doesn't yet directly handle this (http://yuilibrary.com/projects/yui3/ticket/2528067) but handling it shouldn't be too hard, you'll just have to test for browser differences.
Sending Error data to the server
You ought to be able to use Y.IO to send back the error data to the server. It looks like you get errorMsg, url, lineNumber given to you, so you can just send them back to the server:
YUI().use("io-base",function(Y){
window.onerror = function(errorMsg, url, lineNumber){
Y.io("/errorHandler.php", {
data: {
errorMsg: errorMsg,
url: url,
lineNumber: lineNumber
}
});
alert("Sorry, something bad happened");
};
console.log("handler registered");
//now trigger an error
a.b.c="banana";
});
That seems to work here: http://jsfiddle.net/J83LW/
I'l leave the customized alert to you, I've left an alert here as a basic example of handling this

Resources