- xml - AJAX/Jquery XML 解析
- 具有多重继承的 XML 模式
- .net - 枚举序列化 Json 与 XML
- XML 简单类型、简单内容、复杂类型、复杂内容
这个问题遵循这个 one所以有些文字是一样的。
当前端尝试在提交表单时向后端发送 JSON 数据时,Firefox 控制台上的错误消息:
“跨源请求被阻止:同源策略不允许读取位于 https://backend_domain/anteroom 的远程资源。(原因:缺少 CORS header '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 前端作为构建(使用 --prod
标志构建)使用 PM2 和 angular-http-server 在端口 8080 服务它。与后端相同,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 请求 header :
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 代码中如下所示的后端检索 header 并将其传递回前端,对吧?
我读到 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 文件中启用它(改编自 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';
}
}
}
奇怪的是,无论 header 是否在 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 点半更新:
如上所示并由 sideshowbarker 在评论中指出,有一个“405 Method Not Allowed”响应。起初我认为这与 CORS 问题以及 Nginx 相关。为了验证这一点,我停止了 Nginx,并在端口 12345 上打开了防火墙,以便我可以直接 POST 到 Golang 后端。
为了避免同源策略带来的任何复杂化,我使用 cURL 从另一台机器进行 POST:curl -v -X POST -H 'Content-Type: application/json' -d '{"age":"l","性别":"l","问题":"l"}' http://droplet_IP:12345/anteroom
我得到了完全相同的响应:“不允许使用 HTTP/1.1 405 方法”。
在这一点上,我最好的猜测是 Golang 后端不允许 POST,即使它在代码中明确允许,如上所示。我不知道为什么。
最佳答案
这个问题主要是由于 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")
。在这里,它们被一起引用。
我认为可能存在各种各样的问题,但这是一段非常累人的旅程,我现在只记得最后一个。
关于angular - 405 Method Not Allowed and "CORS header ‘Access-Control-Allow-Origin’ missing“虽然tcpdump说它正在被发送出去,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55111117/
Yii::$app->runAction('new_controller/new_action', $params); 我相信这可以用来从另一个 Controller 调用 Controller Ac
这个问题类似于 this ,但我需要访问父成员(不是控制)。我不知道是否可以不使用依赖注入(inject)。 例如,我有一个父级,有一个成员调用用户,我需要从子 Controller 访问用户。 最佳
我有包含 2 个布局的根布局:- 选项面板- 绘制区域 我正在尝试的是访问 OptionsPaneController 中的 DrawAreaController 以调用其绘制方法。下面是 Optio
我的应用程序的 View Controller 层次结构设置如下: UIViewController | UITabBarController | UINavigationCo
我的应用程序的 View Controller 层次结构设置如下: UITabBarController | UINavigationController | | |
当我第一次为我目前在 Storyboard 中开发的应用程序创建基础布局时,我分两步完成: 选择我的 View Controller 并使用 Editor->Embed In->Navigation
设计要求: 显示用户可以选择的项目列表 选择一个项目后,使用后退按钮将用户带到一个新 View 。新 View 应在底部包含第一个屏幕中不存在的选项卡列表 单击选项卡中的项目时,应出现一个带有后退按钮
将父 Controller 设置为“parentCtrl as vm”,并将子 Controller 设置为“childCtrl as vmc”,以避免名称冲突,并且效果良好。 如何在子 Contro
我已经阅读了一些答案,例如关闭当前的 ViewController,但我的情况有所不同,因为我正在展示另一个 ViewController。 虽然我无法访问它的属性,但此代码显示了带有导航 Contr
如我所见,如果我们要实例化一个Model(例如,名为Post),我们只需调用: $post = new Post(); 现在,我还想实例化一个Controller(例如,名为Post,并为此 Cont
我已经疯狂地在整个网络上搜索解决我的问题的方法,但目前还没有。我的问题是我必须检查是否在 HTTP 请求中获得特定文本,该请求在一个 while 循环中,如果我这样做了,那么我应该离开循环并继续线程,
我想用this.get('controllers.pack.query');要得到App.PackQueryController在 App.PackController ,但失败了。 我认为问题是 E
我刚开始使用 Laravel。当我使用 codeigniter 或 zend 框架时,我可以将我的 Controller 组织到一个单独的目录中。例如,我可以创建“user/permission.ph
在 emberjs 前 2 我们可以从另一个 Controller 访问 Controller 或 Controller 中的任何方法 以下方式: App.get('router').get('nav
这可能是非常简单的实现,但我是 iOS 编程的新手,我似乎被卡住了。 所以,基本上,我有一个选项卡式应用程序。我决定除了标签栏之外还需要一个导航栏。为此,我放置了标签栏 Controller ,然后添
我有这个列表 Controller , define([ 'jquery', 'app' ], function ($,app) { app.controller("ListC
我有 3 个 Controller :RootController、FirstController 和 SecondController。我想从 RootController -> FirstCont
我有以下 Controller : /controllers/api/base_controller.rb /controllers/api/v1/articles_controller.rb 当为文
我是 Angular JS 的新手,尝试在另一个 Controller 中调用一个 Controller ,但出现以下错误。 ionic.bundle.js:21157 TypeError: $con
我有一个标签栏 Controller 和它的 3 个 child ,我还有另一个 View ,我制作了一个从 child 到 View Controller 的自定义转场,还有一个从 View Con
我是一名优秀的程序员,十分优秀!