Sails.js - Change routing order (custom routes after blueprints) - express

I am having a very similar issue to this post here: How to use custom route middleware with Sails.js? (ExpressJS)
in that I want all non ajax requests (or all routes with the prefix /api) to load the same view, regardless of route. I have implemented the given answer in that question, but came across the issue that the policy is not called for any unspecified routes.
If I was to catch all routes so that the policy was called, all my blueprints would be overwritten.
Ideally, I would catch all routes last, after the blueprints, since every non API route should be sent to the front end.
I am using angularjs for the front end and want angular to deal with all non API routing.
I would rather not use a .htaccess file as I need to put session information into the page on it's initial load.
Thanks

It seems like your use case is very similar to a HTTP 404 Error situation - you want all requests which don't satisfy blueprint (and possibly route.js) routes to be handled in the same manner.
From api/responses/notFound.js:
* NOTE:
* If a request doesn't match any explicit routes (i.e. `config/routes.js`)
* or route blueprints (i.e. "shadow routes", Sails will call `res.notFound()`
* automatically.
*/
You can have special handling code here which calls the appropriate view if the request path contains /api:
if (req.path.match('^/api')) {
return res.view('your-view-here');
}

Related

Is there a way to apply middlewares on all of specific request method?

I have been working on a typescript project. I have created a middleware to check users' subscription and do not want to let users access PUT and POST routes. But I still want them to be able to access GET and DELETE requests.
I know that the following line applies the checkSubscription middleware to all the requests on the route.
router.use(checkSubscription)
I only want the middleware to run if the request type is PUT or POST.
I could do the following, of course
router.get("/endpoint1", controller1);
router.put("/endpoint2", checkSubscription, controller2);
router.post("/endpoint3", checkSubscription, controller3);
router.delete("/endpoint4", controller4);
Notice that the above PUT and POST requests run the checkSubscription middleware.
But if I could declare on the top of the route file to run the middleware on all POST and PUT requests, that would save a lot of work and time.
Any kind of help would be highly appreciated. Thanks!
You can restrict the middleware to PUT and POST requests by evaluating the req.method inside:
function checkSubscription(req, res, next) {
if (req.method !== "PUT" && req.method !== "POST") return next();
// Rest of your middleware code
}
This keeps the rule "this middleware is only for PUT and POST" local to the middleware, no matter how often it is referenced in other statements like router.use and router.post.
But if I could declare on the top of the route file to run the middleware on all POST and PUT requests, that would save a lot of work and time.
You can just do something like this:
router.put("*", checkSubscription);
router.post("*", checkSubscription);
This will only call the checkSubscription() middleware for all PUT or POST requests that hit this router.
The "*" will match any path that goes through this router, but you could use any particular Express route pattern/regex there that you want if you want it to match more than one path, but not all paths.
As it sounds like you already know, you can also control route declaration ordering to give some routes a chance to handle the request before the middleware gets a shot to run.
Since Express runs middleware (including route handlers) in order, you can place the routes for which you don't want to run the middleware first, then the middleware, then the routes for which it does need to run:
router.get(...);
router.delete(...);
router.use(checkSubscription);
router.post(...);
router.put(...);
It does require some diligence with regards to app maintenance, because developers need to understand that the order in which the handlers are declared is relevant.

Route middleware in ExpressJs?

I am new at ExpressJs. so I have some questions about middlewares. So,when do we have to use route middleware in ExpressJs?
First off middleware is code that generally operates on a number of incoming requests. For example, you might have some middleware that checks a cookie to see if this request is authorized before allowing routing to other request handlers to continue. If the request is authorized, it would call next() to continue routing to whatever route handles that specific URL. If the request is not authorized, then it would send an error response and stop further routing. There are thousands of possible uses for middleware - authorization checking is just one such example.
So, you would use middleware when you have multiple routes that all want some sort of pre-check or pre-processing done before the individual routes get called.
Since you asked about "route middleware", perhaps you also wanted to know when you would use middleware on a specific router rather than on the app object. That would be the same when you want middleware to apply only to the routes that are directed to a router object, not on all routes. That can also be done by specifying a path for the middleware such that is only gets called for certain paths.
You can use middlewares when you want to filter your requests before it goes to the next step and make an operation that you want to do there. For e.g in following ways you can have make use of middewares:
Validate
Authorization
Access levels
Restrict requests calls

NextJS multiple dynamic routes with different destionation

In my project I have the following requirement: having 2 routes that are dynamic but that are going to be drawn by different components.
More context:
I have a CMS that provides all the info and in most of the cases I'm going to read from a "page" model. This is going to be drawn by the Page component and its going to have a getServerSideProps that makes a call to a CMS endpoint to get that information
The endpoint and component are not the same for the other case with a dynamic route
Both types of routes are completely dynamic so I cannot prepare then in advance (or at least I'm trying to find another solution) since they come from the CMS
As an example, I can have this slugs
mypage.com/about-us (page endpoint & component)
mypage.com/resource (resources endpoint & component)
Both routes are configured using dynamic routes like this
{
source: '/:pages*',
destination: '/cms/pages'
}
The problem here is that it can only match one of the endpoints and the logic for both calling the endpoint and the component used to draw it are completely different
Is there a way of fallbacking to the next matched URL in case that there's more than one that matches similar to the return {notFound: true}?
Some solutions that I have are:
Somehow hardcode all the resources urls (since are less than pages) and pass them as defined routes instead of dynamic routes
Make some dirty code that will check if the slug is from a resource and if not fallback to a page and then return a Resource component or a Page component depending on that (this idea I like it less since it makes the logic of the Page component super dirty)
Thanks so much!

Symfony - fallback to another application if Symfonfy app can not handle the request

We have an old Yii application along with new Symfony one.
The basic idea is simple - I need to check if there is a route matching in Symfony application then it is cool, if not then bootstrap Yii application and try to handle the request with it.
The main idea to not instantiate AppKernel (and do not load autoload.php - since there is two different autoload.php for each project) before I am sure there is route matching.
Can I do it somehow?
We've done this before with legacy applications.
There are two approaches you can take.
Wrap your old application inside a symfony project (recommended).
Unfortunately this will indeed load the symfony front-controller and kernel. No way around that. You need to make sure that symfony can't handle the request and to do that the kernel needs to be booted up.
Use sub-directories and apache virtual hosts to load one application vs the other as needed.
Given option 1,
You can either create your own front controller that loads either symfony or yii by reading routes (from static files if using yml or xml, or annotations which will be more complex) OR EventListener (RequestListener) that listens to the HttpKernelInterface::MASTER_REQUEST and ensures that a route can be returned.
Creating your own front controller is the only way that you can make it not load the symfony kernel, but it will require you to write something that understands the routes in both frameworks (or at least symfony's) and hands off the request appropriately.
Event listener example:
public function onkernelRequest(GetResponseEvent $event)
{
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
return;
}
... Code to continue normally, or bootstrap yii and return a custom response... (Can include and ob_start, or make an http request, etc)
}
public function getSubscribedEvents()
{
return [
KernelEvents::REQUEST => ['onKernelRequest']
];
}
As you see, the kernel needs to be booted to ensure symfony can't serve the route. Unless creating your own front controller (as stated above).
A third approach would be to create a fallback controller, which would load up a specified URL if no route was found within symfony. Although this approach is generally used for legacy projects that lack a framework and use page scripts instead of proper routes, and definitely requires the use/help of output buffering.
The EventListener approach gives you the opportunity to create a proper Request to hand off to yii, and using what is returned to create a Response as proper symfony object (can also use ob or other options).
Thank you.
This is an alternative to vpassapera's solution -http://stovepipe.systems/post/migrating-your-project-to-symfony

Adding custom route to Zend REST controller

I am using Zend F/W 1.12 in order to build a REST server.
One of my requirements are to have an action that Is outside the boundaries of what Zend can recognize as a "Restfull" action. What I mean is that I would like to have an action that is called something like mymedia and would like tou routes requests that are directed to //mymedia . Currently, Zend understand it as the id to a getAction and off course this is not what I want.
Any help will be highly appreciated!
Thanks
The implementation of Zend_Rest_Route does not allow much customization but instead provides a rudimental routing scheme for out-of-the-box usage.
So if you need to change the way how URIs are interpreted you can extend Zend_Rest_Route, Zend_Controller_Router_Route_Module or Zend_Controller_Router_Route_Abstract class to create your own kind of routing.
Have a look at the match method of those classes and what they do - e.g. they populate the $_values property array (while respecting the $_moduleKey, $_controllerKey and $_actionKey properties).
You can then add it e.g. as the first route within your bootstrap class:
$frontController = Zend_Controller_Front::getInstance();
$router = $frontController->getRouter();
$router->addRoute('myRoute', new My_Route($frontController));
$router->addRoute('restRoute', new Zend_Rest_Route($frontController));
See:
http://framework.zend.com/manual/1.12/en/zend.controller.router.html#zend.controller.router.basic
Routing is a simple process of iterating through all provided routes and matching its definitions to current request URI. When a positive match is found, variable values are returned from the Route instance and are injected into the Zend_Controller_Request object for later use in the dispatcher as well as in user created controllers. On a negative match result, the next route in the chain is checked.
I once wrote a custom route for zend framework 1 that can handle custom restful routes. it served me well until now. see https://github.com/aporat/Application_Rest_Controller_Route for more details.
for example, if you want to have a url such as /users/30/messages mapped correctly into a zend controller action, use this route in your bootstrap:
$frontController = Zend_Controller_Front::getInstance();
$frontController->getRouter()->addRoute('users-messages', new Application_Rest_Controller_Route($frontController, 'users/:user_id/messages', ['controller' => 'users-messages']));