Заголовки Cors не добавлены к ответу - PullRequest
0 голосов
/ 15 апреля 2019

При попытке войти в систему с помощью API (размещенного локально) из приложения React я получаю эту ошибку каждый раз:
Error image

Я знаю много тем на эту тему, но ни одна из них мне не помогла. Возможно, потому что я что-то пропустил, или не понимаю концепции.

Понятия не имею, как это исправить.

То, что я уже пробовал:
- Добавлено промежуточное ПО HTTP (код будет следовать): не работает.
- Попытка исправить это с помощью пакета spatie/laravel-cors: не работает.
- Попытка исправить это с barryvdh/laravel-cors: тоже не сработало.

У меня нет идей. Кто-то знает, что я делаю не так?

Мой код

protected $middleware = [
    \App\Http\Middleware\CheckForMaintenanceMode::class,
    \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
    \App\Http\Middleware\TrimStrings::class,
    \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
    \App\Http\Middleware\TrustProxies::class,
    \Spatie\Cors\Cors::class, // <-- this line would be pointed to my own middleware when that would be in use
];

Следующий код указывает вместо \Spatie\Cors\Cors::class, если я использую свое промежуточное ПО

class ApiCors
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        return $next($request)
            ->header('Access-Control-Allow-Origin', '*')
            ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS, PATCH')
            ->header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');

    }
}

1 Ответ

1 голос
/ 16 апреля 2019

Есть несколько хитростей с реализацией поддержки CORS:

  1. Ваше промежуточное ПО CORS должно быть добавлено в глобальный стек промежуточного ПО, поскольку браузер может отправлять запрос Preflight, иВы не хотели бы иметь конкретный маршрут OPTIONS для каждого маршрута API.

  2. Промежуточному программному обеспечению не требуется передавать запрос предполетной проверки глубже в приложение.

  3. Заголовок (и) CORS должен быть добавлен как к запросам предполетной проверки, так и к запросу API.

Итак, вот как это должно быть сделано:

Создать промежуточное ПО:

php artisan make:middleware ApiCors

Поставить код:

<?php

namespace App\Http\Middleware;

use Closure;

class ApiCors {

  /**
   * Handle an incoming request.
   *
   * @param  \Illuminate\Http\Request $request
   * @param  \Closure $next
   *
   * @return mixed
   */
  public function handle($request, Closure $next)
  {
    $isPreflight = $request->isMethod('options') && $request->hasHeader('origin');

    // we don't need to process Preflight request further
    $response = $isPreflight ? response()->make() : $next($request);

    if($isPreflight) {
      $response
        ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS, PATCH')
        ->header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization')
        ->header('Access-Control-Max-Age', 86400);
    }
    $response->header('Access-Control-Allow-Origin', $isPreflight ? '*' : ($request->header('origin') ?? '*'));

    return $response;
  }
}

Зарегистрировать промежуточное ПО:

app/Http/Kernel.php:

<?php
// ...
use App\Http\Middleware\ApiCors;

class Kernel extends HttpKernel {
  // ...
  protected $middleware = [
    // ...
    ApiCors::class,
  ];
  // ...
  protected $middlewarePriority = [
    ApiCors::class, // move to the top of the chain
    // ...
  ];
}

Промежуточное ПО для тестирования:

Давайте добавим простой маршрут API.

routes/api.php:

Route::put('/v1/test', function () {
  return response()->json(['answer' => 42]);
});

Давайте запустим простой сервер (запустите в корневой папке проекта Laravel):

php -S localhost:8088 -t public

Далее откройте любую веб-страницу (или используйте текущую) и запустите в консоли разработчика:

fetch('http://localhost:8088/api/v1/test', {
  method: 'PUT', headers: { 'accept': 'application/json' }
}).then(r => r.json()).then(console.log.bind(console))

Вы должны получить ответ:

{answer: 42}

Не забудьте, что вы должны добавить свои [внешние] маршруты API к routes/api.php, , а не к routes/web.php, поскольку в группе веб-маршрутизаторов имеется множество промежуточных программ, которые могут создавать помехи вашим API, например, VerifyCsrfToken.

MDN: Обмен ресурсами между источниками (CORS)

...