2

在此处发布之前,我确保在网上查找可能的问题解决方案。

我将 NuxtSSR用于前端,并将 Laravel 7 作为后端 API,它现在具有本机 CORS 实现。我的前端应用程序在运行,http://localhost:3030api 在http://gaminghub.test.

这是我在cors.php最新版本的 laravel 中所拥有的:

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Cross-Origin Resource Sharing (CORS) Configuration
    |--------------------------------------------------------------------------
    |
    | Here you may configure your settings for cross-origin resource sharing
    | or "CORS". This determines what cross-origin operations may execute
    | in web browsers. You are free to adjust these settings as needed.
    |
    | To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
    |
    */

    'paths' => ['api/*'],

    'allowed_methods' => ['*'],

    'allowed_origins' => ['*'],

    'allowed_origins_patterns' => [],

    'allowed_headers' => ['*'],

    'exposed_headers' => false,

    'max_age' => false,

    'supports_credentials' => true,

];

使用邮递员,这是发送获取请求时返回的内容http://gaminghub.test/api/products?category=play-card

{
    "data": [
        {
            "id": 1,
            "name": "Xiaomi",
            "price": 2000000,
            "description": "Best value for money",
            "slug": "xiaomi"
        }
    ],
    "links": {
        "first": "http://gaminghub.test/api/products?page=1",
        "last": "http://gaminghub.test/api/products?page=2",
        "prev": null,
        "next": "http://gaminghub.test/api/products?page=2"
    },
    "meta": {
        "current_page": 1,
        "from": 1,
        "last_page": 2,
        "path": "http://gaminghub.test/api/products",
        "per_page": 1,
        "to": 1,
        "total": 2
    }
}

nuxt.config.js 包括:

  /*
   ** Axios module configuration
   ** See https://axios.nuxtjs.org/options
   */
  axios: {
    baseURL: "http://gaminghub.test/api",
    credentials: true
  },

product.vue包含以下内容以检索数据:

<script>
export default {
    data() {
    return {
      product: null
    }
  },

  async asyncData({params, app}) {
    let res = await app.$axios.$get(`products/?category=${params.slug}`)

    return {
      product: res.data
    }
  },
}
</script>

所以,基本上,当我点击每个类别时,他们会发送一个 get 请求api/products?category=clicked-category-slug,导致控制台出现以下错误:

Access to XMLHttpRequest at 'http://gaminghub.test/api/products/?category=play-card' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.

网络请求标头包含以下内容:

