Not found route not found in Sailsjs - node.js

Based on Sailsjs documentation, it is possible to add on the routes file a response with a syntax like this:
module.exports.routes = {
'/foo': {response: 'notFound'}
};
This searches for the notFound.js file in the /response directory, which I've in there.
So in my routes.js file I've added this as the end of the other routes in order to catch the not found routes, it is something like this:
module.exports.routes = {
'get /myroute/:myPara/': 'MyController.getAll',
'get /myroute/:myPara/': 'MyController.getOne',
'post /myroute/:myPara/': 'MyController.create',
'/*' : {response: 'notFound'}
};
I've realized that never finds the last route, I've also tried removing the slash ( doing '*' ), but nothing works.
Am I missing something? Thanks!

Sails already take care of the 404 notFound : here
Sails call res.notFound() and you can override the default notFound():
res.notFound() (like other userland response methods) can be overridden or modified. It runs the response method defined in /responses/notFound.js, which is bundled automatically in newly generated Sails apps. If a notFound.js response method does not exist in your app, Sails will implicitly use the default behavior.

Related

Nested route gives 404 not found on a fastify app with file based routing

I've created an app with fastify generate but nested routes are giving me 404. index.ts works a directory but anything else I add is not found. I have /a/b/index.ts which works but /a/b/c.ts which doesn't. But if i move c.ts to the parent dir, it's detected. And i have fastify.get('/c'... on c.ts. How can I fix this?
Fastify is about security, so you need to check the plugins' documentation you are using under the hood.
In your case, you must change the app.ts file like so:
void fastify.register(AutoLoad, {
dir: join(__dirname, 'routes'),
maxDepth: 4, // default is 2
options: opts
})
by doing this, fastify-autoload will search for nested folders deep to 4 levels.
Then you will be able to call: http://127.0.0.1:3000/a/b/c/c assuming you created src/routes/a/b/c/c.ts

Express Router: everything route that allows new routes

Since express evaluates routes in the order they were added, you should put the more specific routes first.
server.get('/product/:id', router.getProduct);
server.get('/user/:id', router.getUser);
server.get('*', router.notFound);
However, the administrative side of the site needs to be able to create new sections. When a new section is created it is added to the Database, and then a new route is created. However, the * route captures everything and was added before the new section route. Thus, the new section route never matches.
If I remove the * route, then the new section routes do match. My question is how to create a route the matches on 404 requests, without using the * route. Or is there a way to add a route that always matches at the end of the routing matching order?
Any help appreciated.
Since sections can have arbitrary names, you could check for the validity of them in the catch-all handler. It would depend on how exactly your code is set up, but to give an idea:
server.get('/product/:id', router.getProduct);
server.get('/user/:id', router.getUser);
server.get('*', function(req, res, next) {
let sectionName = req.url.substring(1);
Sections.findByName(sectionName, (err, section) {
// Pass errors to the generic error handler.
if (err) return next(err);
// If the section isn't known, pass it along.
if (! section) return next();
// Perform the section code here.
...
});
});
server.use(router.notFound);
In other words: the get('*') route would take the path of the request, remove the leading slash (unless that's part of the section name), look it up in the database, and handle errors or unknown section names.
The final handler will generate a 404 for requests that fell through the section handler.
4xx/5xx error handling is described here - http://expressjs.com/en/guide/error-handling.html

Where should I put custom errors in sails.js?

I was wondering what's the best practice and if I should create:
a directory in which declare statically all the errors my application uses, like api/errors/custom1Error
declare them directly inside the files
or put the files directly inside the dir that needs that error, like api/controller/error/formInvalidError
other options!?
A neat way of going about this would be to simply add the errors as custom responses under api/responses. This way even the invocation becomes pretty neat. Although the doc says you should add them directly in the responses directory, I'm sure there must be a way to nest them under, say, responses/errors. I'll try that out and post an update in a bit.
Alright, off a quick search, I couldn't find any way to nest the responses, but you can use a small workaround that's not quite as neat:
Create the responses/errors directory with all the custom error response handlers. Create a custom response and name it something like custom.js. Then specify the response name while calling res.custom().
I'm adding a short snippet just for illustration:
api/responses/custom.js:
var customErrors = {
customError1: require('./errors/customError1'),
customError2: require('./errors/customError2')
};
module.exports = function custom (errorName, data) {
var req = this.req;
var res = this.res;
if (customErrors[errorName]) return customErrors[errorName](req, res, data);
else return res.negotiate();
}
From the controller:
res.custom('authError', data);
If you don't need logical processing for different errors, you can do away with the whole errors/ directory and directly invoke the respective views from custom.js:
module.exports = function custom (viewName, data) {
var req = this.req;
var res = this.res;
return res.view('errors/' + viewName, data);//assuming you have error views in views/errors
}
(You should first check if the view exists. Find out how on the linked page.)
Although I'm using something like this for certain purposes (dividing routes and so on), there definitely should be a way to include response handlers defined in different directories. (Perhaps by reconfiguring some grunt task?) I'll try to find that out and update if I find any success.
Good luck!
Update
Okay, so I found that the responses hook adds all files to res without checking if they are directories. So adding a directory under responses results in a TypeError from lodash. I may be reading this wrong but I guess it's reasonable to conclude that currently it's not possible to add a directory there, so I guess you'll have to stick to one of the above solutions.

Angular Js Unexpected Token error Dynamic Routes

I'm getting getting several "unexpected token <" errors when I try to create a dynamic route.
Normal routes work fine. So if I set the following route:
.when('/user',{
templateUrl: 'views/user/new',
controller: "addUserCtrl"
})
The request goes to the server and gets caught by my express catch all route handler, then angular kicks in and requests express' api route, api/user, binds data, controller and template and I see a nice page. Everything works fine. No errors.
If I try to create a dynamic route or a route with more depth, I get the unexpected token error, when I try to request that route:
.when('/user/:id',{
templateUrl: 'views/user/new',
controller: "addUserCtrl"
})
For example, when I request /user/3, i get the error, and it the addUserCtrl is never called. Any ideas what could be causing this.
.when('/user/show,{
templateUrl: 'views/user/new',
controller: "addUserCtrl"
})
requesting /user/show will also throw the error. In the console the error shows up next to the request for all of angular files (angular.js, App.js, services.js, controllers.js, filters.js, directives.js) that I load in the body of my index.html.
I've noticed that this problem happens whenever I add more than one slash to the route. If I try /user/show, I can see the following requests:
/user/show
syntax errors for the below:
/user/js/App.js
/user/js/lib/angular/angular.js
/user/js/filters.js
/user/js/controllers.js'
/user/js/services.js
/user/js/directives.js
If I try /abc/def, I will get the following request:
/abc/def
syntax errors for the below:
/abc/js/App.js
/abc/js/lib/angular/angular.js
/abc/js/filters.js
/abc/js/controllers.js'
/abc/js/services.js
/abc/js/directives.js
I had the same issue and just as atentaten describes the problem was caused by relative paths to js-files. However, it has nothing to do with Express. It can just as well be caused by relative include paths from script tags in the head of a html file. So, to clarify, I changed my HTML from:
<script src="bower_components/angular/angular.js"></script>
to:
<script src="/bower_components/angular/angular.js"></script>
Apparently this is not really an angular issue, but an express issue.
The problem was that the beginning slashes were missing from my angular js includes in my index.jade:
script(src='js/lib/angular/angular.js')
script(src='js/App.js')
script(src='js/services.js')
script(src='js/controllers.js')
script(src='js/filters.js')
script(src='js/directives.js')
I changed them to this:
script(src='/js/lib/angular/angular.js')
script(src='/js/App.js')
script(src='/js/services.js')
script(src='/js/controllers.js')
script(src='/js/filters.js')
script(src='/js/directives.js')
And the errors went away. Although the js loaded without the starting slash, it was still causing a problem with express, creating the syntax error, which probably broke angular, but I'm not sure exactly why.
The templateUrl needs to be absolute else Express will choke if there is more than one slash/level of depth in the url:
.when('/user/show,{
templateUrl: '/views/user/new', /* add slash */
controller: "addUserCtrl"
})
This happens for ui-router dynamic route in angularJS application. I have the same error. solved by changing the path
<script src="app/components/services/campaign.services.js"></script>
to
<script src="/app/components/services/campaign.services.js"></script>
But in my case index.html file path is generated by gulp task gulp-inject so i changes the config of gulp-inject like
inject: { addRootSlash: true }
and it works for me :)

