Override default of ".{_format}" in routes using FOSRestBundle and Symfony2 - symfony

I am wondering if it is possible to define routes in FOSRestBundle methods that specify the format with something other than a "dot" preceding them.
For example, suppose I'd like the following to work:
http://somesite.com/api/user/20 (renders in the default/fallback format)
http://somesite.com/api/user/20/json (renders in JSON)
http://somesite.com/api/user/20/xml (renders in XML)
If I attempt to define a route like:
/**
* #Get("/user/{id}/{_format}
*/
public function getUserAction($id)
{
// do stuff
}
I get this:
Route pattern "/api/users/{maximum}/{_format}.{_format}" cannot reference variable name "_format" more than once.
That made me realize that it -- and by it, I assume we are talking FOSRestBundle and not Symfony2 by default -- is automatically adding the ".{_format}" to the end of whatever route I define. I was surprised!
So right now, in my earlier example, it works as follows:
http://somesite.com/api/user/20 (renders in the default/fallback format)
http://somesite.com/api/user/20.json (renders in JSON)
http://somesite.com/api/user/20.xml (renders in XML)
A small difference to be sure, but, I am trying to port over a legacy app that uses this syntax. Is what I am trying to do possible? If so, how can I disable that automatic addition of ".{_format}" to each route?
Thanks!

Over a year has passed and FOSRestBundle now supports the feature I was looking for above.
You can control this behavior via the following configuration:
fos_rest:
routing_loader:
default_format: ~
include_format: true
Set the include_format to false to remove the format from the route.
You can view the expanded configuration options for FOSRestBundle here.

Related

How to make a part of URL as optional in asp.net core 3+ web api and regex route attribute?

