2017-10-29 7 views
0

저는 Laravel Lumen에 API를 가지고 있습니다. 우리는 Postman과 Ruby Rest Client를 통해 테스트하고 모두 잘 진행되지만 웹 토큰에 응답하는 간단한 인증 로그인을 생성합니다. 우리의 React App에는 실제로이 "405 405 Method Not Allowed"가 있습니다.루멘 API CORS 아약스 405 메서드가 허용되지 않습니다.

우리는 다음 코드와 클래스 생성 : 우리는 부트 스트랩에 추가

<?php namespace palanik\lumen\Middleware; 

use Closure; 
use Illuminate\Http\Response; 

class LumenCors { 

    protected $settings = array(
       'origin' => '*', // Wide Open! 
       'allowMethods' => 'GET,HEAD,PUT,POST,DELETE,PATCH,OPTIONS', 
       ); 

    protected function setOrigin($req, $rsp) { 
     $origin = $this->settings['origin']; 
     if (is_callable($origin)) { 
      // Call origin callback with request origin 
      $origin = call_user_func($origin, 
            $req->header("Origin") 
            ); 
     } 
     $rsp->header('Access-Control-Allow-Origin', $origin); 
    } 

    protected function setExposeHeaders($req, $rsp) { 
     if (isset($this->settings['exposeHeaders'])) { 
      $exposeHeaders = $this->settings['exposeHeaders']; 
      if (is_array($exposeHeaders)) { 
       $exposeHeaders = implode(", ", $exposeHeaders); 
      } 

      $rsp->header('Access-Control-Expose-Headers', $exposeHeaders); 
     } 
    } 

    protected function setMaxAge($req, $rsp) { 
     if (isset($this->settings['maxAge'])) { 
      $rsp->header('Access-Control-Max-Age', $this->settings['maxAge']); 
     } 
    } 

    protected function setAllowCredentials($req, $rsp) { 
     if (isset($this->settings['allowCredentials']) && $this->settings['allowCredentials'] === True) { 
      $rsp->header('Access-Control-Allow-Credentials', 'true'); 
     } 
    } 

    protected function setAllowMethods($req, $rsp) { 
     if (isset($this->settings['allowMethods'])) { 
      $allowMethods = $this->settings['allowMethods']; 
      if (is_array($allowMethods)) { 
       $allowMethods = implode(", ", $allowMethods); 
      } 

      $rsp->header('Access-Control-Allow-Methods', $allowMethods); 
     } 
    } 

    protected function setAllowHeaders($req, $rsp) { 
     if (isset($this->settings['allowHeaders'])) { 
      $allowHeaders = $this->settings['allowHeaders']; 
      if (is_array($allowHeaders)) { 
       $allowHeaders = implode(", ", $allowHeaders); 
      } 
     } 
     else { // Otherwise, use request headers 
      $allowHeaders = $req->header("Access-Control-Request-Headers"); 
     } 

     if (isset($allowHeaders)) { 
      $rsp->header('Access-Control-Allow-Headers', $allowHeaders); 
     } 
    } 

    protected function setCorsHeaders($req, $rsp) { 

     // http://www.html5rocks.com/static/images/cors_server_flowchart.png 
     // Pre-flight 
     if ($req->isMethod('OPTIONS')) { 
      $this->setOrigin($req, $rsp); 
      $this->setMaxAge($req, $rsp); 
      $this->setAllowCredentials($req, $rsp); 
      $this->setAllowMethods($req, $rsp); 
      $this->setAllowHeaders($req, $rsp); 
     } 
     else { 
      $this->setOrigin($req, $rsp); 
      $this->setExposeHeaders($req, $rsp); 
      $this->setAllowCredentials($req, $rsp); 
     } 
    } 

    /** 
    * Handle an incoming request. 
    * 
    * @param \Illuminate\Http\Request $request 
    * @param \Closure $next 
    * @return mixed 
    */ 
    public function handle($request, Closure $next) { 

     if ($request->isMethod('OPTIONS')) { 
      $response = new Response("", 200); 
     } 
     else { 
      $response = $next($request); 
     } 

     $this->setCorsHeaders($request, $response); 

     return $response; 
    } 

} 

을/app.php

$app->routeMiddleware([ 
    'auth' => App\Http\Middleware\Authenticate::class, 
    'cors' => palanik\lumen\Middleware\LumenCors::class, 
]); 

그리고 우리의 길 : 우리의 나머지 클라이언트와

$app->group(['middleware' => 'cors'], function($app) 
{ 
    $app->post('/auth/login', function() { 
     return response()->json([ 
      'message' => 'CORS OPTIONS Accepted.', 
     ]); 
    }); 
}); 

모두 괜찮 았어.하지만 브라우저가 OPTIONS를 보내고 요청이 POST로 전달되지 않기 때문에 React js 앱에서 어떻게 말했는지.

우리 Recat Axios의 요청 :

axios({ 
    method: 'post', 
    url: 'URL', 
    data: { 
      email: 'Fred', 
      password: 'Flintstone' 
    } 
    }).then(function (response) { 
     console.log(response); 
    }) 
    .catch(function (error) { 
     console.log(error); 
    }); 

오류 죄수 로그인 반작용 : 를 문제는 옵션이 브라우저 POST 전에 전송된다는 점이다. 헤더 응답 : HTTP/1.1 405 메서드 허용 안 함 허용 : POST 캐시 제어 : no-cache, private 내용 유형 : text/html; 우리가 누락 무엇 유지 (keep-alive)

