Description
Q | A |
---|---|
Bug report? | no |
Feature request? | yes |
BC Break report? | unsure |
RFC? | unsure |
Symfony version | 2.8.33 |
I have a version v2 of an API which has majority routes going back to V1, except for a few .
For v2
v2_rest_save_adresses:
pattern: api/v2/addresses
defaults:
_controller: Symfony\Bundle\FrameworkBundle\Controller\RedirectController::redirectAction
route: rest_save_adresses
permanent: false
For V1
rest_save_adresses:
pattern: api/v1/addresses
defaults: { _controller: XYZRestBundle:Address:create}
methods: [POST]
The GET requests get redirected with 302 code successfully, while the post requests see an error like this
No route found for "GET /api/v1/addresses": Method Not Allowed (Allow: POST)
The class that does the routing has handling only for parameters 301 and 302.
/**
* Redirects to another route with the given name.
*
* The response status code is 302 if the permanent parameter is false (default),
* and 301 if the redirection is permanent.
*
* In case the route name is empty, the status code will be 404 when permanent is false
* and 410 otherwise.
*
* @param Request $request The request instance
* @param string $route The route name to redirect to
* @param bool $permanent Whether the redirection is permanent
* @param bool|array $ignoreAttributes Whether to ignore attributes or an array of attributes to ignore
*
* @return Response A Response instance
*
* @throws HttpException In case the route name is empty
*/
public function redirectAction(Request $request, $route, $permanent = false, $ignoreAttributes = false)
{
if ('' == $route) {
throw new HttpException($permanent ? 410 : 404);
}
$attributes = array();
if (false === $ignoreAttributes || is_array($ignoreAttributes)) {
$attributes = $request->attributes->get('_route_params');
unset($attributes['route'], $attributes['permanent'], $attributes['ignoreAttributes']);
if ($ignoreAttributes) {
$attributes = array_diff_key($attributes, array_flip($ignoreAttributes));
}
}
return new RedirectResponse($this->container->get('router')->generate($route, $attributes, UrlGeneratorInterface::ABSOLUTE_URL), $permanent ? 301 : 302);
}
This is the reason that a request that is post and that should be redirected with 307 status code is not redirected at all, leading to even POST requests getting transferred as GET.
I just changed line return new RedirectResponse($this->container->get('router')->generate($route, $attributes, UrlGeneratorInterface::ABSOLUTE_URL), $permanent ? 301 : 302);
To
return new RedirectResponse($this->container->get('router')->generate($route, $attributes, UrlGeneratorInterface::ABSOLUTE_URL), 307);
And this works well ( of course not completely correct). I think this needs an enhancement to even allow POST requests to be redirected.
Proposed solution : (Since I have not learned the pull process completely)
public function redirectAction(Request $request, $route, $permanent = false, $postOrPut = false, $ignoreAttributes = false)
{
if ('' == $route) {
throw new HttpException($permanent ? 410 : 404);
}
$attributes = array();
if (false === $ignoreAttributes || is_array($ignoreAttributes)) {
$attributes = $request->attributes->get('_route_params');
unset($attributes['route'], $attributes['permanent'], $attributes['ignoreAttributes']);
if ($ignoreAttributes) {
$attributes = array_diff_key($attributes, array_flip($ignoreAttributes));
}
}
if (true == $postOrPut)
$code = 307;
else $code = $permanent ? 301 : 302;
return new RedirectResponse($this->container->get('router')->generate($route, $attributes, UrlGeneratorInterface::ABSOLUTE_URL), $code);
}
And in routing use this for POST```
v2_rest_save_adresses:
pattern: api/v2/addresses
defaults:
_controller: Symfony\Bundle\FrameworkBundle\Controller\RedirectController::redirectAction
route: rest_save_adresses
postOrPut: true
And for GET it is same as before