Этот вопрос следует за этим один , поэтому часть текста такая же.
Сообщение об ошибке в консоли Firefox, когда внешний интерфейс пытается отправить данные JSON на внутренний сервер после отправки формы .:
«Запрос перекрестного источника заблокирован: та же политика происхождения запрещает чтение удаленного ресурса на https://backend_domain/anteroom. (причина: отсутствует заголовок CORS« Access-Control-Allow-Origin »).»
Я запускаю серверную часть Golang с модулем systemd и обслуживаю его на локальном хосте: 12345. Nginx прослушивает порт 80 и передает ему запросы:
listen 80;
server_name backend_domain;
location / {
include proxy_params;
proxy_pass http://localhost:12345/;
}
Я запускаю внешний интерфейс Angular как сборку (построенную с флагом --prod
), используя PM2 с сервером angular-http, обслуживающим его через порт 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:
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 отображается на вкладке Params в Network в dev tools.
Этот ответ подсказывает мне, что каким-то образом Nginx не передает запросы на серверную часть через порт 12345. В противном случае он будет извлекать и передавать заголовки из серверной части, показанной ниже в моем коде Golang, обратно во внешний интерфейс, право?
Я читал, что CORS - это проблема на стороне сервера. Итак, я попытался включить его везде, где у меня есть сервер, то есть на внутреннем сервере Nginx и angular-http-server.
Это включено в моем коде Голанга:
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 на задней и передней частях (адаптировано с здесь ):
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, верно?). Он не отправляет их, когда я нажимаю кнопку отправки, чтобы отправить форму. Я не знаю, является ли это правильным поведением или это указывает на то, что что-то не так.
Чего мне не хватает?
Обновление 12 марта, 19:30:
Как видно выше и указано сайдшоу в комментариях, есть ответ "Метод 405 не разрешен". Сначала я подумал, что это связано с проблемой CORS, а также с Nginx. Чтобы проверить это, я остановил Nginx и открыл брандмауэр на порту 12345, чтобы я мог напрямую отправлять сообщения на серверную часть Golang.
Чтобы избежать каких-либо осложнений из-за политики того же происхождения, я использовал cURL to 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, даже если это явно разрешено в коде, как показано выше. Я в недоумении, почему.