$http.post() 方法实际上是发送一个 GET [英] $http.post() method is actally sending a GET

查看:32
本文介绍了$http.post() 方法实际上是发送一个 GET的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意:

我发现了一个可能相关的问题,需要提出一个新问题 这里

<小时>

这是一个奇怪的问题.我在 2 年的时间里一直在使用 angular,从来没有遇到过这个问题.

我使用的是 angular v1.5.0.我正在发出这样的帖子请求:

$http({方法:POST",url: "/myurl",数据: {file: myFile//这只是一个对象}});

普通的 POST 请求对吗?得到这个.我查看控制台,网络"选项卡将请求记录为 GET.奇怪.所以我把代码改成了这样:

$http.post("/myurl", {file: myFile});

同样的事情.在逐步完成 $http 服务代码后,我确信标头设置正确.有其他人遇到过这个问题吗?

更新

根据 germanio 的建议,我尝试使用 $resource 服务代替:

promise = $resource("/upload").save()

(由于另一个原因返回错误,它仍然正确执行 POST).我遇到了同样的问题:请求在控制台中被记录为 GET.

这是到达我的服务器时请求的标头:

GET/myurl/HTTP/1.1主机:本地主机:8001接受:应用程序/json、文本/纯文本、*/*接受编码:gzip、deflate、sdch接受语言:en-US,en;q=0.8缓存控制:无缓存连接:保持连接编译指示:无缓存引用者:http://localhost:8001/myurl/用户代理:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36

更新 2

根据 georgeawg 的建议,我使用了拦截器来记录各个阶段的请求.这是拦截器代码:

$httpProvider.interceptors.push(function() {返回 {请求:功能(配置){控制台日志(配置);返回配置;}}}

运行此代码后,我得到了记录:

data:Object//包含文件对象headers: Object//将 Content-Type 设置为 multipart方法:POST"//???网址:"/我的网址

所以这意味着请求是从 Angular 内部作为 POST 发送的,但它仍然在浏览器和我的服务器上记录为 GET.我认为这里有一些我不理解的关于 HTTP 协议的低级工作.

请求是否在实际登录浏览器之前发送到服务器?如果是这样,那至少可以指出我的服务器是罪魁祸首.

为了找出发生了什么,这是我的服务器代码:

type FormStruct struct {测试字符串}func PHandler(w http.ResponseWriter, r *http.Request) {var t FormStructreq, _ := httputil.DumpRequest(r, true)log.Println(string(req))log.Println(r.Method)//GETlog.Println(r.Body)解码器:= json.NewDecoder(r.Body)错误:=decoder.Decode(&t)log.Println("解码完成")如果错误!= nil {log.Println("错误")恐慌(错误.错误()+\n\n")}log.Println(t.Test)w.Write([]byte("上传完成,没有错误"))}功能主(){http.HandleFunc("/myurl/", PHandler)fmt.Println("Go Server 监听端口 8001")http.ListenAndServe(":8001", nil)}

我的服务器在收到请求时抛出 EOF 错误:

2016/03/30 10:51:37 http: 恐慌服务 [::1]:52039: EOF

不确定在这种情况下 EOF 甚至意味着什么.

更新 3

根据其他用途的建议,我尝试使用 POSTMAN 以虚假 POST 请求访问我的服务器.服务器正确接收请求.这对我来说意味着发出 POST 请求的角度有问题.请帮忙.

有什么想法吗?

完整的服务器日志:

Go 服务器监听 8001 端口2016/03/30 11:13:08 GET/myurl/HTTP/1.1主机:本地主机:8001接受: */*接受编码:gzip、deflate、sdch接受语言:en-US,en;q=0.8缓存控制:无缓存连接:保持连接内容类型:应用程序/json邮递员令牌:33d3de90-907e-4350-c703-6c57a4ce4ac0用户代理:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36X-Xsrf-Token:空2016/03/30 11:13:082016/03/30 11:13:08 {}2016/03/30 11:13:08 解码完成2016/03/30 11:13:08 错误2016/03/30 11:13:08 http:恐慌服务[::1]:52228:EOFgoroutine 5 [正在运行]:net/http.(*conn).serve.func1(0xc820016180)/usr/local/Cellar/go/1.6/libexec/src/net/http/server.go:1389 +0xc1恐慌(0x3168c0,0xc82000b1a0)/usr/local/Cellar/go/1.6/libexec/src/runtime/panic.go:426 +0x4e9路线.FUPHandler(0x1055870,0xc820061ee0,0xc820104000)/Users/projectpath/routes.go:42 +0x695net/http.HandlerFunc.ServeHTTP(0x4e7e20, 0x1055870, 0xc820061ee0, 0xc820104000)/usr/local/Cellar/go/1.6/libexec/src/net/http/server.go:1618 +0x3anet/http.(*ServeMux).ServeHTTP(0xc820014b40, 0x1055870, 0xc820061ee0, 0xc820104000)/usr/local/Cellar/go/1.6/libexec/src/net/http/server.go:1910 +0x17dnet/http.serverHandler.ServeHTTP(0xc820016100, 0x1055870, 0xc820061ee0, 0xc820104000)/usr/local/Cellar/go/1.6/libexec/src/net/http/server.go:2081 +0x19enet/http.(*conn).serve(0xc820016180)/usr/local/Cellar/go/1.6/libexec/src/net/http/server.go:1472 +0xf2e由 net/http.(*Server).Serve 创建/usr/local/Cellar/go/1.6/libexec/src/net/http/server.go:2137 +0x44e

更新 4

我偶然发现了一些有趣的事情:

Charles 在我向 myurl 发帖时记录了一个 POST 请求,但响应状态是 301.在 POST 后记录了一个 GET.这是访问我的服务器的 GET.

正如您在上面看到的,我的服务器不进行任何重定向.301 是怎么发生的?

解决方案

这是出于安全考虑.

在您的情况下,当重定向从服务器发送回浏览器时,浏览器不会重复 POST 请求(而只是一个简单的"GET 请求).

一般来说,浏览器不会将 POST 数据发送到重定向 URL,因为浏览器没有资格决定您是否愿意将相同的数据发送到新 URL,而您打算发送到原始 URL(想想密码、信用卡号和其他敏感数据).但不要试图规避它,只需使用处理程序的注册路径进行 POST,或链接答案中提到的任何其他提示.

有关上下文,请参阅问题:

Go 网络服务器自动重定向 POST 请求

您可以在此处阅读有关该主题的更多信息:

为什么 HTTP 没有 POST 重定向?>

NOTE:

I've found a possibly related issue that warrants a new question here


This is a weird problem. I've been using angular over the course of 2 years and have never run into this problem.

I'm using angular v1.5.0. I'm making a post request like this:

$http({
    method: "POST",
    url: "/myurl",
    data: {
        file: myFile // This is just an object
    }
});

Run-of-the-mill POST request right? Get this. I look in the console and the Network tab logs the request as a GET. Bizarre. So I've jiggered the code to work like this:

$http.post("/myurl", {file: myFile});

Same thing. After stepping through the $http service code I'm confident that the headers are being set properly. Has anyone else run into this problem?

Update

Taking germanio's advice, i've tried using the $resource service instead:

promise = $resource("/upload").save()

(this returns an error for another reason, it still executes the POST properly). I'm having the same problem: the request is logged as a GET in the console.

Here are the headers of the request when it gets to my server:

GET /myurl/ HTTP/1.1
Host: localhost:8001
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Cache-Control: no-cache
Connection: keep-alive
Pragma: no-cache
Referer: http://localhost:8001/myurl/
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36

Update 2

As per georgeawg's suggestion I've used an interceptor to log the request at its various stages. Here is the interceptor code:

$httpProvider.interceptors.push(function() {
    return {
        request: function(config) {
            console.log(config);
            return config;
        }
    }
}

Having run this code I get this logged:

data:Object // contains file object
headers: Object // has Content-Type set to multipart
method:"POST" // ???
url :"/myurl

So this means the request is being sent as a POST from within Angular, but it is still logged as a GET both in the browser and on my server. I think there is something low level at work here about the HTTP protocol that I dont understand.

Is the request sent to the server before it is actually logged in the browser? If so, that might atleast point to my server as the culprit.

In the hopes of finding out whats going on, here is my server code:

type FormStruct struct {
    Test string
}

func PHandler(w http.ResponseWriter, r *http.Request) {
    var t FormStruct

    req, _ := httputil.DumpRequest(r, true)

    log.Println(string(req))
    log.Println(r.Method) // GET
    log.Println(r.Body)

    decoder := json.NewDecoder(r.Body)
    err := decoder.Decode(&t)
    log.Println("Decoding complete")
    if err != nil {
        log.Println("Error")
        panic(err.Error()+"\n\n")
    }
    log.Println(t.Test)

    w.Write([]byte("Upload complete, no errors"))
}

func main() {
    http.HandleFunc("/myurl/", PHandler)    
    fmt.Println("Go Server listening on port 8001")
    http.ListenAndServe(":8001", nil)
}

My server throws an EOF error when it receives the request:

2016/03/30 10:51:37 http: panic serving [::1]:52039: EOF

Not sure what an EOF would even mean in this context.

Update 3

By the suggestion of another use, I tried using POSTMAN to hit my server with a fake POST request. The server receives the request properly. This means to me that there is something up with how angular is making the POST request. Please help.

Any ideas?

Full server logs:

Go Server listening on port 8001

2016/03/30 11:13:08 GET /myurl/ HTTP/1.1
Host: localhost:8001
Accept: */*
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Cache-Control: no-cache
Connection: keep-alive
Content-Type: application/json
Postman-Token: 33d3de90-907e-4350-c703-6c57a4ce4ac0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36
X-Xsrf-Token: null


2016/03/30 11:13:08 GET
2016/03/30 11:13:08 {}
2016/03/30 11:13:08 Decoding complete
2016/03/30 11:13:08 Error
2016/03/30 11:13:08 http: panic serving [::1]:52228: EOF


goroutine 5 [running]:
net/http.(*conn).serve.func1(0xc820016180)
    /usr/local/Cellar/go/1.6/libexec/src/net/http/server.go:1389 +0xc1
panic(0x3168c0, 0xc82000b1a0)
    /usr/local/Cellar/go/1.6/libexec/src/runtime/panic.go:426 +0x4e9
routes.FUPHandler(0x1055870, 0xc820061ee0, 0xc820104000)
    /Users/projectpath/routes.go:42 +0x695
net/http.HandlerFunc.ServeHTTP(0x4e7e20, 0x1055870, 0xc820061ee0, 0xc820104000)
    /usr/local/Cellar/go/1.6/libexec/src/net/http/server.go:1618 +0x3a
net/http.(*ServeMux).ServeHTTP(0xc820014b40, 0x1055870, 0xc820061ee0, 0xc820104000)
    /usr/local/Cellar/go/1.6/libexec/src/net/http/server.go:1910 +0x17d
net/http.serverHandler.ServeHTTP(0xc820016100, 0x1055870, 0xc820061ee0, 0xc820104000)
    /usr/local/Cellar/go/1.6/libexec/src/net/http/server.go:2081 +0x19e
net/http.(*conn).serve(0xc820016180)
    /usr/local/Cellar/go/1.6/libexec/src/net/http/server.go:1472 +0xf2e
created by net/http.(*Server).Serve
    /usr/local/Cellar/go/1.6/libexec/src/net/http/server.go:2137 +0x44e

Update 4

I stumbled onto something interesting:

Charles logs a POST request when I post to myurl, but the response status is 301. After the POST a GET is logged. This is the GET that is hitting my server.

My server, as you can see above, does not do any sort of redirection. How is the 301 happening?

解决方案

This is due to a security consideration.

In your situation when a redirect is sent back from the server to the browser, the browser will not repeat the POST request (but rather just a "simple" GET request).

Generally speaking a browser will not send POST data to a redirect URL because the browser is not qualified to decide if you're willing to send the same data to the new URL what you intended to send to the original URL (think about passwords, credit card numbers and other sensitive data). But don't try to circumvent it, simply use registered path of your handler to POST to, or any of the other tips mentioned in the linked answer.

For context see question:

Go web server is automatically redirecting POST requests

You can read more on the subject here:

Why doesn't HTTP have POST redirect?

这篇关于$http.post() 方法实际上是发送一个 GET的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