为什么把某些参数放在请求头中

在HTTP协议中,首部和请求体是分开传输的,将一些认证信息参数放在请求头中,服务端先解析请求头,如果认证不通过,可以直接返回认证失败,不用再传输请求体,从而提高服务器的性能。
下面做实验验证,实验思路:
编写一个带有身份验证的上传文件接口,此接口先解析请求头中的 token参数,如果token正确,继续解析请求体中的附件,如果token错误,直接返回401,
上传一个超大的文件,比较两种情况的接口耗时。

接口

package main

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

func main(){
    server := http.Server{
        Addr: "127.0.0.1:8080",
    }
    http.HandleFunc("/test",test)
    server.ListenAndServe()
}

func test(w http.ResponseWriter, request *http.Request) {
    token := request.Header.Get("Authorization")
    if token != "Bearer 12345" {
        w.WriteHeader(401)
        fmt.Fprintln(w,"认证失败")
        return
    }
    fmt.Println("解析文件。。。")
    data, _ ,err := request.FormFile("file")
    if err != nil {
        file, _ := ioutil.ReadAll(data)
        fmt.Fprintln(w, string(file))
    }
}

测试

通过 curl 调用该接口, 为使效果明显,上传了一个较大的镜像文件。

  • token 错误的情况
curl -i --location --request GET '127.0.0.1:8080/test'  --header 'Authorization:Bearer 123456'  --form 'file=@"/home/dc/windows10.iso"'

几毫秒内就返回了失败的结果:

HTTP/1.1 401 Unauthorized
Date: Wed, 27 Oct 2021 14:45:54 GMT
Content-Length: 13
Content-Type: text/plain; charset=utf-8
Connection: close

认证失败

token 正确的情况

curl -i --location --request GET '127.0.0.1:8080/test'  --header 'Authorization:Bearer 12345'  --form 'file=@"/home/dc/windows10.iso"'

通过后台日志可以看到正在读取文件。由于测试的附件有3G多,需要漫长的等待。

总结

由此证明,请求头和请求体时分开传输的, 我们往往把一些身份认证信息等放在首部,便于服务快速的响应。此外还需注意一点,在一些web框架中提供的通用身份校验中间件,或者自己编写的请求过滤器,需要先解析请求头,再解析请求体。才能利用上此特性。