Is it necessary to explicitly handle 404s in Express? - express

Express documentation at https://expressjs.com/en/starter/faq.html shows how to handle 404 by adding the following after all middleware:
app.use(function (req, res, next) {
res.status(404).send("Sorry can't find that!")
})
But even without adding this, unhandled routes are automatically responding 404. Is there some reason why I need to explicitly handle 404s if I don't need any extra functionality there?

Express has a default 404 handler built-in so if you're perfectly fine with what it provides, then it is not necessary to provide your own 404 handler. You provide your own 404 handler when you want to control what response is sent for a 404 condition.
I went to look for the default 404 handler in the Express source code and it's a bit hard to find. It is buried in a dependent module called finalHandler which I was only able to find by stepping through the Express code which eventually stepped into this other module and you can see this module in the Express package.json as a dependency.
Here's a link to the relevant function in the finalHandler source.
Basically, if Express handlers/middleware keep calling next() and run out of more matching request handlers, they get to this final function which, if there is no pending error, then it sends a vanilla 404 response.
The relevant lines of code are these:
status = 404
msg = 'Cannot ' + req.method + ' ' + encodeUrl(getResourceName(req))
// ...
send(req, res, status, headers, msg)

Related

Nuxt 3 $fetch method doesn't work with golang servers?

UPD: you can check this yourself: https://github.com/Rusinas/nuxt-fetch-bug
I know I know this sounds stupid as hell and server language has nothing to do with such problems, but hear me out.
I am trying to load data from my local server using $fetch() (or useFetch, no difference), but I get this error:
FetchError: fetch failed ()
No any other details provided. Server is running using Golang/Fiber. When I am trying to load the same endpoint via Postman, everything is OK:
But when I try to load the SAME endpoint in my nuxt 3 application:
I get this:
But my golang server logging this as success:
The more weird thing about all this is that if I run my nodejs version of the exact same server (or any other random API), I don't get any error.
I am pretty sure that my server working 100% correct, but maybe I lost some header or something, which express put automatically? Here is my response headers:
I also checked nodejs response headers:
Doesn't seem like problem is there.
I have no idea what is happening and I don't know other methods to retrieve async data on server side in nuxt js. I have installed axios, but it throws random errors and works on client side for some reason, which makes using nuxt meaningless. However, axios can call this endpoint and returns my data, but only in browser (despite I call it in setup function without any hooks). I am thinking to switch career now
The problem was that fetch() didn't reconize localhost:9000 for some
reason, but when I changed BASE_URL to 127.0.0.1:9000 it started to
work
I had the same error: FetchError: fetch failed ()
Changing localhost in the url to 127.0.0.1 worked for me.
Writing as a separate answer because some might not find it in the comments.
First I think you are using $fetch in a wrong way, as I've seen Nuxt uses fetch for example:
const data = await fetch(endpoint, {
method: "GET",
mode: "cors"
})
.then(resp => resp.json())
And for the server, just enable CORS header on the response, like this:
// you can replace the asterisk with the clients you want.
c.Append("Access-Control-Allow-Origin", "*")
hope I helped :)

How does vue PWA use the precache? I still get "Page does not work offline"