Request Headers Provisional headers are shown Accept: application/json, text/plain, */* Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9nYW1pbmdodWIudGVzdFwvYXBpXC9hdXRoXC9sb2dpbiIsImlhdCI6MTU4MzU3MjQ4MiwiZXhwIjoxNTgzNTc2MDgyLCJuYmYiOjE1ODM1NzI0ODIsImp0aSI6ImdYY1Q3WGRSVnFXdUpocFIiLCJzdWIiOjMsInBydiI6Ijg3ZTBhZjFlZjlmZDE1ODEyZmRlYzk3MTUzYTE0ZTBiMDQ3NTQ2YWEifQ.t4JLsLLE6WIFZp67hbafZl8YTLlzN2WyQVw11mETMNQ Referer: http://localhost:3000/categories/play-card User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36

当我重新加载浏览器时,错误消失并返回预期的数据。Nuxt 正在universal ssr模式下运行。

我需要一些指导来了解可能导致此问题的原因。我肯定错过了什么

4

2 回答 2

0

错误“预检请求不允许重定向”。通常在服务器向客户端发送“位置”响应标头时发生。浏览器不喜欢这样,因此会引发错误。所以你在 url /api/products?category=play-card 的 laravel 控制器可能会发送一个 Location 标头,我不确定。例如,您可以做些什么来调试此问题,即在您请求此 url 时使用 Postman 检查发送给客户端的标头。

希望这会帮助你。

PS:我是在这里回答问题的初学者,所以可能不是正确的答案。

于 2020-03-07T10:51:21.267 回答
0

这就是我如何使用 react 16 和 laravel 7

在我的控制器中,我只是将 welcomeController 用作存储在 app\http 中的示例

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;

class WelcomeController extends Controller
{
    public function show() {
        return view('welcome');
    }

    public function post(Request $request) {
        // extra data that may come from a database 
        // or a token or whatever your external component needs
        $post = [
            'title' => 'my title',
            'content' => 'Lorem, ipsum dolor sit amet consectetur adipisicing elit. Hic velit, harum neque adipisci praesentium quo voluptate laudantium ipsam optio provident accusamus modi nobis, facere atque iure perferendis corporis? Quam, distinctio.'
        ];
        $response = array_merge($request->all(), $post);
        return json_encode($response);
    }
}

在 /app/http/Middleware 里面

添加文件 Cors.php。添加以下代码

<?php
namespace App\Http\Middleware;
use Closure;
class Cors
{
  public function handle($request, Closure $next)
  {
    return $next($request)
      ->header('Access-Control-Allow-Origin', 'http://localhost:3000')
      ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
      ->header('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, X-Token-Auth, Authorization');
  }
}

接下来在 ./routes 中像这样构建你的 api

// the order or the middleware matter so make sure that
// cors middleware is first before the api middleware 
Route::middleware('cors:api')->post('/post', 'WelcomeController@post');

在 app/config/cors.php 中,保持这个文件不变

[
    'paths' => ['api/*'],

    'allowed_methods' => ['*'],

    'allowed_origins' => ['*'],

    'allowed_origins_patterns' => [],

    'allowed_headers' => ['*'],

    'exposed_headers' => [],

    'max_age' => 0,

    'supports_credentials' => false,

];

在受保护的 $routeMiddleware 数组中的 app/Http/Kernel.php 中附加一个新的键/值对,请参见下面的示例:

 protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
    'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
    'can' => \Illuminate\Auth\Middleware\Authorize::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
    'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
    'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
    'cors' => \App\Http\Middleware\Cors::class, // add route middleware
];

然后在您的 UI 中,您可以测试来的数据是否通过,我使用 react 但我使用它与本机 javaScript Fetch api 一起发布帖子。下面是进行调用并将信息呈现给 DOM 的组件

import React, { Component } from 'react';

class ConnectToApi extends Component {
  
  state = {
    data: []
  }

  componentDidMount() {
    this.handleGetData();
  }

  handleGetData = async () => {
    fetch('http://laravel-api.local/api/post', {
      method: 'post',
      mode: 'cors',
      headers: new Headers({
        'Accept': 'application/json',
        'Content-Type': 'application/json',
      }),
      body: JSON.stringify({
        name: 'John',
        surname: 'Doe',
      })
    })
    .then(response => response.json())
    .then(data => {
      const state = Object.assign({}, this.state)
      state.data.push(data);
      this.setState(state);      
    })
    .catch(error => console.log(error));
  }

  render() {
    console.log(this.state.data);
    
    return <div>
      <header>
      <h1>
        data
      </h1>
    </header>
    <p>Modified data</p>
    {this.state.data.length === 0 && <p>loading data...</p>}
    {
      this.state.data.length > 0  && this.state.data.map((value, index) => {
        return (
          <div key={index}>
            <p>name: {value.name}</p>
            <p>surname: {value.surname}</p>
            <p>title: {value.title}</p>
            <p>Content <br/><br/> {value.content}</p>
          </div>
        )
      })
    }
    </div>
  }
}
export default ConnectToApi;

然后在 app.js 中只有

import React from 'react';
import logo from './logo.svg';
import './App.css';
import ConnectToApi from './connectToApi'

function App() {
  return (
    <div className="App">
      <ConnectToApi />
    </div>
  );
}

export default App;
于 2020-08-08T17:30:36.753 回答