否'Access-Control-Allow-Origin'Symfony 3和React

时间:2018-12-11 16:06:32

标签: reactjs symfony cors axios

我遇到了一个重大问题。我使用symfony 3开发了一个api。使用React在前端查询此api。背面(API)使用的服务器为http://127.0.0.1:8000。前端使用的服务器是http://localhost:3000

从前端调用api时,出现两个错误: -405方法不允许 -已通过以下方式阻止从原点“ http://127.0.0.1:8000/users/email/settings”访问“ http://localhost:3000”处的XMLHttpRequest:CORS策略:对预检检查的响应:请求中不存在“ Access-Control-Allow-Origin”标头资源。

但是,我指定了正确的方法(补丁)并通过API配置了标头:

这是详细的代码:

API(带有symfony支持)

    /**
 * @Route("/users/email/settings", methods={"PATCH"})
 * @param Request $request
 * @param FlashMessage $flashMessage
 */
public function usersEmailEditAction(Request $request, FlashMessage $flashMessage)
{
    if($request->getContent())
    {
        $data = json_decode($request->getContent(), true);

        $em = $this->getDoctrine()->getManager();

        $user = $this->get('security.token_storage')->getToken()->getUser();

        $editUser = $em->getRepository(User::class)->find($user->getId());

        if (!$editUser) {
            return $flashMessage->messageError("USER_NOT_FOUND", 1);
        }

        if (!$data['password']) {
            return $flashMessage->messageError("PASSWORD_NOT_FOUND", 1);
        }

        if (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
            return $flashMessage->messageError("INVALID_EMAIL", 1, "format email invalid");
        }

        if (!filter_var($data['confirmEmail'], FILTER_VALIDATE_EMAIL)) {
            return $flashMessage->messageError("INVALID_EMAIL", 1, "format email invalid");
        }

        if ($data['email'] != $data['confirmEmail']) {
            return $flashMessage->messageError("NO_MATCHING_EMAIL", 1, "les emails sont différents");
        }

        // on vérifie le mot de passe
        $encoder = $this->get('security.password_encoder');

        $isPasswordValid = $encoder->isPasswordValid($user, $data['password']);

        // Le mot de passe n'est pas correct
        if (!$isPasswordValid) { 
            return $flashMessage->messageError("INCORRECT_PASSWORD", 1);
        }

        $editUser->setEmail($data['email']);
        $editUser->setUpdatedAt(new \DateTime());

        $em->flush();

        return $flashMessage->messageSuccess("EMAIL_UPDATED_SUCCESSFULLY", 0);



    }else {
        return $flashMessage->messageWarning("NOTHING_UPDATED", 2);
    }
}

返回$ flashMessage

    public function messageSuccessAction($message, $code, $desc = null)
{
    $response = new Response();
    $response->setContent(json_encode([
        'error' => $code,
        'message' => $message
    ]));

    $response->headers->set('Content-Type', 'application/json');
    $response->headers->set('Access-Control-Allow-Origin', 'http://localhost:3000');
    $response->headers->set('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, PATCH, OPTIONS'); 

    return $response;

    //return new JsonResponse(array("error" => $code, "message" => $message));
}

public function messageErrorAction($message, $code, $desc = null)
{
    $response = new Response();
    $response->setContent(json_encode([
        'error' => $code,
        'message' => $message
    ]));

    $response->headers->set('Content-Type', 'application/json');
    $response->headers->set('Access-Control-Allow-Origin', 'http://localhost:3000');
    $response->headers->set('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, PATCH, OPTIONS'); 

    return $response;

    //return new JsonResponse(array("error" => $code, "message" => $message));
}

public function messageWarningAction($message, $code, $desc = null)
{

    $response = new Response();
    $response->setContent(json_encode([
        'error' => $code,
        'message' => $message
    ]));

    $response->headers->set('Content-Type', 'application/json');
    $response->headers->set('Access-Control-Allow-Origin', 'http://localhost:3000');
    $response->headers->set('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, PATCH, OPTIONS'); 

    return $response;
    //return new JsonResponse(array("error" => $code, "message" => $message));
}

从Front请求API(使用Axios)

    requestAPI = (myPassword, newEmail, confirmEmail) => {
    axios.patch('http://127.0.0.1:8000/users/email/settings', {
        crossdomain: true,
        password: myPassword,
        email: newEmail,
        confirmEmail: confirmEmail
      })
      .then(function (response) {
        console.log(response);
      })
      .catch(function (error) {
        console.log(error);
      });
}

我也尝试了没有跨网域,但是没有。

你有什么主意吗?谢谢您的帮助

1 个答案:

答案 0 :(得分:0)

是否有405 Method Not Allowed通话获得了OPTIONS的通话?也称为"preflight request"

对于您的所有CORS需求,您都应该包括NelmioCorsBundle,它很容易配置,并且您不需要设置自己的CORS标头。

这里发生的是,您的浏览器将首先通过OPTIONS调用检查服务器是否理解CORS协议。但是您的应用程序并没有回答这一问题,至少没有正确的CORS标头,因此您的PATCH调用永远不会被浏览器发出。错误消息甚至如此。 “响应飞行前检查:所请求的资源上没有'Access-Control-Allow-Origin'标头。”