CORS Policy: Response to preflight request fails access control check: No 'Access-Control-Allow-Origin'

王林
Release: 2024-02-06 11:00:08
forward
798 people have browsed it

CORS 策略:对预检请求的响应未通过访问控制检查:无“Access-Control-Allow-Origin”

Question content

I use golang and gin-gonic/gin web framework on the backend and react axios on the frontend. I've been trying to solve it for two days and I'm still getting the same error below:

cors policy: response to preflight request doesn't pass access control check: no 'access-control-allow-origin' header is present on the requested resource.
Copy after login

This error only occurs when I try to send a patch request, so that request requires a preflight options request, but everything with get and post works as expected, they don't run any preflight checks.

This is the code for my router configuration:

package main

import (
    "book_renting/api"
    "log"
    "net/http"

    "github.com/gin-contrib/sessions"
    "github.com/gin-contrib/sessions/cookie"
    "github.com/gin-gonic/contrib/cors"
    "github.com/gin-gonic/gin"
    _ "github.com/lib/pq"
)

func main() {

    router := gin.default()
    store := cookie.newstore([]byte("your-secret-key"))
    store.options(sessions.options{maxage: 60 * 60 * 24})

    router.use(cors.default())
    router.use(sessions.sessions("sessions", store))

    router.use(func(c *gin.context) {
        host := c.request.header.get("origin")
        c.writer.header().set("access-control-allow-origin", host)
        c.writer.header().set("access-control-allow-credentials", "true")
        c.writer.header().set("access-control-allow-headers", "content-type, authorization")
        c.writer.header().set("access-control-allow-methods", "get, post, put, delete, patch, options")
        if c.request.method == "options" {
            log.println("handling options request")
            c.abortwithstatus(http.statusnocontent)
            return
        }
        log.println("executing cors middleware")
        c.next()
    })

    router.post("/login", api.handlelogin)
    router.get("/logout", api.handlelogout)
    router.post("/register", api.handleregister)
    router.get("/getcookie", api.getcookiesession)

    router.get("/books", api.getbooksapi)
    router.get("/books/:id", api.bookbyidapi)
    router.patch("/rent/:id", api.rentbookapi)
    router.patch("/return/:id", api.returnbookapi)
    router.run("localhost:3000")
}
Copy after login

This is the front end:

import axios from 'axios'

const url = 'http://localhost:3000'

export const loginuser = async (credentials) => await axios.post(`${url}/login`, credentials, {withcredentials: true})
export const logoutuser = async () => await axios.get(`${url}/logout`, {withcredentials: true})
export const registeruser = () => axios.post(`${url}/register`)
export const fetchbooks = () => axios.get(`${url}/books`, { withcredentials: true })
export const fetchbookbyid = (book_id) => axios.get(`${url}/books/${book_id}`, { withcredentials: true })
export const rentbook = (book_id) => axios.patch(`${url}/rent/${book_id}`, { withcredentials: true })
export const returnbook = (book_id) => axios.patch(`${url}/return/${book_id}`, { withcredentials: true })
Copy after login

I'm pretty sure I've set up the backend correctly and it should return all the necessary headers.

For example, for a get request, the response headers look like this:

http/1.1 200 ok
access-control-allow-credentials: true
access-control-allow-headers: content-type, authorization
access-control-allow-methods: get, post, put, delete, patch, options
access-control-allow-origin: http://localhost:3001
content-type: application/json; charset=utf-8
date: sat, 10 jun 2023 22:12:11 gmt
content-length: 495
Copy after login

Although for the patch request attempt I get no response (unsurprisingly) and the preflight response headers are:

http/1.1 200 ok
date: sat, 10 jun 2023 22:12:12 gmt
content-length: 0
Copy after login

Do you have any suggestions for possible problems? After these two days I have no clue. Thank you in advance!

I also tried adding a title:

c.writer.header().set("access-control-allow-origin", host)
        c.writer.header().set("access-control-allow-credentials", "true")
        c.writer.header().set("access-control-allow-headers", "content-type, authorization")
        c.writer.header().set("access-control-allow-methods", "get, post, put, delete, patch, options")
Copy after login

...again in the if statement:

if c.request.method == "options" {
    log.println("handling options request")
    c.abortwithstatus(http.statusnocontent)
    return
    }
Copy after login

But this doesn't help at all. In fact, this if statement is not executed when the preflight is executed, I know from the console that the server is executing the options request.

[gin] 2023/06/11 - 00:12:13 | 200 |       7.708µs |       127.0.0.1 | options  "/rent/2"
Copy after login

edit:

This is the curl command that sends the patch request (so actually this is the preflight options request):

curl 'http://localhost:3000/return/2' \
  -x 'options' \
  -h 'accept: */*' \
  -h 'accept-language: en-us,en;q=0.9,pl-pl;q=0.8,pl;q=0.7' \
  -h 'access-control-request-headers: content-type' \
  -h 'access-control-request-method: patch' \
  -h 'cache-control: no-cache' \
  -h 'connection: keep-alive' \
  -h 'origin: http://localhost:3001' \
  -h 'pragma: no-cache' \
  -h 'referer: http://localhost:3001/' \
  -h 'sec-fetch-dest: empty' \
  -h 'sec-fetch-mode: cors' \
  -h 'sec-fetch-site: same-site' \
  -h 'user-agent: mozilla/5.0 (macintosh; intel mac os x 10_15_7) applewebkit/537.36 (khtml, like gecko) chrome/114.0.0.0 safari/537.36' \
  --compressed
Copy after login

Response to this request:

HTTP/1.1 200 OK
Date: Sun, 11 Jun 2023 01:22:57 GMT
Content-Length: 0
Copy after login


Correct answer


It turns out you are using a deprecated packagegithub.com/gin-gonic/contrib/cors . You should use github.com/gin-contrib/cors instead. Here is a demo configuration using github.com/gin-contrib/cors:

package main

import (
    "github.com/gin-contrib/cors"
    "github.com/gin-contrib/sessions"
    "github.com/gin-contrib/sessions/cookie"
    "github.com/gin-gonic/gin"
)

func main() {
    router := gin.default()

    config := cors.defaultconfig()
    config.addallowheaders("authorization")
    config.allowcredentials = true
    config.allowallorigins = false
    // i think you should whitelist a limited origins instead:
    //  config.allowallorigins = []{"xxxx", "xxxx"}
    config.alloworiginfunc = func(origin string) bool {
        return true
    }
    router.use(cors.new(config))

    store := cookie.newstore([]byte("your-secret-key"))
    store.options(sessions.options{maxage: 60 * 60 * 24})
    router.use(sessions.sessions("sessions", store))

    // routes below

    router.run("localhost:3000")
}
Copy after login

For some reason, the patch request headers are missing the "cookie" header, even though I used the withcredentials parameter.

axios.patch(`${url}/rent/${book_id}`, { withcredentials: true })
Copy after login

Here { withcredentials: true } is treated as data and has no configuration. If you have no data to send to the server, you should write like this:

axios.patch(`${url}/rent/${book_id}`, null, { withCredentials: true })
Copy after login

The above is the detailed content of CORS Policy: Response to preflight request fails access control check: No 'Access-Control-Allow-Origin'. For more information, please follow other related articles on the PHP Chinese website!

source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template