Moving route logic out of app.js

I'm designing an app with node.js and Express, and I was wondering if it was possible to move certain routing logic out of the app.js file. For exapmle, my app.js currently contains:
app.get('/groups',routes.groups);
app.get('/',routes.index);
Is there a way to move this logic out of the app.js file, and only have something like:
app.get('/:url',routes.get);
app.post('/:url",routes.post);
such that all GET requests would be processed by routes.get and all POST requests processed with routes.post?
You could pass a regular expression as the route definition:
app.get(/.+/, someFunction);
This would match anything. However, if you simply want to move your route definitions outside of your main app.js file, it is much clearer to do something like this:
app.js
var app = require('express').createServer();
...
require('routes').addRoutes(app);
routes.js
exports.addRoutes = function(app) {
app.get('/groups', function(req, res) {
...
});
};
This way, you're still using Express' built-in routing, rather than re-rolling your own (as you'd have to do in your example).
FULL DISCLOSURE: I am the developer of the node module mentioned below.
There is a node module that does kind of what you're asking for (and will, eventually, do more). It offers automatic routing based on convention over configuration for express. The module name is honey-express, but is currently in alpha development and not yet available on NPM (but you can get it from the source at https://github.com/jaylach/honey-express.
A short example of how it works: (Please note that this coffeescript)
# Inside your testController.coffee file. Should live inside /app/controllers
honey = require 'honey-express'
TestController = new honey.Controller
index: ->
# #view() is a helper method to automatically render the view for the action you're executing.
# As long as a view (with an extension that matches your setup view engine) lives at /app/views/controller/actionName (without method, so index and not getIndex), it will be rendered.
#view()
postTest: (data) ->
# Do something with data
Now, inside your app.js file you just have to setup some simple configuration:
# in your app.configure callback...
honey.config 'app root', __dirname + '/app'
app.use honey.router()
Now anytime a request comes in, honey will automatically look for a controller with the specified route, and then look for a matching action.. for example -
/test will automatically route to the index/getIndex() method of
testController
/ will automatically route to the index/getIndex() method of the homeController (the default controller is home), if it exists
/test/test will automatically route to the postTest() method of testController if the http method is POST.
As I mentioned, the module is currently in it's alpha state but the automatic routing works wonderfully and has been tested on two different projects now :) But since it's in alpha development, the documentation is missing. Should you decide to go this route, you can look at the sample I have up on the github, look through the code, or reach out to me and I'd be happy to help :)
EDIT: I should also note that honey-express does require the latest (BETA) version of express as it uses features that are not present in 2.x of express.

Resources