을 : 문자셋 = UTF-8 날짜 : 2017년 10월 29일 (일) 그리니치 표준시 01시 30분 34초 서버 : 아파치/2.4.18 (우분투) 전송 - 인코딩 : 연결 청크 우리의 API에?

감사합니다.

답변

1

를 원래 요청을 보내기 전에 반작용이 경우 검사 HTTP 메소드 옵션의 요청을 전송 교차 도메인 요청은 API 서버에서 허용됩니까?

아래는 내가 다음에 방법은 다음과 같습니다

option

Route::options(
    '/{any:.*}', 
    [ 
     'middleware' => ['CorsMiddleware'], 
     function(){ 
      return response(['status' => 'success']); 
     } 
    ] 
); 

CorsMiddleware는 요청을 처리하는 데 사용되는 미들웨어 방법의 와일드 카드 경로를 추가합니다.

<?php 

namespace App\Http\Middleware; 

use Closure; 
use Illuminate\Http\Response; 

class CorsMiddleware 
{ 
    protected $settings = array(
     'origin' => '*', // Wide Open! 
     'allowMethods' => 'GET,HEAD,PUT,POST,DELETE,PATCH,OPTIONS', 
    ); 

    protected function setOrigin($req, $rsp) { 
     $origin = $this->settings['origin']; 
     if (is_callable($origin)) { 
      // Call origin callback with request origin 
      $origin = call_user_func($origin, 
         $req->header("Origin") 
        ); 
     } 
     $rsp->header('Access-Control-Allow-Origin', $origin); 
    } 

    protected function setExposeHeaders($req, $rsp) { 
     if (isset($this->settings['exposeHeaders'])) { 
      $exposeHeaders = $this->settings['exposeHeaders']; 
      if (is_array($exposeHeaders)) { 
       $exposeHeaders = implode(", ", $exposeHeaders); 
      } 

      $rsp->header('Access-Control-Expose-Headers', $exposeHeaders); 
     } 
    } 

    protected function setMaxAge($req, $rsp) { 
     if (isset($this->settings['maxAge'])) { 
      $rsp->header('Access-Control-Max-Age', $this->settings['maxAge']); 
     } 
    } 

    protected function setAllowCredentials($req, $rsp) { 
     if (isset($this->settings['allowCredentials']) && $this->settings['allowCredentials'] === True) { 
      $rsp->header('Access-Control-Allow-Credentials', 'true'); 
     } 
    } 

    protected function setAllowMethods($req, $rsp) { 
     if (isset($this->settings['allowMethods'])) { 
      $allowMethods = $this->settings['allowMethods']; 
      if (is_array($allowMethods)) { 
       $allowMethods = implode(", ", $allowMethods); 
      } 

      $rsp->header('Access-Control-Allow-Methods', $allowMethods); 
     } 
    } 

    protected function setAllowHeaders($req, $rsp) { 
     if (isset($this->settings['allowHeaders'])) { 
      $allowHeaders = $this->settings['allowHeaders']; 
      if (is_array($allowHeaders)) { 
       $allowHeaders = implode(", ", $allowHeaders); 
      } 
     } 
     else { // Otherwise, use request headers 
      $allowHeaders = $req->header("Access-Control-Request-Headers"); 
     } 
     if (isset($allowHeaders)) { 
      $rsp->header('Access-Control-Allow-Headers', $allowHeaders); 
     } 
    } 

    protected function setCorsHeaders($req, $rsp) { 
     // http://www.html5rocks.com/static/images/cors_server_flowchart.png 
     // Pre-flight 
     if ($req->isMethod('OPTIONS')) { 
      $this->setOrigin($req, $rsp); 
      $this->setMaxAge($req, $rsp); 
      $this->setAllowCredentials($req, $rsp); 
      $this->setAllowMethods($req, $rsp); 
      $this->setAllowHeaders($req, $rsp); 
     } 
     else { 
      $this->setOrigin($req, $rsp); 
      $this->setExposeHeaders($req, $rsp); 
      $this->setAllowCredentials($req, $rsp); 
     } 
    } 
    /** 
    * Handle an incoming request. 
    * 
    * @param \Illuminate\Http\Request $request 
    * @param \Closure $next 
    * @return mixed 
    */ 
    public function handle($request, Closure $next) { 
     if ($request->isMethod('OPTIONS')) { 
      $response = new Response("", 200); 
     } 
     else { 
      $response = $next($request); 
     } 
     $this->setCorsHeaders($request, $response); 
     return $response; 
    } 
} 

로드 미들웨어 $app->routeMiddleware 섹션 bootstrap/app.php

의 것은 CorsMiddleware

Route::group(['middleware' => 'CorsMiddleware'], function($router){ 
    $app->post('/auth/login', function() { 
     return response()->json([ 
      'message' => 'CORS OPTIONS Accepted.', 
     ]); 
    }); 
} 
+0

이 답변은 Lumen 5.5에 적용되었습니다. – Puneee

+0

실제로 작동합니다! 고마워, 우리는 다른 옵션과 라이브러리를 많이 시도하지만 이것은 간단하고 효과적이다. – UlyssesMarx

+0

그것이 당신을 위해 작동하는 경우 답변을 수락 할 수 있습니다 :). – Puneee

1

당신은 200 코드 다음은 유용한 예는 통합 반환해야합니다 간단한 옵션 핸들러를 추가 할 수 있습니다

https://gist.github.com/danharper/06d2386f0b826b669552

+0

내가 그 시도 검사 그룹의 모든 응용 프로그램 URL을 유지하지만 지금은 "301 영구적으로 이동"하지만 다른 사람의 작품에 도착 벌금. – UlyssesMarx