islishude / blog

my web notes
https://islishude.github.io/blog/
101 stars 15 forks source link

GET 请求可不可以附带 body? #218

Closed islishude closed 4 years ago

islishude commented 4 years ago

正常的认知中,GET 是不可以使用 body 的,如果要使用 body,可以转化成 querystring。

查了些资料,发现规范并没有限制,但是实际使用是有很大区别的。

使用 Go 实现一个 Server,然后使用 curl(v7.54.0),nodejs(v13.5.0),go(v1.13.5) 来实验:

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
        data, _ := ioutil.ReadAll(req.Body)
        fmt.Println(req.Method)
        fmt.Println(req.Header)
        fmt.Println(string(data))
        fmt.Println()
    })
    _ = http.ListenAndServe(":8000", nil)
}

使用 Go client

package main

import (
    "io"
    "io/ioutil"
    "net/http"
    "strings"
)

func main() {
    var url = "http://localhost:8000/"
    var payload = strings.NewReader("hello,world")

    req, err := http.NewRequest(http.MethodGet, url, payload)
    if err != nil {
        panic(err)
    }

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    _, _ = io.Copy(ioutil.Discard, resp.Body)
}

Server 正常打印。

使用 curl

curl --location --request GET 'localhost:8000' --data-raw 'hello,world'

Server 正常打印,另外 Content-Type 也自动加上了 application/x-www-form-urlencoded。

使用 nodejs 的话,就有很大区别,GET 不会传递 body,而 POST 会。

// nodejs version v13.5.0
var https = require('http');

var options = {
    'method': 'POST',
    'hostname': 'localhost',
    'port': 8000,
    'path': '/'
};

var req = https.request(options, function (res) {
    var chunks = [];
    res.on("data", function (chunk) {
        chunks.push(chunk);
    });

    res.on("end", function (chunk) {
        var body = Buffer.concat(chunks);
        console.log(body.toString());
    });

    res.on("error", function (error) {
        console.error(error);
    });
});

req.write("hello,world");

req.end();

切换到 postman 实现,postman 是支持 GET with body 的。

greatghoul commented 4 years ago

今天也注意到 postman 的 GET 请求是可以携带 body 的,不过感觉这种的使用场景非常的少。

islishude commented 4 years ago

今天也注意到 postman 的 GET 请求是可以携带 body 的,不过感觉这种的使用场景非常的少。

elasticsearch 很多请求都是 GET 加 json 的