您好我正在实施rest apis,因此我想允许提供跨域请求。
我目前在做什么:
AWS上的Go-server代码:
func (c *UserController) Login(w http.ResponseWriter, r *http.Request, ctx *rack.Context) {
w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin"))
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
...
...
c.render.Json(w,rsp, http.StatusOK)
return
}
localhost上的Ajax代码:
<script>
$( document ).ready(function() {
console.log( "ready!" );
$.ajax({
url: 'http://ip:8080/login',
crossDomain: true, //set as a cross domain requests
withCredentials:false,
type: 'post',
success: function (data) {
alert("Data " + data);
},
});
});
我在浏览器控制台上收到以下错误: XMLHttpRequest无法加载http://ip:8080/login。请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,不允许原点“http://localhost:8081”访问。响应的HTTP状态代码为422。
我尝试添加预检选项:
func corsRoute(app *app.App) {
allowedHeaders := "Accept, Content-Type, Content-Length, Accept-Encoding, Authorization,X-CSRF-Token"
f := func(w http.ResponseWriter, r *http.Request) {
if origin := r.Header.Get("Origin"); origin != "" {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
w.Header().Set("Access-Control-Allow-Headers", allowedHeaders)
w.Header().Set("Access-Control-Expose-Headers", "Authorization")
}
return
}
app.Router.Options("/*p", f, publicRouteConstraint)
}
但它没有用。
可以做些什么来解决它。
答案 0 :(得分:11)
我使用gorilla/mux
包构建Go RESTful API服务器,客户端使用JavaScript Request可以工作,
My Go Server在localhost:9091
运行,服务器代码:
router := mux.NewRouter()
//api route is /people,
//Methods("GET", "OPTIONS") means it support GET, OPTIONS
router.HandleFunc("/people", GetPeopleAPI).Methods("GET", "OPTIONS")
log.Fatal(http.ListenAndServe(":9091", router))
我发现在这里给予OPTIONS
很重要,否则会发生错误:
选项http://localhost:9091/people 405(方法不允许)
无法加载http://localhost:9091/people:对预检请求的响应未通过访问控制检查:请求的资源上没有“Access-Control-Allow-Origin”标头。因此,不允许原点“http://localhost:9092”访问。响应的HTTP状态代码为405。
在允许OPTIONS
之后,效果很好。我从This Article得到了这个想法。
此外,MDN CORS doc提到:
此外,对于可能对服务器数据造成副作用的HTTP请求方法,规范要求浏览器“预检”该请求,并使用HTTP OPTIONS从服务器请求支持的方法请求方法,然后,在服务器“批准”后,使用实际的HTTP请求方法发送实际请求。
以下是api GetPeopleAPI 方法,请注意方法我给出评论 //允许CORS此处*或特定来源,我有另一个类似的答案解释这个概念CORS Here:
func GetPeopleAPI(w http.ResponseWriter, r *http.Request) {
//Allow CORS here By * or specific origin
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
// return "OKOK"
json.NewEncoder(w).Encode("OKOK")
}
在客户端,我在localhost:9092
上使用带有javascript的html,javascript会从localhost:9092
function GetPeople() {
try {
var xhttp = new XMLHttpRequest();
xhttp.open("GET", "http://localhost:9091/people", false);
xhttp.setRequestHeader("Content-type", "text/html");
xhttp.send();
var response = JSON.parse(xhttp.response);
alert(xhttp.response);
} catch (error) {
alert(error.message);
}
}
并且请求可以成功获得响应"OKOK"
。
您还可以使用Fiddler
等工具检查响应/请求标头信息。
答案 1 :(得分:6)
您可以查看W3 rule
这也将处理Options
请求
答案 2 :(得分:6)
感谢您的线索 - 这一切都在标题中!我在服务器端只使用这些golang标头:
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.Header().Set("Access-Control-Allow-Origin", "*")
现在使用这个JQuery:
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js">
</script>
<script>
$.ajax({
type: 'GET',
url: 'https://www.XXXXXXX.org/QueryUserID?u=juXXXXny&p=blXXXXXne',
crossDomain: true,
dataType: 'text',
success: function(responseData, textStatus, jqXHR) {
alert(responseData);
},
error: function (responseData, textStatus, errorThrown) {
alert('POST failed.');
}
});
</script>
答案 3 :(得分:1)
GO SERVER SETTING:
package main
import (
"net/http"
)
func Cors(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html; charset=ascii")
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Headers","Content-Type,access-control-allow-origin, access-control-allow-headers")
w.Write([]byte("Hello, World!"))
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/plm/cors",Cors)
http.ListenAndServe(":8081", mux)
}
客户端JQUERY AJAX设置:
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js">
</script>
</head>
<body>
<br> Please confirm to proceed : <button class="myConfirmButton1">Go!!</button>
<div id="loader1" style="display:none;">loading...</div>
<div id="loader2" style="display:none;">...done</div>
<div id="myFeedback1"></div>
<script>
$(document).ready(function(){
$(".myConfirmButton1").click(function(){
$('#loader1').show();
$.ajax({
url:"http://[webserver.domain.com:8081]/plm/cors",
dataType:'html',
headers: {"Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "access-control-allow-origin, access-control-allow-headers"},
type:'get',
contentType: 'application/x-www-form-urlencoded',
success: function( data, textStatus, jQxhr ){
$('#loader1').hide();
$('#loader2').show();
$('#myFeedback1').html( data );
},
error: function( jqXhr, textStatus, errorThrown ){
$('#loader1').hide();
$('#myFeedback1').html( errorThrown );
alert("error" + errorThrown);
}
});
});
});
</script>
</body>
客户测试请求卷曲并获得响应:
curl -iXGET http://[webserver.domain.com:8081]/plm/cors
HTTP/1.1 200 OK
Access-Control-Allow-Headers: Content-Type,access-control-allow-origin, access-control-allow-headers
Access-Control-Allow-Origin: *
Content-Type: text/html; charset=ascii
Date: Wed, 17 Jan 2018 13:28:28 GMT
Content-Length: 13
Hello, World!
答案 4 :(得分:1)
好吧,这个问题给了我一些问题,但是找到了必须使用的解决方法
github.com/gorilla/handlers
连同gollila / mux lib
所以这是一个片段
r := mux.NewRouter()
header := handlers.AllowedHeaders([]string{"X-Requested-With", "Content-Type", "Authorization"})
methods := handlers.AllowedMethods([]string{"GET", "POST", "PUT", "HEAD", "OPTIONS"})
origins := handlers.AllowedOrigins([]string{"*"})
api := r.PathPrefix("/api").Subrouter()
api.Handle("/route", function).Methods("GET", "OPTIONS")
r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
_, _ = fmt.Fprint(w, "hello")
})
err := http.ListenAndServe(":9000", handlers.CORS(header, methods, origins)(r))
if err != nil {
fmt.Println(err)
}
这应该解决您的问题
答案 5 :(得分:1)
第一:cors
svc.Handle("/", restAPI.Serve(nil))
之后,我修复:Handle -> HandleFunc
svc.HandleFunc("/", func(rw http.ResponseWriter, req *http.Request) {
setupHeader(rw, req)
if req.Method == "OPTIONS" {
rw.WriteHeader(http.StatusOK)
return
}
restAPI.Serve(nil).ServeHTTP(rw, req)
return
})
func setupHeader(rw http.ResponseWriter, req *http.Request) {
rw.Header().Set("Content-Type", "application/json")
rw.Header().Set("Access-Control-Allow-Origin", "*")
rw.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
rw.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
}
答案 6 :(得分:0)
添加所有优秀答案:您可能希望使用appHandler模式,而不是在每个处理程序中设置标题:
type Handler func(http.ResponseWriter, *http.Request) *Error
func (fn Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
if e := fn(w, r); e != nil { // e is *appError, not os.Error.
http.Error(w, e.Message, e.Code)
}
}
func Login(w http.ResponseWriter, r *http.Request) *Error {
...
return nil
}
r.Handle("/login", Handler(Login))
答案 7 :(得分:0)
为允许CORS,您的服务器应在使用OPTIONS方法进行实际查询之前,先捕获浏览器发送的所有Preflight request。
第一种方法是通过类似以下方式进行手动管理:
func setupCORS(w *http.ResponseWriter, req *http.Request) {
(*w).Header().Set("Access-Control-Allow-Origin", "*")
(*w).Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
(*w).Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
}
func indexHandler(w http.ResponseWriter, req *http.Request) {
setupCORS(&w, req)
if (*req).Method == "OPTIONS" {
return
}
// process the request...
}
第二种方法是对https://github.com/rs/cors之类的第三方pkg随时使用
package main
import (
"net/http"
"github.com/rs/cors"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte("{\"hello\": \"world\"}"))
})
// cors.Default() setup the middleware with default options being
// all origins accepted with simple methods (GET, POST). See
// documentation below for more options.
handler := cors.Default().Handler(mux)
http.ListenAndServe(":8080", handler)
}
答案 8 :(得分:0)
router := mux.NewRouter()
api := router.PathPrefix("/api/v1").Subrouter()
api.HandleFunc("/getLastDateOfAMonth", lastday.Handler).Methods(http.MethodPost)
c := cors.New(cors.Options{
AllowedOrigins: []string{"http://localhost:3000"},
AllowCredentials: true,
AllowedMethods: []string{"GET", "DELETE", "POST", "PUT"},
})
handler := c.Handler(router)
log.Fatal(http.ListenAndServe(":3001", handler))
我们所有人都面临CORS问题-> 修复->后端服务器应接受CORS。将cors添加到您的后端应用程序。这样它就可以了解浏览器发出的Preflight请求上的CORS。