I have a symfony 2 backend and I have installed it on a server. My frontend is an ionic PWA, so it runs in browser and it is also installed on that server, but with an other subdomain. When I send a request from the web app to the backend, I'm getting this error:
OPTIONS https://api.example.com/api/login.json
XMLHttpRequest cannot load https://api.example.com/api/login.json. Response for preflight has invalid HTTP status code 405
This is my code for the login action:
/**
* Login via username and password or via API key
*
* @Doc\ApiDoc(
* section="Security",
* description="Login",
* views={"default", "security"}
* )
*
* @param ParamFetcher $params
*
* @Rest\RequestParam(name="username", nullable=true, description="Username")
* @Rest\RequestParam(name="password", nullable=true, description="Password")
* @Rest\RequestParam(name="apikey", nullable=true, description="API key (alternative to username + password)")
*
* @Rest\Post("/login", name="api_security_login", options={"method_prefix" = false})
*
* @return Response
*/
public function loginAction(ParamFetcher $params)
{
//...do some stuff here...//
$data = array(
'user' => $userValue,
'apikey' => $user->getApiKey(),
);
$groups = array('default', 'private');
return $this->createAPIResponse(self::STATUS_OK, $data, $groups);
}
This is header from the response:
Access-Control-Allow-Methods:GET,POST,OPTIONS,DELETE,PUT
Access-Control-Allow-Origin:*
Allow:POST
Cache-Control:no-cache
Connection:Keep-Alive
Content-Length:54
Content-Type:application/json
Date:Tue, 29 Aug 2017 08:33:26 GMT
Keep-Alive:timeout=5, max=100
Server:Apache
This is the error message in the prod.log file:
request.ERROR: Uncaught PHP Exception Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException: "No route found for "OPTIONS /api/login.json": Method Not Allowed (Allow: POST)" at /var/www/example.com/api/htdocs/symfony/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php line 163 {"exception":"[object] (Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException(code: 0): No route found for \"OPTIONS /api/login.json\": Method Not Allowed (Allow: POST) at /var/www/example.com/api/htdocs/symfony/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php:163, Symfony\Component\Routing\Exception\MethodNotAllowedException(code: 0): at /var/www/example.com/api/htdocs/symfony/app/cache/prod/appProdUrlMatcher.php:855)"} []
So it seems like the OPTIONS request, which is send because CORS, is not allowed, because of the "Allow" header, where only "POST" is allowed. So what is the best way to fix that for all routes?
You only have a route on your action for the
POSTmethod:@Rest\Post("/login", name="api_security_login", options={"method_prefix" = false})If you want to answer
OPTIONSrequests, you have to define an Options route using the@Rest\Optionsannotation.You can either have several annotations on the same action and test the method inside the action (typically the case with
GETandPOSTfor a form action), or define two distinct actions with the same path but different methods.http://symfony.com/doc/master/bundles/FOSRestBundle/7-manual-route-definition.html