I have a vue application that I updated to have PWA capability. It uses the firebase messaging service that has overridden the service worker with its own firebase-messaging-sw.js file.
The service worker is registered, active and working, I have added the pwa in the vue.config.js file so that it generates the manifest.json. When you build the production version of the app the following code gets added to the top of the service worker.
importScripts("precache-manifest.7b51ac9589a6dc8041a85d8f1792defa.js", "https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
From what I see the percache works fine.
Should this be enough to get the site to work in offline mode?
Do I need to add some cache management myself?
What am I missing because I still get the "Page does not work offline" error message in Chrome's dev tools under the App manifest tab.
Looks like Google also picked up on the quick hack and the warning has returned.
So since of Chrome93 (AUG-2021) the quick hack, will not work anymore :
self.addEventListener('fetch', function(event) {})
Solution working "for now" (since we never know what requirements Google will add later on)
I've found a nice article which provides with a few solutions, the first one the author provides is Network-Falling-Back-To-Cache strategy:
your service worker will first try to retrieve the resource from your server. Then when it can’t do that — because for example, you’re offline — retrieve it from the cache (if it exists there).
self.addEventListener('fetch', function(event) {
event.respondWith(async function() {
try{
var res = await fetch(event.request);
var cache = await caches.open('cache');
cache.put(event.request.url, res.clone());
return res;
}
catch(error){
return caches.match(event.request);
}
}());
});
You can find all the information and alternative solutions in the article:
https://javascript.plainenglish.io/your-pwa-is-going-to-break-in-august-2021-34982f329f40
I hope this will help futur visitors.
Additional side note:
using the above code you might encounter the following error:
service-worker.js:40 Uncaught (in promise) TypeError: Failed to execute 'put' on 'Cache': Request scheme 'chrome-extension' is unsupported
This error is caused by chrome extentions like Augury or Vue dev-tools. Switching both off will cause the error to disappear.
You need to add this line in the serviceworker. It fools the browser into thinking that the page will work offline:
self.addEventListener('fetch', function(event) {}) // add this to fool it into thinking its offline ready

Calling next('route') when no other route matches the request uri

The Express documentation states the following about next('route') callback:
You can provide multiple callbacks, and all are treated equally, and behave just like middleware, except that these callbacks may invoke next('route') to bypass the remaining route callback(s). You can use this mechanism to perform pre-conditions on a route then pass control to subsequent routes when there is no reason to proceed with the route matched.
and
To skip the rest of the middleware functions from a router middleware stack, call next('route') to pass control to the next route. NOTE: next('route') will work only in middleware functions that were loaded by using the app.METHOD() or router.METHOD() functions.
What is the response to the client when a middleware calls next('route') and there is no other matching route?
The response to the client is a status 404 error. This is not caught by the routers error handlers.
If you want to catch the 404 error for some reason, see this question.
However beware of matching routes:
router.get('/profile', auth.hasRole('User'), controller.showProfile);
router.get('/:id', controller.show);
I had the hasRole('User') function call next('route') if the client did not have that role. Controll was then passed to the '/:id' route as this matched the request uri, causing errors.
It will exit the Router and continue on with the rest of your application middleware and if still nothing ends in a response then a 404 error will be thrown and will be handled by the error handlers.

ASP.NET Web API 2 BadRequest content

I'm not receiving the expected Response Content on the client when the resource returns BadRequest.
[HttpGet]
[Route("Test", Name = "Test")]
public async Task<IHttpActionResult> Test()
{
var result = BadRequest("test");
return result;
}
On client (see hurl.it example below) I simply receive the string Bad Request in the body:
The response on the server seems to be fine:
It was working fine at some point (returning strings or ModelState in content) and recently we noticed this problem. I can't think of any recent change on server that could cause it.
It works neither locally nor when deployed on server.
It can be reproduced in any ApiController in the project.
return Ok("test"); works as expected.
Does anyone know what can cause this behavior?
Thank you!
It is hard to tell what goes wrong.
Things you could check:
Perhaps is your error caused by invalid authentication request
Try with a new project, if that makes difference then you know it's your project and there are no errors caused by your local IIS and server settings (highly unlikely but you never know.
Check your App_Start folder, containing the BundleConfig, RouteConfig, FilterConfig,WebApiConfig`. Perhaps some custom settings did cause to give you bad request error while it might be a not found error.
Check if it's only on Get request or also on others, could be caused by different versions of assemblies.
Check if you only have the problem with 400, or does 401, 500 gives the same problem?
Check your Web.Config file, these might contain <CustomErrors> that might redirect, or throw there own errors.
After some comments, custom erros seemed to be the problem.

How to bypass the Sails body parser for multi-part form uploads

I am facing a problem on Sails.js (0.9.16) with POST requests sent from a JAVA client.
On the client side I built a POST request (with enctype : multipart/form-data) sending a text file.
On the server side, I created a controller with a method (action) getRequest which looks like :
getRequest: function (req, res, next) {
//var busboy = require('connect-busboy');
console.log('req: ', req);
return res.send(200);
}
But I have the following error on my sails.js console:
Error: 'Unable to parse HTTP body :: { [error: Expected CR Received 10] status: 400 }
So I saw on the Web that Express/Connect included with Sails.js was not appropriate to handle multipart data, has anybody already faced my problem and succeed to use an other middleware like busboy or formidable to handle these kind of request?
Thanks in advance.
Best
Loïc
I've been trying to solve this problem as well. Looks like skipper from the sails team is the way to go. https://github.com/balderdashy/skipper
The docs appear to be decent w/ examples for sails 0.10.0 & 0.9.x.
See this thread on GitHub https://github.com/balderdashy/sails/issues/1521 for more info and background.
Hope this helps. FYI - The google group for sails is active.
Graham