I have a bundle AcmeDemoBundle. I would like it to use both annotations within a controller and a routing.yml file for routes. If I use the CRUD generator, I like how it already defines my routes, takes care of all my work and for those pages that done really need CRUD components, like say an About us page, it would be better off creating a route in routing.yml.
app/config/routing.yml:
AcmeDemoBundle:
resource: "#AcmeDemoBundle/Resources/config/routing.yml"
resource: "#AcmeDemoBundle/Controller"
type: annotation
prefix: /
This returns errors so I know it is wrong, if I take off one resource the other does not work :(. Please let me know if there is a way to do this.
I could be wrong, but I don't think it's possible to use both yml routes and annotation routes in the same bundle. I remember trying to get it to work myself and not having much luck. But even if it is possible, I would recommend sticking with one format. You may be able to keep track of where each route is defined right now, but as the project becomes more complex (read: more routes) and time goes on, you'll have a tougher time keeping track of where each route is defined. When you have to revisit the project 6 months later, you'll be glad you only have routes defined in one place. This is also important if other people are going to work with this code - it'd be much easier for them if the routes were all defined in the same fashion.
You need to do something like that
acme_test:
resource: "#AcmeDemoBundle/Resources/config/routing.yml"
prefix: /
acme_dummy:
resource: "#Acme/Controller/DummyController.php"
type: annotation
prefix: /
Related
What's the appropriate way to make a Servant handler respond with a redirection? I am working in a navigation REST app and I would like to respond to POST requests that create resources with a redirection to the corresponding GET resource list paths. So for instance POST /foos should redirect to GET /foos after creating a foo. I could not find a clear way to do that in the documentation.
There is one simple (but slightly hacky) answer, and a lead for making the first option obsolete (EDIT: and a third, better option, actually).
The current typical solution for this is to simply use the fact that the Handler monad has a MonadError ServantErr instance, and that ServantErr is a very general "response type" that can indeed describe the HTTP response for an application error, but also a redirect or many other things really. So you can do something like throwError $ err301 { errHeaders = [("Location", "https://haskell.org/")] }. It's ugly because we hijack the "erroring out" bit for some successful workflow. But it works, and is a single line of code.
I have explored alternative approaches, that let you mix type-safe links with redirects to easily redirect to other endpoints/pages of your app. This is outdated now but could probably be made to work without toooo much trouble.
And upon seeing this question, I just now thought of a third option. Took a bit of time to experiment with it and looks like it works! You can see the code with an example of using it in this gist. Let me know if you have any question. We might want to add some of this to servant. Feel free to bring it up on the issue tracker if you think this is good enough. The gist of this approach is to define a custom PostRedirect that has the right shape (no response body, a Location header with a type of your choice, and parametrized by the status code that you want your redirect to use), and a little function that wraps the location appropriately before returning.
Say I want to have an apparent directory that, via the browser, is http://whatever/images/
But on the file system, it actually draws from both /Users/me/www/images and /Users/me/moreimages/. So if I request http://whatever/images/selfie.jpg, it will first look for /Users/me/www/images/selfie.jpeg, and if that isn't found, serve /Users/me/moreimages/selfie.jpeg instead.
I can think of some ugly ways of doing this, handling the routing and serving myself, but I'd like to do it in the most "correct" and hopefully straightforward way. Does express have some workaround where I can cause it to do this?
Yes, this is possible. Just have two instances of express.static both mounted on /images:
router.use('/images', express.static('/Users/me/images/'));
router.use('/images', express.static('/Users/me/moreimages/'));
If the request is not satisfied in the first instance of the middleware, the second one will be processed, and so on.
In Express.js, is there a standard way to re-order the middleware registered on an express#Router object? I have a situation where it is possible to dynamically register static asset directories that should be served by the app via express.static(). However, the Router#use() method (which I'm using to register the new asset directories) always puts middleware at the end of Router#stack. I want this to be at the beginning. Is there any way to achieve this?
I have a working implementation that basically traverses the current Router's stack in reverse, picks the first middleware called staticMiddleware, and moves it from that location to the front of the array. This works, but is obviously dependent on the internals of Route. I'm hoping there's another, more standard way to achieve the same behavior.
You probably want to just have a custom route at the beginning of the order that can examine the path, compare it to a list of directories you want to serve (that can change over time) and then serve the static content if its path matches.
This would just be a smarter version of express.static() that works off a dynamic path list rather than only a pre-defined path. There isn't much to express.static() so you can just copy it into your function and make it smarter.
It is apparently possible to crack into the stack of middleware and modify the order. I don't know if this is a supported capability or just something unsupported that people have figured out (that could break in the future). Here's one article that discusses this: https://www.exratione.com/2013/03/nodejs-abusing-express-3-to-enable-late-addition-of-middleware/
we have a relatively complex (10 controllers, about 25 views) contest website. Contest will be over soon and we are required to put a "contest is closed" page to be displayed instead of all other pages. But with few exceptions - for example, Contest/Rules should still display the rules.
To rephrase it - how can I make sure that no action will be called from any of the controller except the ones I somehow specify? Basically I need something like this in my routing table:
if (requestedAction is Contest/Rules)
allow;
else
redirect to Contest/Closed;
Add one more controller and bind it with desired view, specify this controller in routes.
You are looking for too much easy way.
[Wanted to add as comment, but can not because stupid reputation policy]
I've been on a mission to learn everything about Yesod, and I'm (somewhat) stuck on the routing system and it's relation to subsites and cross-route linking in general. The first thing I would like to address is the "ResourceR" pattern found throughout the route definitions and Hamlet links.
I notice that the "type" itself (ResourceR) is never addressed or referenced outside of Yesod's TH DSL's. Does this mean that it's only really used as a dummy type, meant only for leveraging Haskell's type safety in referencing Yesod links? I also notice that the functions getResourceR, postResourceR etc. are vital for the app to work, yet it's not explicit where their definitions are used in boilerplate app code. Does Yesod simply reduce the calls to #{ResourceR} to the appropriate function?
I keep feeling like I should be defining ResourceR myself as a datatype, when in fact it's generated and reduced internally by Yesod.
So my question is: do the "resource types" referenced in Hamlet and Route code get automatically generated and reduced by Yesod's DSL's?
Thank you in advance!
Yesod indeed expands what it sees in the the routes file (or what you type in the parseRoutes function in a quasiquotes section), and gives the server the appropriately named get or post function (by prefixing "get" or "post" to the resource name). All that you need to do is create the get/post function, and the framework will use the routes to call the function for you. You need only specify the path and request type.
Centralizing all path information in one location like this makes it easy for you to debug where an individual request will go (think of what the alternative spaghetti code would look like). The forced name standards also keep your code understandable, and code generation removes some of the repetition (ie- it helps you adhere to the dry principle).