I am using the following regex in route and I want to support these routes
/en-gb/api/cat/...
/th-th/api/cat/...
/api/cat/...
I am not able to support the URL path without locale i.e /api/cat/... I tried to put the locale part in my regex as option by using ?. I tried in regex 101 and tested my regex it works fine (Note [ and { becomes [[ and {{ in .net core API routes)
[ApiController]
[Route("/{url:regex([[a-zA-Z]]{{2}}-[[a-zA-Z]]{{2}})?}/api/cat/")]
public class CatApiController : ControllerBase
This looks like a basic usecase, but I am not able to figure it out. Can someone please help guide me on this.
EDIT -
[Route("{locale?}/api/cat/")]
I also try this, but it does not work for the URL without locale, even after making the locale optional.
it does not work for the URL without locale, even after making the locale optional
You can try to define multiple routes as below.
[ApiController]
[Route("/api/cat")]
[Route("{locale?}/api/cat")]
public class CatApiController : ControllerBase
{
//...

openapi documentation how to handle extension in the path

I have URLs like:
/return/{pid}.xml?d1='123'&d2='345'
/return/{pid}.json?d1='123'&d2='345'
the swagger specification calls for:
path:/return/{pid}
....
but how can I map the extension ie
path:/return/{pid}.xml
or
path:/return/{pid}.json
It is a jersey+spring mvc application - so both the URLs are hitting the same controller and only based on the extension the rest framework is going to generate the xml / json output.
I can't ignore the extension from the path ie:
path:/return/{pid}
because the user needs to know that he/she has to provide the file extension as part of the URL. Also I can't use two paths corresponding to xml / json because they are treated the same by the application. In addition it will duplicate things (I am not sure whether there is a fall-through like mechanism just like "case" statements in c++/java "switch" block)
In Swagger specs,You can define the file extensions in the path as below :
/return/{pId}.{fileExtension}
and define the fileExtension in parameters .
also the below is valid (not for your case) :
/return/pid.{fileExtension}

Translated Symfony routes with multiple parameters

As the title suggests, I'm using Symfony in conjunction with the JMSTranslationBundle and JMSI18nBundle in order to serve translated routes.
Here's my currently configured route:
/{location}/{profession}/{specialty}
So the route
/berlin/arzt/allgemein
is successfully pushed to the correct controller and action.
The JMSI18nBundle is automagically prefixing my English routes with /en/. This works for every other route with a non-dynamic component (such as /profile/{slug}/). This DOES NOT work, however, when using the English version of the above example. i.e.
/en/berlin/doctor/general
I'm guessing the router is not reading this properly as the English version of the normal route, and instead tries to assign location = en, profession = berlin, etc, which is obviously incorrect.
I've tried defining optional parameters, more complicated regexes, and trailing slashes for the translation (all with cache flushes in between). None of this works. What DOES work, is inserting a pointless non-dynamic component, i.e. /en/s/berlin/doctor/general etc
As a part of the business requirements, we don't want this additional pointless non-dynamic URL component.
So, my question is: how can I use (prefixed) translatable URLs in Symfony that contain nothing but dynamic fields?
Your help is greatly appreciated!
Solved:
As is the norm with Friday-afternoon problems, I found I had a $ inside my translated route rule, like so:
/{location}/{$profession}/{specialty}
Removing it and flushing the cache resulted in the route working.
tl;dr - PEBKAC

Symfony2 GenerateURL to a complex route

This seems like the dumbest question ever, but I can't seem to figure it out. I have a page the needs to redirect to a complex route and I can't seem to generate the URL. Redirecting to a simple route is easy enough:
return $this->redirect($this->generateUrl('testnumber'));
However, I want to route to: testnumber/1/question/4. How can I accomplish this incredibly simple task? The only thing I have found in the documentation and Google allows me to add parameters and not just create a complex route. For example:
generateURL('testnumber', array('testid'=>1, 'question'=>4))
makes a URL of /testnumber?testid=1&question=4, which I do not want.
Edit: Yes, I already have the route created in a YML file. I simply cannot generate the URL to link to it.
return $this->redirect($this->generateUrl(???????????),true));
This is my route:
#Route("/testnumber/{testid}/question/{question}", name="testnumber")
The Symfony documentation only shows how to generate a URL to " testnumber/1", I need to generate "testnumber/1/question/4".
For
generateURL('testnumber', array('testid'=>1, 'question'=>4))
to work as you want, your route must look like (example using annotations)
#Route("/testnumber/{testid}/question/{question}", name="testnumber")
If you don't define "testid" & "question" parameters in your route, they'll be added to the query string (appended at the end of the URL as GET paramaters)
generated_route?test_id=X&question=X
Find here more relevent examples.

IgnoreRoute with webservice - Exclude asmx URLs from routing

Im adding the filevistacontrol to my asp.net MVC web application.
I have a media.aspx page that is ignored in the routing with
routes.IgnoreRoute("media.aspx");
This works successfully and serves a standard webforms page.
Upon adding the filevistacontrol, I can't seem to ignore any calls the control makes to it's webservice.
Eg the following ignoreRoute still seems to get picked up by the MvcHandler.
routes.IgnoreRoute("FileVistaControl/filevista.asmx/GetLanguageFile/");
The exception thrown is:
'The RouteData must contain an item named 'controller' with a non-empty string value'
Thanks in advance.
Short answer:
routes.IgnoreRoute( "{*url}", new { url = #".*\.asmx(/.*)?" } );
Long answer:
If your service can be in any level of a path, none of these options will work for all possible .asmx services:
routes.IgnoreRoute("{resource}.asmx/{*pathInfo}");
routes.IgnoreRoute("{directory}/{resource}.asmx/{*pathInfo}");
By default, the parameters in a route pattern will match until they find a slash.
If the parameter starts with a star *, like pathInfo in those answers, it will match everything, including slashes.
So:
the first answer will only work for .asmx services in the root path, becasuse {resource} will not match slashes. (Would work for something like http://example.com/weather.asmx/forecast)
the second one will only work for .asmx services which are one level away from the root.{directory} will match the first segment of the path, and {resource} the name of the service. (Would work for something like http://example.com/services/weather.asmx/forecast)
None would work for http://example.com/services/weather/weather.asmx/forecast)
The solution is using another overload of the IgnoreRoute method which allows to specify constraints. Using this solution you can use a simple pattern which matches all the url, like this: {*url}. Then you only have to set a constraint which checks that this url refers to a .asmx service. This constraint can be expressed with a regex like this: .*\.asmx(/.*)?. This regex matches any string which ends with .asmx optionally followed by an slash and any number of characters after it.
So, the final answer is this:
routes.IgnoreRoute( "{*url}", new { url = #".*\.asmx(/.*)?" } );
I got it to work using this (a combo of other answers):
routes.IgnoreRoute("{directory}/{resource}.asmx/{*pathInfo}");
What happens when you use:
routes.IgnoreRoute("FileVistaControl/filevista.asmx");
If that doesn't work, try using the ASP.NET Routing Debugger to help you:
http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx
Try this:
routes.IgnoreRoute("{*filevista}", new { filevista = #"(.*/)?filevista.asmx(/.*)?" });
This is based on a Phil Haack recommendation stated here.
Have you tried:
routes.IgnoreRoute("{resource}.aspx/{*pathInfo}");
routes.IgnoreRoute("{resource}.asmx/{*pathInfo}");
It would help if you posted the source for your route configuration. I'm going to take a shot in the dark and say to make sure that your IgnoreRoute() calls are all at the top of your routing definition.
The way IgnoreRoute works is to create a route that matches the ignored route URL and constraints, and attaches a StopRoutingHandler as the RouteHandler. The UrlRoutingModule knows that a StopRoutingHandler means it shouldn't route the request.
As we know, the routes are matched in the order of which they are defined. So, if your {controller}/{action}/{id} route appears before your "FileVistaControl/filevista.asmx/GetLanguageFile/" route, then it will match the "{controller}/{action}/{id}" route.
I may be totally off base here, but it's hard to know without seeing your source. Hope this helps. And post source code! You'll get better answers.

Resources