1 Star 0 Fork 0

simple/simple.io

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
request_decoder.go 4.11 KB
一键复制 编辑 原始数据 按行查看 历史
simple 提交于 2024-09-29 23:27 +08:00 . fix(RequestDecoder): 解码器 RFC 7230, Request-URI
package http
import (
"errors"
"fmt"
"golang.org/x/net/http/httpguts"
"net/http"
"net/textproto"
"net/url"
"strconv"
"strings"
)
// RequestDecoder 请求解码器, 从io缓冲区读取字节流, 并解码为http请求对象, 缓冲区一般为socket连接, 也可以使字节数组等
type RequestDecoder struct {
}
// Decoder 解码入口
func (r *RequestDecoder) Decoder(request *Request) (err error) {
defer func() {
if e := recover(); e != nil {
err = errors.New(fmt.Sprintln("Error decoding request, ", e))
}
}()
if request.BufReadr == nil {
return errors.New("request buffer is empty")
}
r.line(request)
r.header(request)
r.uri(request)
r.contentLength(request)
r.body(request)
return
}
// 解码请求行
func (r *RequestDecoder) line(request *Request) {
str, err := request.BufReadr.ReadLine()
if err != nil {
panic(errors.New("HTTP request line format error, " + err.Error()))
}
line := strings.TrimSpace(str)
method, rest, ok1 := strings.Cut(line, " ")
requestURI, proto, ok2 := strings.Cut(rest, " ")
if ok1 && ok2 {
request.Method = method
request.RequestURI = requestURI
request.Proto = proto
} else {
panic(errors.New("HTTP request line format error, " + line))
}
if len(request.Method) < 0 || !ValidMethod(request.Method) || !ValidPath(request.RequestURI) {
panic(errors.New("invalid request " + request.Method + " " + request.RequestURI))
}
var ok bool
if request.ProtoMajor, request.ProtoMinor, ok = http.ParseHTTPVersion(request.Proto); !ok {
panic(errors.New("malformed HTTP version " + request.Proto))
}
}
// 解码请求头
func (r *RequestDecoder) header(request *Request) {
header := make(http.Header, 4)
for {
str, err := request.BufReadr.ReadLine()
if err != nil {
panic(errors.New("HTTP request line format error, " + err.Error()))
}
line := strings.TrimSpace(str)
if len(line) == 0 {
break
}
if line[0] == ' ' || line[0] == '\t' {
panic(badRequestError("malformed MIME header initial line: " + line))
}
name, value, found := strings.Cut(line, ":")
name = strings.TrimSpace(name)
value = strings.TrimSpace(value)
if name == "" || value == "" || !found {
panic(badRequestError("Hearer format error: " + line))
}
if !httpguts.ValidHeaderFieldName(name) {
panic(badRequestError("invalid header name: " + value))
}
if !httpguts.ValidHeaderFieldValue(value) {
panic(badRequestError("invalid header value: " + value))
}
if header.Get(name) == "" {
header.Add(name, value)
} else {
header.Set(name, value)
}
}
request.Header = header
request.Host = header.Get("Host")
// 解析表单数据
_ = request.ParseForm()
// 调整缓存头
PragmaCacheControl(header)
}
// 解码请求URL, RFC 7230, Request-URI: "*" | absoluteURI | abs_path | authority
func (r *RequestDecoder) uri(request *Request) {
var err error
if strings.HasPrefix(request.RequestURI, "http://") {
// absoluteURI
request.URL, err = url.ParseRequestURI(request.RequestURI)
} else if strings.HasPrefix(request.RequestURI, "/") {
// abs_path
request.URL, err = url.ParseRequestURI("http://" + request.Host + request.RequestURI)
} else if !strings.HasPrefix(request.RequestURI, "*") {
// authority
request.URL, err = url.ParseRequestURI("http://" + request.RequestURI)
request.URL.Path = "/"
}
if err != nil {
panic(errors.New("HTTP request uri format error, " + err.Error()))
}
if request.URL.Host != "" {
request.Host = request.URL.Host
}
}
// 解码请求体长度
func (r *RequestDecoder) contentLength(request *Request) {
contentLength := textproto.TrimString(request.Header.Get("Content-Length"))
if contentLength == "" {
request.ContentLength = 0
} else if n, err := strconv.ParseUint(contentLength, 10, 63); err != nil {
request.ContentLength = -1
panic(errors.New("bad Content-Length: " + contentLength))
} else {
request.ContentLength = int64(n)
}
}
// 解码请求体
func (r *RequestDecoder) body(request *Request) {
if request.ContentLength > 0 {
request.body = NewReadBody(request.ContentLength, request.BufReadr)
}
}
// NewRequestDecoder 构造函数
func NewRequestDecoder() *RequestDecoder {
return &RequestDecoder{}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/simple-set/simple.io.git
git@gitee.com:simple-set/simple.io.git
simple-set
simple.io
simple.io
v1.6.5

搜索帮助