我在后端使用 golang 和 gin-gonic/gin web 框架,在前端使用 react axios。我已经尝试解决它两天了,但我仍然遇到以下相同的错误:
cors policy: response to preflight request doesn't pass access control check: no 'access-control-allow-origin' header is present on the requested resource.
仅当我尝试发送 patch 请求时才会发生此错误,因此该请求需要预检 options 请求,但 get 和 post 一切都按预期工作,它们不运行任何预检检查。
这是我的路由器配置的代码:
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")
}
这是前端:
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 })
我非常确定我正确设置了后端,它应该返回所有必要的标头。
例如,对于 get 请求,响应标头如下所示:
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
虽然对于 patch 请求尝试,我没有任何响应(毫不奇怪),并且预检响应标头是:
http/1.1 200 ok
date: sat, 10 jun 2023 22:12:12 gmt
content-length: 0
您对可能出现的问题有什么建议吗?经过这两天我已经毫无头绪了。预先感谢您!
我还尝试添加标题:
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 语句中:
if c.request.method == "options" {
log.println("handling options request")
c.abortwithstatus(http.statusnocontent)
return
}
但这根本没有帮助。事实上,这个if语句在执行预检时并没有执行,我从控制台知道服务器正在执行options请求。
[gin] 2023/06/11 - 00:12:13 | 200 | 7.708µs | 127.0.0.1 | options "/rent/2"
编辑:
这是发送 patch 请求的 curl 命令(因此实际上这是预检 options 请求):
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
对此请求的响应:
HTTP/1.1 200 OK
Date: Sun, 11 Jun 2023 01:22:57 GMT
Content-Length: 0
正确答案
事实证明,您正在使用已弃用的软件包 github.com/gin-gonic/contrib/cors
。您应该使用 github.com/gin-contrib/cors
代替。这是使用 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")
}
由于某种原因,patch
请求标头缺少“cookie”标头,尽管我使用了 withcredentials
参数。
axios.patch(`${url}/rent/${book_id}`, { withcredentials: true })
这里 { withcredentials: true }
被视为数据,并且没有配置。如果你没有数据发送到服务器,你应该这样写:
axios.patch(`${url}/rent/${book_id}`, null, { withCredentials: true })
以上就是CORS 策略:对预检请求的响应未通过访问控制检查:无“Access-Control-Allow-Origin”的详细内容,更多请关注编程网其它相关文章!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
软考中级精品资料免费领
- 历年真题答案解析
- 备考技巧名师总结
- 高频考点精准押题
- 资料下载
- 历年真题
193.9 KB下载数265
191.63 KB下载数245
143.91 KB下载数1142
183.71 KB下载数642
644.84 KB下载数2755