吃海底撈前用golang例項來看看瀏覽器的同源策略
明天中秋節, 今天出來吃海底撈,取號後,還要等100多桌,呵呵噠。索性來奈雪喝茶,寫點東西玩玩。
瀏覽器同源策略? 網上一查一大堆,多數是理論講解,網文也經常到處複製抄襲, 我不具體解釋理論了。 本文來簡單玩一下, 便於對瀏覽器的同源策略有更具體地理解。
來看static.go的程式碼:
package main import ( "io" "log" "net/http" ) func staticFile(w http.ResponseWriter, r *http.Request) { str := ` <html> <body> <div> <input type="button" id="ok" value="click"/> </div> </body> </html> <script> var btn = document.getElementById('ok'); btn.onclick = function() { var xmlHttp = new XMLHttpRequest(); xmlHttp.open('post', 'http://localhost:9999/hello') //xmlHttp.setRequestHeader("Content-type","application/x-www-form-urlencoded") xmlHttp.send("key=123") xmlHttp.onreadystatechange = function () { if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { //alert("ok") } } } </script> ` io.WriteString(w, str) } func main() { http.HandleFunc("/static", staticFile) err := http.ListenAndServe("localhost:8080", nil) if err != nil { log.Println(err) } }
可以看到, 瀏覽器上顯示了一個按鈕。
再看server.go的內容:
package main import ( "io" "log" "net/http" ) func handlerHello(w http.ResponseWriter, r *http.Request) { str := "hello world" io.WriteString(w, str) } func main() { http.HandleFunc("/hello", handlerHello) err := http.ListenAndServe("localhost:9999", nil) if err != nil { log.Println(err) } }
用go run server.go跑起來。
然後,我們在頁面上除錯可以看到:
Failed to load http://localhost:9999/hello: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.
這裡一定要注意一個問題,即使在瀏覽器頁面除錯中出現瞭如上錯誤, 也不能說明server.go對應的服務沒有返回內容, 來抓包實際看看就知道了:
HTTP/1.1 200 OK
Date: Sun, 23 Sep 2018 10:12:09 GMT
Content-Length: 11
Content-Type: text/plain; charset=utf-8
hello world
可見, server.go對應的服務端還是返回了正確內容的!只是瀏覽器針對伺服器的回包,在渲染顯示的時候,做了同源限制而已。
那怎麼處理這種限制呢? 我們可以在server.go程式碼中加上w.Header().Set("Access-Control-Allow-Origin", "*")就可以了, 具體如下:
package main
import (
"io"
"log"
"net/http"
)
func handlerHello(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
str := "hello world"
io.WriteString(w, str)
}
func main() {
http.HandleFunc("/hello", handlerHello)
err := http.ListenAndServe("localhost:9999", nil)
if err != nil {
log.Println(err)
}
}
OK, 不會出現上述錯誤了。
好了, 基於上述實際例子, 再去理解同源策略的內容和原理吧。
暫不多說, 以後再說。
海底撈,還需要排隊,人好多。