【问题标题】:Why got 404 for API endpoint with react-admin?为什么使用 react-admin 获得 404 的 API 端点?
【发布时间】:2018-11-21 15:44:18
【问题描述】:

创建的后端 API 使用 gingo 语言

type Post struct {
    ID uint `json:"id"`
    Title string `json:"title"`
    Body string `json:"body"`
}

func main() {
    // ...
    r := gin.Default()
    r.GET("/posts", GetPosts)
    r.GET("/posts/:id", GetPost)
    r.POST("/posts", CreatePost)
    r.PUT("/posts/:id", UpdatePost)
    r.DELETE("/posts/:id", DeletePost)

    r.Run(":8080")
}

func GetPosts(c *gin.Context) {
    var posts []Post
    c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
    if err := db.Find(&posts).Error; err != nil {
            c.AbortWithStatus(404)
            fmt.Println(err)
    } else {
            c.JSON(200, post)
    }
}

// ...

创建的前端使用 reactreact-admin

src/App.js

import React from 'react';
import { Admin, Resource } from 'react-admin';
import jsonServerProvider from 'ra-data-json-server';
import { PostList } from './posts';

const dataProvider = jsonServerProvider('http://localhost:8080');

const App = () => (
        <Admin dataProvider={dataProvider}>
    <Resource name="posts" list={PostList} />
        </Admin>
);

export default App;

src/posts.js

import React from 'react';
import { List, Datagrid, TextField } from 'react-admin';

export const PostList = (props) => (
    <List {...props}>
        <Datagrid>
            <TextField source="id" />
            <TextField source="title" />
            <TextField source="body" />
        </Datagrid>
    </List>
);

当从 chrome 浏览器访问 http://localhost:3000 时,收到 Failed to fetch 消息。从我看到的控制台:

Failed to load http://localhost:8080/posts?_end=10&_order=DESC&_sort=id&_start=0: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 404. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

我尝试在 go API 程序中添加Access-Control-Allow-Origin,但结果相同。从gin 输出我得到:

[GIN] 2018/06/12 - 18:14:50 | 404 |       1.813µs |       127.0.0.1 | OPTIONS  /posts?_end=10&_order=DESC&_sort=id&_start=0

添加

添加 cors 包然后将源更改为:

package main

import (
        "fmt"

        "github.com/gin-contrib/cors"
        "github.com/gin-gonic/gin"
        // ...
)

// ...

func main() {
    r := gin.Default()

    r.Use(cors.New(cors.Config{
            AllowOrigins: []string{"http://localhost:8080"},
    }))

    r.GET("/posts", GetPosts)
    r.GET("/posts/:id", GetPost)
    r.POST("/posts", CreatePost)
    r.PUT("/posts/:id", UpdatePost)
    r.DELETE("/posts/:id", DeletePost)

    r.Run()
}

又遇到同样的错误:

Failed to load http://localhost:8080/posts?_end=10&_order=DESC&_sort=id&_start=0: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 403. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

这一次,gin 的输出是:

[GIN] 2018/06/13 - 11:01:59 | 403 |       7.873µs |             ::1 | OPTIONS  /posts?_end=10&_order=DESC&_sort=id&_start=0

【问题讨论】:

  • 尝试为golang代码添加gin的CORS中间件,允许跨域请求访问
  • @Himanshu 我添加了一个中间件但得到了相同的结果。

标签: reactjs api go cors go-gin


【解决方案1】:

为跨域请求添加CORS 中间件。我宁愿使用postman 访问 api 来检查它是否工作正常。下面是在go中为gin实现CORS中间件的方法:-

package main

import (
    "time"

    "github.com/gin-contrib/cors"
    "github.com/gin-gonic/gin"
)

func main() {
    router := gin.Default()
    // CORS for http://localhost:8080 and https://github.com origins, allowing:
    // - PUT and PATCH methods
    // - Origin header
    // - Credentials share
    // - Preflight requests cached for 12 hours
    router.Use(cors.New(cors.Config{
        AllowOrigins:     []string{"http://localhost:8080, https://localhost:8080"},
        AllowMethods:     []string{"GET", "POST", "HEAD", "PUT", "PATCH"},
        AllowHeaders:     []string{"Origin"},
        ExposeHeaders:    []string{"Content-Length"},
        AllowCredentials: true,
        MaxAge: 12 * time.Hour,
    }))
    router.Run()
}

已编辑:为了允许所有来源使用 Default 配置 cors as

func main() {
    router := gin.Default()
    // same as
    // config := cors.DefaultConfig()
    // config.AllowAllOrigins = true
    // router.Use(cors.New(config))
    router.Use(cors.Default())
    router.Run()
}

欲了解更多信息,请查看CORS middleware 获取杜松子酒

【讨论】:

  • 谢谢。我已经添加了那个包。但又是同样的结果。我已将来源添加到问题中。
  • 你需要设置 AllowOrigins("localhost:8080") & AllowMethods & AllowHeaders("Origin")
  • 如果设置localhost:8080会在启动服务器时导致panic: bad origin: origins must either be '*' or include http:// or https://错误。
  • @vv 我已经编辑了答案以允许您可以使用Default 配置的所有来源。请检查编辑后的答案
  • @Himanshu 谢谢。这次得到了Warning: Missing translation for key: "The X-Total-Count header is missing in the HTTP Response. The jsonServer Data Provider expects responses for lists of resources to contain this header with the total number of results to build the pagination. If you are using CORS, did you declare X-Total-Count in the Access-Control-Expose-Headers header?",我也加了X-Total-Count,但没有修复。
【解决方案2】:

这种方法有效:

func main() {
        // ...
        r := gin.Default()
        r.Use(cors.New(cors.Config{
                AllowOrigins:  []string{"http://localhost:3000"},
                AllowMethods:  []string{"GET", "POST", "PUT", "PATCH", "DELETE", "HEAD"},
                AllowHeaders:  []string{"Origin", "Content-Length", "Content-Type"},
                ExposeHeaders: []string{"X-Total-Count"},
        }))
        r.GET("/posts", GetPosts)
        // ...
        r.Run()
}

func GetPosts(c *gin.Context) {
        var posts []Post
        if err := db.Find(&posts).Error; err != nil {
                c.AbortWithStatus(404)
                fmt.Println(err)
        } else {
                c.Header("X-Total-Count", "25")
                c.JSON(200, posts)
        }
}

由于ra-data-json-server

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多