golang跨域访问
假设在站点 http://domain-a.com
的某 HTML
页面通过 <img>
的src
请求 http://domain-b.com/image.jpg
。网络上的许多页面都会加载来自不同域的CSS
样式表,图像和脚本等资源。出于安全原因,浏览器限制从脚本内发起的跨源HTTP请求。
例如,XMLHttpRequest
和Fetch API
遵循同源策略。 这意味着使用这些API
的Web应用程序只能从加载应用程序的同一个域请求HTTP
资源,尤其在开发和测试时,跨域问题会给前端测试带来非常不便。除非使用CORS
头文件。
这个CORS(Cross-Origin Resource Sharing,跨域资源共享)
是W3C
的一个工作草案,定义了在必须访问跨域资源时,浏览器与服务器应该如何沟通。它背后的基本思想是:使用自定义的HTTP
头来告诉浏览器,让运行在一个 Origin
(包含请求页面的源信息:协议、域名和端口)上的Web应用被准许访问来自不同源服务器上的指定的资源。
比如一个简单请求,它没有自定义的头部,而主体内容是text/plain
。在发送请求时,需要给它附加一个额外的Origin
头部,其中包含请求页面的源信息(协议、域名和端口),以便服务器根据这个头信息来决定是否给予响应。例如Origin: http://www.baidu.com
。
如果服务器认为这个请求可以接受,就在Access-Control-Allow-Origin
头部中返回相同的源信息,例如:Access-Control-Allow-Origin:http://www.baidu.com
。如果是公共资源,可以将值设置为*
。但是如果没有这个头部,或者有这个头部,但源信息不匹配,浏览器就会驳回请求。
具体实现
CORS
需要浏览器和服务器同时支持。整个CORS
通信过程,浏览器是自动完成,而服务器需要手动配置。golang
设置HTTP
头部相当简单,标准包有现成的方法可以使用。
完整代码示例
ajax.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script>
function loadXMLDoc() {
var xmlhttp;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
}
else {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById("myDiv").innerHTML = xmlhttp.responseText;
}
}
xmlhttp.open("GET", "http://127.0.0.1:8001", true);
xmlhttp.send();
}
</script>
<title>Document</title>
</head>
<body>
<h2>cross origin</h2>
<button type="button" onclick="loadXMLDoc()">请求数据</button>
<div id="myDiv"></div>
</body>
</html>
8000port.go
package main
import (
"net/http"
"html/template"
)
func main() {
http.HandleFunc("/", Entrance)
http.ListenAndServe(":8000", nil)
}
func Entrance(w http.ResponseWriter, r *http.Request) {
t,_:=template.ParseFiles("templates/ajax.html")
t.Execute(w, nil)
}
8001port.go
package main
import (
"net/http"
"fmt"
)
func main() {
http.HandleFunc("/", TestCrossOrigin)
http.ListenAndServe(":8001", nil)
}
func TestCrossOrigin(w http.ResponseWriter, r *http.Request) {
//w.Header().Set("Access-Control-Allow-Origin","*")
w.Header().Add("Access-Control-Allow-Headers","Content-Type")
w.Header().Set("content-type","text/plain")
fmt.Fprintln(w,"hello cros!")
}
当将TestCrossOrigin
接口中的首行注释后,进行访问。我们可以在浏览器控制台看到下图中的内容。取消注释后,就可以正常调用端口
8001
上的接口。
参考文章