You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
naza/pkg/nazahttp/read_message.go

97 lines
2.1 KiB
Go

// Copyright 2020, Chef. All rights reserved.
// https://github.com/q191201771/naza
//
// Use of this source code is governed by a MIT-style license
// that can be found in the License file.
//
// Author: Chef (191201771@qq.com)
package nazahttp
import (
"io"
"strconv"
)
// e.g. bufio.Reader
type HttpReader interface {
LineReader
io.Reader
}
type HttpMsgCtx struct {
ReqMethodOrRespVersion string
ReqUriOrRespStatusCode string
ReqVersionOrRespReason string
Headers HttpHeaders
Body []byte
}
type HttpReqMsgCtx struct {
Method string
Uri string
Version string
Headers HttpHeaders
Body []byte
}
type HttpRespMsgCtx struct {
Version string
StatusCode string
Reason string
Headers HttpHeaders
Body []byte
}
func ReadHttpRequestMessage(r HttpReader) (ctx HttpReqMsgCtx, err error) {
msgCtx, err := ReadHttpMessage(r)
if err != nil {
return
}
ctx.Method = msgCtx.ReqMethodOrRespVersion
ctx.Uri = msgCtx.ReqUriOrRespStatusCode
ctx.Version = msgCtx.ReqVersionOrRespReason
ctx.Headers = msgCtx.Headers
ctx.Body = msgCtx.Body
return
}
func ReadHttpResponseMessage(r HttpReader) (ctx HttpRespMsgCtx, err error) {
msgCtx, err := ReadHttpMessage(r)
if err != nil {
return
}
ctx.Version = msgCtx.ReqMethodOrRespVersion
ctx.StatusCode = msgCtx.ReqUriOrRespStatusCode
ctx.Reason = msgCtx.ReqVersionOrRespReason
ctx.Headers = msgCtx.Headers
ctx.Body = msgCtx.Body
return
}
// 注意如果HTTP Header中不包含`Content-Length`则不会读取HTTP Body并且err返回值为nil
func ReadHttpMessage(r HttpReader) (ctx HttpMsgCtx, err error) {
var requestLine string
requestLine, ctx.Headers, err = ReadHttpHeader(r)
if err != nil {
return ctx, err
}
ctx.ReqMethodOrRespVersion, ctx.ReqUriOrRespStatusCode, ctx.ReqVersionOrRespReason, err = ParseHttpRequestLine(requestLine)
if err != nil {
return ctx, err
}
contentLength, ok := ctx.Headers[HeaderFieldContentLength]
if !ok {
return ctx, nil
}
cl, err := strconv.Atoi(contentLength[0])
if err != nil {
return ctx, err
}
ctx.Body = make([]byte, cl)
_, err = io.ReadFull(r, ctx.Body)
return ctx, err
}