【问题标题】:Preflight Doesn't Pass Control Check Access-Control-Allow-Origin Not PresentPreflight 未通过控制检查 Access-Control-Allow-Origin Not Present
【发布时间】:2018-02-09 15:21:38
【问题描述】:

我有一个在 React 中运行的简单客户端。我正在尝试使用 Axios 向本地运行的 Go 服务器发出 GET 请求。 React 代码在 3000 端口上运行,Go 服务器在 4000 上运行。

如果我将 GET 请求本身粘贴到浏览器窗口中,它可以正常工作:http://localhost:4000/numberconverter?number=10&oldBase=10&newBase=2

我做了一些研究并找到了this post,但插件和 Chrome 选项没有帮助。这不是我做过的唯一研究,但这似乎是最有希望的。我发现的大多数东西都不涉及 Go 服务器。

我也找到了this post,但这也没有解决我的问题。如果我取消注释服务器中的代码,它仍然会失败。

如果我将允许的方法更改为:

writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PATCH, PUT, DELETE, OPTIONS")

失败并出现 405 错误。服务器打印出这个:

&{0xc4200f4000 0xc42000a500 {} 0x10ec430 true false false false 0xc4200143c0 {0xc420100000 map[Access-Control-Allow-Origin:[*] Access-Control-Allow-Methods:[GET, POST, PATCH, PUT, DELETE, OPTIONS] Content-Type:[text/plain; charset=utf-8] X-Content-Type-Options:[nosniff]] false false} map[Access-Control-Allow-Origin:[*] Access-Control-Allow-Methods:[GET, POST, PATCH, PUT, DELETE, OPTIONS] Content-Type:[text/plain; charset=utf-8] X-Content-Type-Options:[nosniff]] true 19 -1 405 false false [] 0 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0] 0xc4200620e0 0}

我想我的问题是这是服务器端还是客户端的问题,以及我该如何解决这个问题?

客户:

import React, {Component} from 'react';
import axios from 'axios';

class Converter extends Component {
    constructor(props) {
        super(props);
        this.state = {
            // number: 0,
            // base: 10,
            // newBase: 10
        };
        this.convertButtonPressed = this.convertButtonPressed.bind(this);
        this.handleChange = this.handleChange.bind(this);
    }

    handleChange(event) {
        const target = event.target;
        const value = target.value;
        const name = target.name;

        this.setState({
        [name]: value
        });
    }

    convertButtonPressed(event) {
        axios({
            method: 'GET',
            baseURL: 'http://localhost:4000/',
            url: '/numberconverter',
            headers: {
                'Access-Control-Allow-Origin': '*',
                'Access-Control-Allow-Methods': 'GET, POST, PATCH, PUT, DELETE, OPTIONS',
                'Access-Control-Allow-Headers': 'Origin, Content-Type, X-Auth-Token'
            },
            params: {
            number: this.state.number,
            oldBase: this.state.base,
            newBase: this.state.newBase
            }
        });
    }

    render() {
        return (
        <div className="App">
            <p>Number Converter</p>
            <div>
            Number:
            <input name="number" onChange={this.handleChange} type="text" placeholder="Number"></input><br />
            Base:
            <input name="base" onChange={this.handleChange} type="text" placeholder="Base"></input><br />
            New Base:
            <input name="newBase" onChange={this.handleChange} type="text" placeholder="New Base"></input><br />
            </div>
            <button onClick={this.convertButtonPressed}>Convert</button>
        </div>
        );
    }
}

export default Converter;

服务器:

package rest

// Example:
// http://localhost:3000/numberconverter?number=500000&oldBase=10&newBase=16

import (
    "fmt"
    "log"
    "net/http"

    "../converter"
)

// Start starts the server
func Start() {
    //muxRouter := http.NewServeMux()
    //muxRouter.HandleFunc("/numberconverter", numberconverter)
    //http.Handle("/", muxRouter)
    http.HandleFunc("/numberconverter", numberconverter)
    log.Fatal(http.ListenAndServe(":4000", nil))
}

func numberconverter(writer http.ResponseWriter, response *http.Request) {
    //writer.Header().Set("Access-Control-Allow-Origin", "*")
    //writer.Header().Set("Access-Control-Allow-Methods", "*")
    //writer.Header().Set("Content-Type", "text/html; charset=utf-8")

    // Check if the method is a get
    if response.Method != http.MethodGet {
        http.Error(writer, http.StatusText(405), 405)
        fmt.Println(writer)
        return
    }

    number := response.FormValue("number")
    oldBase := response.FormValue("oldBase")
    newBase := response.FormValue("newBase")
    result := converter.ConvertStringNumberToNewBase(number, oldBase, newBase)
    fmt.Fprintf(writer, "%s base %s is %s in base %s", number, oldBase, result, newBase)
}

【问题讨论】:

  • 取消注释这些标题设置行是否有效?浏览器扩展绝对是解决这个问题的错误方法。您的任何用户都不会拥有它们。
  • IIRC,Access-Control-Allow-Methods 不能是 *。它应该是一个方法列表。
  • Setting HTTP headers的可能重复
  • @captncraig 如果我取消注释这些行,它仍然不起作用。这些行来自我试图解决问题。
  • 您的前端代码添加的那些标头会触发您的浏览器在尝试 GET 请求之前自动执行 COR preflight OPTIONS 请求,您的代码打算发送 developer.mozilla.org/en-US/docs/Web/HTTP/… 并且因为在后端代码中您将请求发送到的服务器,您有它执行if response.Method != http.MethodGet { http.Error(writer, http.StatusText(405), 405) …},当浏览器发送预检选项并且预检失败并且您的浏览器永远不会继续尝试从您的代码中获取 GET 时,它会被命中

标签: rest reactjs go cors preflight


【解决方案1】:

一旦我注释掉 React 代码中的标头,GET 请求就会起作用。我要感谢sideshowbarker 的回答。我真的很感激。

convertButtonPressed(event) {
    axios({
        method: 'GET',
        baseURL: 'http://localhost:4000/',
        url: '/numberconverter',
        // headers: {
        //     'Access-Control-Allow-Origin': '*',
        //     'Access-Control-Allow-Methods': 'GET, POST, PATCH, PUT, DELETE, OPTIONS',
        //     'Access-Control-Allow-Headers': 'Origin, Content-Type, X-Auth-Token'
        // },
        params: {
          number: this.state.number,
          oldBase: this.state.base,
          newBase: this.state.newBase
        }
      });
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-15
    • 1970-01-01
    • 2017-06-22
    • 2016-04-09
    • 2018-10-12
    • 1970-01-01
    • 2018-07-20
    • 2017-06-15
    相关资源
    最近更新 更多