I want to build RESTful API with URLs something like:
First route: http://example.com/api/{element_name}/aaa/{related_name} and
Second route: http://example.com/api/{element_name}/bbb/{related_name}.
Everything is simple and easy when element_name is integer or simple text.
Things get complicated when parameter {element_name} has "/" char in the name, because even if I encode / by %2f (url encode) routing will decode %2f before process routes.
For example when I want to generate URL to first route and I have {element_name} = xyz and {related_name} = ooo then the URL will be http://example.com/api/xyz/aaa/ooo and it's OK.
But when I have {element_name} = xyz/bbb and {related_name} = ooo then the URL should be: http://example.com/api/xyz%2fbbb/aaa/ooo but routing first will decode url and make: http://example.com/api/xyz/bbb/aaa/ooo and it isn't OK because doesn't match to first route.
How I should do that?
All you need to do is to add requirement while configuring the routes in your controller. Like so :
class DefaultController
{
/**
* #Route("/share/{token}", name="share", requirements={"token"=".+"})
*/
public function share($token)
{
// ...
}
}
it's explained in the SF doc: http://symfony.com/doc/current/routing/slash_in_parameter.html
Related
I have a Symfony Route configured with annotations where I want the last parameter to allow for slashes in it.
#[Route('/getFtp/{customerName}/{taskId}/{domainName}', name: 'get_ftp', requirements: ['domainName' => '.+'])]
public function index(string $customerName, string $taskId, string $domainName): Response
According to documentation https://symfony.com/doc/6.0/routing.html#slash-characters-in-route-parameters this should work.
It works for
http://mgr2.example.com/getFtp/quadramedia/abcdef/http:
but not for
http://mgr2.example.com/getFtp/quadramedia/abcdef/http:%2F
Using your exemple in my own project worked.
I tryied this url http://127.0.0.1:8080/getFtp/thomas/23/http:%2F
And then i dumped my param to be sure and got :
So, it is on your project that something is wrong.
I expect something like an other route is matching.
Try to define the route in yaml (or just on top of your controller) and put it on top of all the other to be completely sure that this is not working.
By the way, i tried your case in php 8.1 and Symfony 6.2
It works in Symfony 5.x versions. I would suggest take domainName as a request parameter in an argument. For example:
#[Route('/getFtp/{customerName}/{taskId}', name: 'get_ftp')]
public function index(string $customerName, string $taskId, Request $request): Response
{
$domainName = $request->query->get('domainName');
...
}
My case is the following:
I have a Shopware Bundle and i need to change/extend the routing in such a way that if a request URL contains a keyword "xyz", the request is forwarded to a controller in my bundle without checking further if the route is available in "static routes" for example.
For instance: "/xyz/1/lorem/3" or "/xyz/5/3/ipsum" etc. all need to be rerouted to the controller in my bundle, since they contain the keyword /xyz.
Is there a service i can overwrite/decorate or something similar where i can implement this behaviour?
You can have a placeholder in your route with a default and a requirement allowing for all characters:
/**
* #Route("/xyz{anything}", name="frontend.my.action", methods={"GET"}, defaults={"anything"=""}, requirements={"anything"=".+"})
*/
public function myAction(Request $request): Response
{
$anything = $request->get('anything');
// ...
}
This will match any url starting with /xyz and every set of characters that follows afterwards is considered to be part of anything.
I have a .Net core 2.2 WebAPI that works perfectly fine with "normal" style URLs e.g. /api/controller/action/param etc. I have a 3rd party service that does a POST to this API with a URL encoded path and the Asp.Net routing fails to route this request correctly.
The controller is at: .../api/file/uploadFile/{filename}
The POST from the 3rd party is:
".../api%2Ffile%2FuploadFile%2FMaintenanceReport_2019_08_05_17_11_10.html.gz".
Replacing the %2F in the path appears to work as expected:
".../api/file/uploadFile/MaintenanceReport_2019_08_05_17_11_10.html.gz"
The filename is: "MaintenanceReport_2019_08_05_17_11_10.html.gz"
Placing a Route Attribute with %2F instead of "/" sort of works, but looks very messy.
The filename passed into the path is also not resolving correctly as a parameters. I suspect this is due to the file extension being included.
I've searched the net and did not find anything related jumping out at me. Any suggestions/ideas?
[Route("api/[controller]/[action]")]
[Route("api%2F[controller]%2F[action]")]
public class FileController : Controller
{
...
}
I would have thought that the .Net core routing engine would detect the path
The default path separator in the url generated by the route is / .The issue seems that the separator before the parameter which is as part of the path value is not recognized or missing .
If you request the url like .../api%2Ffile%2FuploadFile%2FMaintenanceReport_2019_08_05_17_11_10.html.gz , you could try to use URL Rewriting Middleware like below :
In Configure
app.UseRewriter(new RewriteOptions()
.Add(RewriteRouteRules.ReWriteRequests)
);
2.Custom a class containing ReWriteRequests
public class RewriteRouteRules
{
public static void ReWriteRequests(RewriteContext context)
{
var request = context.HttpContext.Request;
if (request.Path.Value.Contains("%2F", StringComparison.OrdinalIgnoreCase))
{
context.HttpContext.Request.Path = context.HttpContext.Request.Path.Value.Replace("%2F", "/");
}
}
}
Reference: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/url-rewriting?view=aspnetcore-2.1&tabs=aspnetcore2x
We have files behind authentication, and I want to do different things for post-authentication redirect if the user entered the application using a URL of a file versus a URL of an HTML resource.
I have a URL: https://subdomain.domain.com/resource/45/identifiers/567/here/11abdf51e3d7-some%20file%20name.png/download. I want to get the route name for this URL.
app/console router:debug outputs this: _route_name GET ANY subdomain.domain.{tld} /resource/{id2}/identifiers/{id2}/here/{id3}/download.
Symfony has a Routing component (http://symfony.com/doc/current/book/routing.html), and I'm trying to call match() on an instance of Symfony\Bundle\FrameworkBundle\Routing\Router as provided by Symfony IOC. I have tried with with the domain and without the domain, but they both create a MethodNotAllowed exception because the route cannot be found. How can I match this URL to a route?
Maybe a bit late but as I was facing the same problem, what I come to is something like
$request = Request::create($targetPath, Request::METHOD_GET, [], [], [], $_SERVER);
try {
$matches = $router->matchRequest($request);
} catch (\Exception $e) {
// throw a 400
}
The key part is to use $_SERVER superglobal array in order to have all things setted straight away.
According to this, Symfony uses current request's HTTP method while matching. I guess your controller serves POST request, while your download links are GET.
The route name is available in the _route_name attribute of the Request object: $request->attributes->get('_route_name').
You can do something like this ton get the route name:
public/protected/private function getRefererRoute(Request $request = null)
{
if ($request == null)
$request = $this->getRequest();
//look for the referer route
$referer = $request->headers->get('referer');
$path = substr($referer, strpos($referer, $request->getBaseUrl()));
$path = str_replace($request->getBaseUrl(), '', $lastPath);
$matcher = $this->get('router')->getMatcher();
$parameters = $matcher->match($path);
$route = $parameters['_route'];
return $route;
}
EDIT:
I forgot to explain what I was doing. So basicly you are getting the page url ($referer) then taking out your website's base url with str_replace and then trying to match the remaining part of the path with a know route pattern using route matcher.
EDIT2:
Obviously you need to have this inside you controller if you want to be able to use $this->get(...)
I need to compare these two strings, so for example:
if($this->getRequest()->headers->get('referer') != $this->generateUrl('foo')) {}
The thing is that the referrer here gives me the full url address:
http://website.com/foo
And the generateUrl() method gives me only the following:
/foo
How can I solve this?
You can generate an absolute url using:
$this->generateUrl('route_name', $parameters, true))
$parameters can be null ... see the API reference.