此问题one之后,因此某些文本是相同的。
当提交表单时,前端尝试将JSON数据发布到后端时,Firefox控制台上的错误消息。
“跨域请求被阻止:相同起源策略不允许读取https://backend_domain/anteroom处的远程资源。(原因: CORS标头'Access-Control-Allow-Origin'丢失)。 “
我正在使用systemd单元运行Golang后端,并在localhost:12345上为其提供服务。 Nginx侦听端口80并将请求向下传递到端口:
listen 80;
server_name backend_domain;
location / {
include proxy_params;
proxy_pass http://localhost:12345/;
}
我使用Angular-http-server在端口8080上使用PM2,将Angular前端作为构建版本(使用--prod
标志运行)。与后端相同,Nginx从端口执行其操作80:
listen 80;
server_name frontend_domain;
location / {
include proxy_params;
proxy_pass http://localhost:8080/;
}
我使用的版本:Ubuntu 16.04,PM2 3.3.1,Angular CLI 7.3.4,angular-http-server 1.8.1
开发人员工具中的Firefox网络标签显示POST请求标头:
Host: backend_domain
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: frontend_domain/
Content-Type: text/plain
Content-Length: 111
Origin: frontend_domain
DNT: 1
Connection: keep-alive
响应头:
HTTP/1.1 405 Method Not Allowed
Server: nginx/1.10.3 (Ubuntu)
Date: Mon, 11 Mar 2019 21:08:24 GMT
Content-Length: 0
Connection: keep-alive
Strict-Transport-Security: max-age=31536000; includeSubDomains
当我按下“提交”按钮时,应该发送到后端的实际请求是:
if (val.issues && val.age && val.gender) {
this.profile = JSON.stringify({
age: val.age,
gender: val.gender,
issues: val.issues
});
return this.http
.post(environment.anteroomPOSTURL, this.profile, {
observe: "response"
})
Firefox通过开发工具中的“网络”的“参数”选项卡下显示的JSON,成功地触发了此操作。
此响应向我表明,Nginx不会以某种方式将请求向下传递到端口12345的后端。否则,它将从Golang代码中所示的后端中检索标头并将其传递回前端,对吧?
我读到CORS是服务器端的问题。因此,我尝试在有服务器的任何地方(即后端Nginx和angular-http-server)启用它。
它已在我的Golang代码中启用:
func anteroom(res http.ResponseWriter, req *http.Request) {
res.Header().Set("Access-Control-Allow-Origin", "*")
res.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS")
res.Header().Set("Access-Control-Allow-Headers", "Content-Type")
res.Header().Set("Content-Type", "application/json")
...
}
func main() {
...
# Using Gorilla mux router.
router := mux.NewRouter()
router.HandleFunc("/anteroom", anteroom).Methods("POST, OPTIONS")
}
这成功地启用了CORS的开发功能,在该服务中,为Golang提供服务只是打开其内置的二进制文件,而为Angular提供ng serve
。
以上内容在生产中还不够。因此,我尝试使用angular-http-server启用它。注意结尾处的--cors
标志:
pm2 start $(which angular-http-server) --name app -- --path /PATH/TO/DIST -p 8080 --cors
我还尝试过在后端Nginx文件和前端Nginx文件中启用它(改编自here):
location / {
proxy_pass http://localhost:8080; # or 12345 if it's the back end conf
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Content-Type';
add_header 'Content-Type' 'application/json';
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Content-Type';
add_header 'Content-Type' 'application/json';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Content-Type';
}
}
}
奇怪的是,无论标头是否在Nginx文件中,tcpdump -vvvs 1024 -l -A src host backend_domain | grep 'Access-Control-Allow-Origin:'
都会产生以下信息:
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: *
不知道为什么它会重复12次,但是无论如何,后端都会在前端加载的那一刻发送以上消息(这意味着Nginx确实将请求成功向下传递到端口12345,对吗?)。当我单击提交按钮提交表单时,它不会发送给他们。我不知道这是正确的行为,还是表明有问题。
我想念什么?
更新19年3月12日,晚上7.30:
如上所示,并在sideshowbarker的注释中指出,存在“ 405不允许的方法”响应。起初我以为这与CORS问题以及Nginx有关。为了验证这一点,我停止了Nginx,并在端口12345上打开了防火墙,以便可以直接将其发布到Golang后端。
为避免同源策略引起的任何复杂性,我使用cURL从另一台机器上进行POST:curl -v -X POST -H 'Content-Type: application/json' -d '{"age":"l","gender":"l","issues":"l"}' http://droplet_IP:12345/anteroom
我得到了完全相同的响应:“不允许使用HTTP / 1.1 405方法”。
在这一点上,我最好的猜测是,即使代码中明确允许,Golang后端也不允许POST,如上所示。我不知道为什么。
答案 0 :(得分:0)
首要地,问题是由于Golang代码中main()
中的Gorilla mux这一行引起的:
router.HandleFunc("/anteroom", anteroom).Methods("POST, OPTIONS")
注意后面的方法:("POST, OPTIONS")
。错了它应该是("POST", "OPTIONS")
。它们必须单独引用。
这与在net / http:res.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS")
页面的函数中设置方法时不同。在这里,它们被一起引用。
我认为可能存在各种各样的问题,但是这是一个令人厌烦的旅程,我只记得这最后一个了。