mirror of
https://github.com/eolinker/apinto
synced 2025-10-05 00:42:47 +08:00
226 lines
5.3 KiB
Go
226 lines
5.3 KiB
Go
package http_context
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
|
|
uuid2 "github.com/satori/go.uuid"
|
|
|
|
"github.com/valyala/fasthttp"
|
|
|
|
goku_plugin "github.com/eolinker/goku-standard-plugin"
|
|
|
|
access_field "github.com/eolinker/goku-eosc/node/common/access-field"
|
|
"github.com/eolinker/goku-eosc/utils"
|
|
)
|
|
|
|
var _ goku_plugin.ContextProxy = (*Context)(nil)
|
|
|
|
//Context context
|
|
type Context struct {
|
|
responseWriter *fasthttp.RequestCtx
|
|
*CookiesHandler
|
|
*PriorityHeader
|
|
*StatusHandler
|
|
*StoreHandler
|
|
RequestOrg *RequestReader
|
|
ProxyRequest *Request
|
|
ProxyResponseHandler *ResponseReader
|
|
Body []byte
|
|
|
|
requestID string
|
|
|
|
RestfulParam map[string]string
|
|
LogFields *access_field.Fields
|
|
|
|
labels map[string]string
|
|
}
|
|
|
|
func (ctx *Context) Labels() map[string]string {
|
|
if ctx.labels == nil {
|
|
ctx.labels = map[string]string{}
|
|
}
|
|
return ctx.labels
|
|
}
|
|
|
|
func (ctx *Context) SetLabels(labels map[string]string) {
|
|
if ctx.labels == nil {
|
|
ctx.labels = make(map[string]string)
|
|
}
|
|
if labels != nil {
|
|
for k, v := range labels {
|
|
ctx.labels[k] = v
|
|
}
|
|
}
|
|
}
|
|
|
|
//Finish finish
|
|
func (ctx *Context) Finish() (statusCode int) {
|
|
defer ctx.responseWriter.Done()
|
|
header := ctx.PriorityHeader.header
|
|
|
|
statusCode = ctx.StatusHandler.code
|
|
if statusCode == 0 {
|
|
statusCode = 504
|
|
}
|
|
ctx.LogFields.StatusCode = statusCode
|
|
bodyAllowed := true
|
|
switch {
|
|
case statusCode >= 100 && statusCode <= 199:
|
|
bodyAllowed = false
|
|
break
|
|
case statusCode == 204:
|
|
bodyAllowed = false
|
|
break
|
|
case statusCode == 304:
|
|
bodyAllowed = false
|
|
break
|
|
}
|
|
|
|
if ctx.PriorityHeader.appendHeader != nil {
|
|
for k, vs := range ctx.PriorityHeader.appendHeader.header {
|
|
for _, v := range vs {
|
|
header.Add(k, v)
|
|
}
|
|
}
|
|
}
|
|
|
|
if ctx.PriorityHeader.setHeader != nil {
|
|
for k, vs := range ctx.PriorityHeader.setHeader.header {
|
|
header.Del(k)
|
|
for _, v := range vs {
|
|
header.Add(k, v)
|
|
}
|
|
}
|
|
}
|
|
|
|
for k, vs := range ctx.PriorityHeader.header {
|
|
if k == "Content-Length" {
|
|
continue
|
|
//vs = []string{strconv.Itoa(len(string(ctx.body)))}
|
|
}
|
|
for _, v := range vs {
|
|
ctx.responseWriter.Response.Header.Add(k, v)
|
|
}
|
|
}
|
|
if ctx.ProxyResponseHandler.header.Get("Content-Type") == "" {
|
|
ctx.responseWriter.Response.Header.Set("Content-Type", "application/json")
|
|
}
|
|
|
|
if ctx.ProxyResponseHandler.header.Get("Content-Encoding") == "gzip" {
|
|
body, err := utils.GzipCompress(ctx.Body)
|
|
if err == nil {
|
|
ctx.Body = body
|
|
}
|
|
}
|
|
ctx.responseWriter.SetStatusCode(statusCode)
|
|
//ctx.LogFields.ResponseHeader = utils.HeaderToString(ctx.header)
|
|
|
|
if !bodyAllowed {
|
|
return statusCode
|
|
}
|
|
ctx.responseWriter.SetBody(ctx.Body)
|
|
ctx.LogFields.ResponseMsg = string(ctx.Body)
|
|
ctx.LogFields.ResponseMsgSize = len(ctx.Body)
|
|
return statusCode
|
|
}
|
|
|
|
//RequestId 请求ID
|
|
func (ctx *Context) RequestId() string {
|
|
return ctx.requestID
|
|
}
|
|
|
|
//NewContext 创建Context
|
|
func NewContext(requestCtx *fasthttp.RequestCtx) *Context {
|
|
//requestID := uuid.New()
|
|
id := uuid2.NewV4()
|
|
requestID := id.String()
|
|
requestReader := NewRequestReader(requestCtx.Request)
|
|
ctx := &Context{
|
|
responseWriter: requestCtx,
|
|
CookiesHandler: newCookieHandle(requestReader.header),
|
|
PriorityHeader: NewPriorityHeader(),
|
|
StatusHandler: NewStatusHandler(),
|
|
StoreHandler: NewStoreHandler(),
|
|
RequestOrg: requestReader,
|
|
ProxyRequest: NewRequest(requestReader),
|
|
ProxyResponseHandler: nil,
|
|
requestID: requestID,
|
|
LogFields: access_field.NewFields(),
|
|
}
|
|
//ctx.LogFields.RequestHeader = utils.HeaderToString(requestReader.Headers())
|
|
ctx.LogFields.RequestMsg = string(ctx.RequestOrg.rawBody)
|
|
ctx.LogFields.RequestMsgSize = len(ctx.RequestOrg.rawBody)
|
|
ctx.LogFields.RequestUri = requestReader.req.URL.RequestURI()
|
|
ctx.LogFields.RequestID = requestID
|
|
return ctx
|
|
}
|
|
|
|
//SetProxyResponse 设置转发响应
|
|
func (ctx *Context) SetProxyResponse(response *http.Response) {
|
|
|
|
ctx.SetProxyResponseHandler(newResponseReader(response))
|
|
|
|
}
|
|
|
|
//SetProxyResponseHandler 设置转发响应处理器
|
|
func (ctx *Context) SetProxyResponseHandler(response *ResponseReader) {
|
|
ctx.ProxyResponseHandler = response
|
|
if ctx.ProxyResponseHandler != nil {
|
|
ctx.Body = ctx.ProxyResponseHandler.body
|
|
ctx.SetStatus(ctx.ProxyResponseHandler.StatusCode(), ctx.ProxyResponseHandler.Status())
|
|
ctx.header = ctx.ProxyResponseHandler.header
|
|
}
|
|
}
|
|
|
|
//func (ctx *Context) Write(w http.ResponseWriter) {
|
|
// if ctx.StatusCode() == 0 {
|
|
// ctx.SetStatus(200, "200 ok")
|
|
// }
|
|
// if ctx.Body != nil {
|
|
// w.Write(ctx.Body)
|
|
// }
|
|
//
|
|
// w.WriteHeader(ctx.StatusCode())
|
|
//
|
|
//}
|
|
|
|
//GetBody 获取请求body
|
|
func (ctx *Context) GetBody() []byte {
|
|
return ctx.Body
|
|
}
|
|
|
|
//SetBody 设置body
|
|
func (ctx *Context) SetBody(data []byte) {
|
|
ctx.Body = data
|
|
}
|
|
|
|
func (ctx *Context) SetError(err error) {
|
|
result := map[string]string{
|
|
"status": "error",
|
|
"msg": err.Error(),
|
|
}
|
|
errByte, _ := json.Marshal(result)
|
|
ctx.Body = errByte
|
|
}
|
|
|
|
//ProxyResponse 返回响应
|
|
func (ctx *Context) ProxyResponse() goku_plugin.ResponseReader {
|
|
return ctx.ProxyResponseHandler
|
|
}
|
|
|
|
//Request 获取原始请求
|
|
func (ctx *Context) Request() goku_plugin.RequestReader {
|
|
return ctx.RequestOrg
|
|
}
|
|
|
|
//Proxy 代理
|
|
func (ctx *Context) Proxy() goku_plugin.Request {
|
|
return ctx.ProxyRequest
|
|
}
|
|
|
|
func NotFound(ctx *Context) {
|
|
ctx.responseWriter.SetStatusCode(404)
|
|
ctx.responseWriter.SetBody([]byte("404 Not Found"))
|
|
}
|