Я пытаюсь сделать почтовый запрос от моего внешнего интерфейса Angular к моему внутреннему интерфейсу Golang, оба обслуживаются с одной и той же машины. Я продолжаю получать:
OPTIONS http://localhost:12345/anteroom 405 (Method Not Allowed)
и
Access to XMLHttpRequest at 'http://localhost:12345/anteroom' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Golang back end с использованием мультиплексора Gorilla:
func main() {
router := mux.NewRouter()
router.HandleFunc("/anteroom", anteroom).Methods("POST")
log.Fatal(http.ListenAndServe(":12345", router))
}
func anteroom(res http.ResponseWriter, req *http.Request) {
res.Header().Set("Access-Control-Allow-Origin", "*")
// *Edit 17 Jan 19 12.44pm*: Billy, user268396, and Peter suggest that OPTIONS should be added. As mentioned below, I've already tried that.
res.Header().Set("Access-Control-Allow-Methods", "POST")
res.Header().Set("Content-Type", "application/json")
// Put it into a struct variable and print a bit of it.
_ = json.NewDecoder(req.Body).Decode(&member)
fmt.Println(member.ID)
}
Угловая часть переднего конца:
export class AnteroomComponent implements OnInit {
public profile: string;
constructor(private http: HttpClient, private cookieService: CookieService) {}
ngOnInit() {}
// This is the relevant function.
// Triggered by a button.
sendProfile(Profile) {
let httpHeaders = new HttpHeaders({
"Content-Type": "application/json",
"Origin": "http://localhost:4200"
});
return this.http
.post("http://localhost:12345/anteroom", this.profile, {
headers: httpHeaders,
observe: "response"
})
.subscribe(
data => {
console.log("POST Request is successful ", data);
},
error => {
console.log("Error", error);
}
);
}
}
Вот некоторые из многих вещей, которые я пробовал:
Я прочитал, что браузер устанавливает заголовки, а не мои (что не имеет смысла для меня, потому что тогда зачем нужен HttpHeaders()
?), Поэтому я удалил все заголовки из Angular.
Я попытался включить CORS на Голанге, как показано здесь :
(*w).Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
if (*req).Method == "OPTIONS" {
return
}
Я пытался изменить Access-Control-Allow-Origin
с *
на Origin
, потому что я где-то читал, что *
предотвращает отправку / получение файлов cookie. (Потерянная ссылка.) Может быть, это мешает и другим MIME-типам? Я не знаю, просто пытаюсь.
Mozilla говорит: «Конструктор инициализирует XMLHttpRequest. Он должен быть вызван до вызова любого другого метода». Поэтому я подумал, что сделаю это, но тогда Angular говорит: «HttpClient в @ angular / common / http предлагает упрощенный клиентский HTTP API для приложений Angular, который опирается на интерфейс XMLHttpRequest, предоставляемый браузерами». Итак, я думаю, что это не обязательно? В конструкторе уже есть HttpClient
.
this.Profile
выглядит довольно стандартно, как JSON: {id: testid, username: "Mr Odour", age: "87"}
. Но, возможно, это проблема. Поэтому я положил его в String()
. Затем я выкинул ответ из внешнего интерфейса с httputil.DumpRequest()
:
Голанга
output, err := httputil.DumpRequest(req, true)
if err != nil {
fmt.Println("Error dumping request:", err)
return
}
fmt.Println(string(output))
Возможно, это дало немного больше понимания. Распечатано:
POST /anteroom HTTP/1.1
Host: localhost:12345
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,en-GB;q=0.8
Connection: keep-alive
Content-Length: 15
Content-Type: text/plain
Dnt: 1
Origin: http://localhost:4200
Referer: http://localhost:4200/anteroom
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,
like Gecko) Chrome/71.0.3578.98 Safari/537.36
Я думаю, что это произошло? Я не уверен. Это не говорит 200 ОК. Консоль выводит «Запрос POST успешен», но без data
. Я попытался прочитать это на Голанге:
body, err := ioutil.ReadAll(req.Body)
if err != nil {
fmt.Println(err)
}
fmt.Println(body)
Это произвело []
. Пустой.
Там также написано Content-Type: text/plain
. Это проблема? Разве это не должно быть application/json
? Но код других людей использует его таким, каким он есть, без String()
, как this :
return this.http.post<Article>(this.url,
{
id: 100,
title: 'Java Functional Interface',
category: 'Java 8',
writer: 'Krishna'
}
);
Редактировать 17 января 19 12.45 вечера : Билли предлагает использовать Header().Add()
вместо Header().Set()
, вот так:
res.Header().Add("Access-Control-Allow-Origin", "*")
res.Header().Add("Access-Control-Allow-Methods", "POST")
res.Header().Add("Access-Control-Allow-Methods", "OPTIONS")
res.Header().Add("Content-Type", "application/json")
Итак, я сделал. Также не работал.
Задняя часть кажется нормальной. Я написал к нему с curl, и он выдает:
Connected to localhost (::1) port 12345 (#0)
> POST /anteroom HTTP/1.1
> Host: localhost:12345
> User-Agent: curl/7.47.1
> Accept: */*
> Content-Type: application/json
> Content-Length: 126
>
} [126 bytes data]
* upload completely sent off: 126 out of 126 bytes
< HTTP/1.1 200 OK
*Edit 17 Jan 19 12.45pm*: Methods contains OPTIONS once the header is set in backend. So, no problem with curl this way.
< Access-Control-Allow-Methods: POST
< Access-Control-Allow-Origin: *
< Date: Tue, 15 Jan 2019 19:34:32 GMT
< Content-Length: 0
Он также распечатал fmt.Println(member.ID)
и все остальное из строки JSON просто отлично.
Редактировать 17 января 19 13.25 : Когда я выпускаю curl -i -X OPTIONS http://localhost:12345/anteroom
, возвращается сообщение: «Access-Control-Allow-Methods: POST, OPTIONS». Так что ВАРИАНТЫ РАБОТАЮТ. Но запрос переднего плана остался прежним, никаких явных 200 OK и JSON, похоже, не проходят, хотя консоль регистрирует его как успешный. MIME-тип указан в ответе как «text / plain», но разве это не нормально для JSON? Как уже упоминалось, другие решения используют тот же формат, и он работает для них. Сейчас я работаю над этой частью проблемы.
Я новичок в Golang, TypeScript и Angular, поэтому я надеюсь, что выложу весь соответствующий код. Это кажется популярной проблемой, поэтому я просмотрел довольно много подобных вопросов здесь, но все еще не могу понять это. Что я пропустил?