doushi3189
doushi3189
2018-06-12 09:34

为什么使用react-admin获得404的API端点?

已采纳

Created backend API use gin with go language

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)
    }
}

// ...

Created frontend use react with react-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>
);

When access http://localhost:3000 from chrome browser, got Failed to fetch message. From the console I saw:

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.

I have tried to add Access-Control-Allow-Origin in the go API program, but the same result. From the gin output I got:

[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

Add

Added cors package then change source as:

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()
}

Got same error again:

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.

This time, the output of gin was:

[GIN] 2018/06/13 - 11:01:59 | 403 |       7.873µs |             ::1 | OPTIONS  /posts?_end=10&_order=DESC&_sort=id&_start=0
  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

2条回答

  • dongpaocuan7498 dongpaocuan7498 3年前

    This way works:

    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)
            }
    }
    

    Due to ra-data-json-server.

    点赞 评论 复制链接分享
  • douwen0647 douwen0647 3年前

    Add CORS middleware for cross origin domain requests. I would prefer to hit the api using postman to check if it is working fine. Below is the way to implement CORS middleware for gin in go:-

    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()
    }
    

    Edited: For allowing all origins use Default config for 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()
    }
    

    For more information checkout CORS middleware for gin

    点赞 评论 复制链接分享