返回

gin+vue跨域问题解决之道

后端





## gin+vue跨域问题解决之道

在开发gin+vue应用时,跨域问题是一个常见的痛点。跨域问题是指浏览器出于安全考虑,不允许一个域下的脚本访问另一个域下的资源。这可能会导致诸如无法获取数据、无法提交表单等问题。

### 跨域问题的产生原因

跨域问题产生的根本原因是浏览器的同源策略。同源策略规定,只有来自同一来源的脚本才能访问彼此的数据。来源由协议、主机名和端口号决定。例如,`https://example.com:8080`和`https://example.com:443`是不同的来源。

### gin+vue跨域问题的解决方案

解决gin+vue跨域问题的方法有多种,具体方法取决于请求的类型。

#### 简单请求

简单请求是指不使用自定义HTTP方法(如PUT、DELETE、POST)且不携带凭证(如cookie)的请求。对于简单请求,我们可以使用以下方法解决跨域问题:

- 在后端设置CORS头。CORS(跨域资源共享)是一种W3C标准,它允许浏览器在不同来源之间进行跨域请求。在后端,我们可以使用CORS头来指定哪些来源可以访问我们的API。例如,在gin中,我们可以使用以下代码设置CORS头:

```go
package main

import (
	"github.com/gin-gonic/gin"
)

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

	r.GET("/api/v1/users", func(c *gin.Context) {
		c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
		c.Writer.Header().Set("Access-Control-Allow-Methods", "GET")
		c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type")

		c.JSON(200, gin.H{
			"message": "Hello, world!",
		})
	})

	r.Run()
}
  • 在前端使用CORS代理。CORS代理是一种代理服务器,它可以将跨域请求转发到后端服务器。在前端,我们可以使用CORS代理来绕过浏览器的同源策略。例如,我们可以使用以下代码在Vue中使用CORS代理:
import axios from 'axios'

const proxy = 'https://cors-anywhere.herokuapp.com/'

const instance = axios.create({
  baseURL: proxy + 'https://example.com/api/v1/',
  withCredentials: true,
})

instance.get('/users').then((response) => {
  console.log(response.data)
})

复杂请求

复杂请求是指使用自定义HTTP方法(如PUT、DELETE、POST)或携带凭证(如cookie)的请求。对于复杂请求,我们需要使用预检请求来解决跨域问题。

预检请求是一种特殊的HTTP请求,它用于检查服务器是否允许客户端进行跨域请求。预检请求使用OPTIONS方法,并且必须在实际请求之前发送。在预检请求中,我们需要指定请求的类型、携带的凭证以及请求头。服务器收到预检请求后,会返回一个预检响应。预检响应中包含了服务器允许的请求类型、携带的凭证以及请求头。客户端收到预检响应后,就可以发送实际请求了。

在gin中,我们可以使用以下代码来处理预检请求:

package main

import (
	"github.com/gin-gonic/gin"
)

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

	r.OPTIONS("/api/v1/users", func(c *gin.Context) {
		c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
		c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE, OPTIONS")
		c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type")

		c.Status(200)
	})

	r.POST("/api/v1/users", func(c *gin.Context) {
		c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
		c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE, OPTIONS")
		c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type")

		c.JSON(200, gin.H{
			"message": "Hello, world!",
		})
	})

	r.Run()
}

在Vue中,我们可以使用以下代码来发送预检请求:

import axios from 'axios'

const instance = axios.create({
  baseURL: 'https://example.com/api/v1/',
  withCredentials: true,
})

instance.post('/users', {
  name: 'John Doe',
  email: 'john.doe@example.com',
})
  .then((response) => {
    console.log(response.data)
  })
  .catch((error) => {
    console.log(error.response.data)
  })

总结

通过本文,我们学习了如何解决gin+vue跨域问题。我们介绍了跨域问题的产生原因,以及简单请求、复杂请求和预检请求三种情况的解决方案。希望本文能够帮助您解决gin+vue跨域问题。