本书未发布

5.8. Eudore请求上下文

未匹配的标注

Context

Context定义了请求上下文对象的主要方法,额外方法需要扩展,已有方法修改可以使用接口重写实现,请求对象使用Context的Request和SetRequest方法读写。

Context主要分为请求上下文数据、请求、参数、响应、日志输出五部分。

Context的生命周期就是一个请求开始到结束,里面记录整个请求的数据。

Context的定义:

type Context interface {
    // context
    Reset(context.Context, http.ResponseWriter, *http.Request)
    GetContext() context.Context
    Request() *http.Request
    Response() ResponseWriter
    Logger() Logout
    WithContext(context.Context)
    SetRequest(*http.Request)
    SetResponse(ResponseWriter)
    SetLogger(Logout)
    SetHandler(int, HandlerFuncs)
    GetHandler() (int, HandlerFuncs)
    Next()
    End()
    Err() error

    // request info
    Read([]byte) (int, error)
    Host() string
    Method() string
    Path() string
    RealIP() string
    RequestID() string
    Referer() string
    ContentType() string
    Istls() bool
    Body() []byte
    Bind(interface{}) error
    BindWith(interface{}, Binder) error
    Validate(interface{}) error

    // param query header cookie session
    Params() *Params
    GetParam(string) string
    SetParam(string, string)
    AddParam(string, string)
    Querys() url.Values
    GetQuery(string) string
    GetHeader(name string) string
    SetHeader(string, string)
    Cookies() []Cookie
    GetCookie(name string) string
    SetCookie(cookie *SetCookie)
    SetCookieValue(string, string, int)
    FormValue(string) string
    FormValues() map[string][]string
    FormFile(string) *multipart.FileHeader
    FormFiles() map[string][]*multipart.FileHeader

    // response
    Write([]byte) (int, error)
    WriteHeader(int)
    Redirect(int, string)
    Push(string, *http.PushOptions) error
    Render(interface{}) error
    RenderWith(interface{}, Renderer) error
    WriteString(string) error
    WriteJSON(interface{}) error
    WriteFile(string) error

    // log Logout interface
    Debug(...interface{})
    Info(...interface{})
    Warning(...interface{})
    Error(...interface{})
    Fatal(...interface{})
    Debugf(string, ...interface{})
    Infof(string, ...interface{})
    Warningf(string, ...interface{})
    Errorf(string, ...interface{})
    Fatalf(string, ...interface{})
    WithField(key string, value interface{}) Logout
    WithFields(fields Fields) Logout
}

请求上下文部分数据

该部分主要是读写一些基本数据和中间件机制操作。

// context.go
type Context interface {
    // context
    Reset(context.Context, http.ResponseWriter, *http.Request)
    GetContext() context.Context
    Request() *http.Request
    Response() ResponseWriter
    Logger() Logout
    WithContext(context.Context)
    SetRequest(*http.Request)
    SetResponse(ResponseWriter)
    SetLogger(Logout)
    SetHandler(int, HandlerFuncs)
    GetHandler() (int, HandlerFuncs)
    Next()
    End()
    Err() error
    ...
}

Reset(context.Context, http.ResponseWriter, *http.Request)方法在EudoreHTTP中来使用http请求数据初始化ctx对象。

Request() RequestReaderResponse() ResponseWriter方法获取ctx的请求和响应对象,允许直接操作ctx的底层请求对象;
SetRequest(RequestReader)SetResponse(ResponseWriter)方法设置请求和响应对象,可以用来重写ctx的请求和响应,例如gzip响应中间件实现。

GetContext() context.Context方法
获得当前ctx的context.Context;WithContext(context.Context)方法设置当前请求上下文的context.Context对象。

Logger() LogoutSetLogger(Logout)方法获取设置当前请求上下文的Logout。

SetHandler(HandlerFuncs)方法设置上下文处理者,通常在ctx初始化后,然后调用Router.Match匹配得到多个请求处理者,设置给上下文,最后调用Next开始处理;同时拥有GetHandler() (int, HandlerFuncs)方法获取当前处理函数和状态。

Next()方法调用下一个请求处理者开始处理,通过Next方法可以巧妙实现请求后处理请求。

ctx.Println("前执行")
ctx.Next()
fmt.Println("后执行")

End()方法结束ctx的处理,忽略全部剩余的请求处理者,未实现获取是否结束处理状态,同时结束Conext的生命周期。

Done() <-chan struct{}方法返回请求上下文结束,不允许go ctx.Done()可能出现并发安全问题,防止请求上下文被回收,需要确保主go最后结束,或者获得到context.Context对象使用Done。

请求信息

请求部分主要是请求行、部分header、body的读取,header使用ctx.Request().Header()读取,io.Reader接口直接读取body的数据,Body方法读取全部内容,其他方法见方法名称。

type Context interface {
    // request info
    Read([]byte) (int, error)
    Host() string
    Method() string
    Path() string
    RealIP() string
    RequestID() string
    Referer() string
    ContentType() string
    Istls() bool
    Body() []byte
    Bind(interface{}) error
    BindWith(interface{}, Binder) error
    ...
}

Read([]byte) (int, error)方法实现io.Reader接口,可以直接读取请求body,和RequestReader.Read()方法一样。

Host() string方法获取请求的Host。

Method() string方法获取http请求方法。

Path() string方法获取http请求路径。

RealIP() string方法获取请求远程真实ip地址,http连接的地址通过RequestReader.RemoteAddr()方法获取。

RequestID() string方法获取X-Request-ID http header

Referer() string方法获取Referer http header

ContentType() string方法获取Content-Type http header

Istls() bool方法获取是否是Tls连接(是否为https),可以使用RequestReader.TLS()活动tls连接状态。

Body() []byte方法获取请求Body并保存全部body,如果调用Body方法前使用read读取的数据无法获得。

Bind(interface{}) error方法调用Binder对象解析请求,并给对象绑定数据,根据请求Context-Type Header来决定Bind方法。

BindWith(interface{}, Binder) error方法使用指定的Binder解析请求。

参数

参数部分是对param query header cookie form五部分读写,Params是Context的参数都是字符串类型,query是http uri参数,header分为请求header和响应header,cookie和header类似,form是对form请求解析的数据读取。

type Context interface {
    // param query header cookie session
    Params() Params
    GetParam(string) string
    SetParam(string, string)
    AddParam(string, string)
    Querys() url.Values
    GetQuery(string) string
    GetHeader(name string) string
    SetHeader(string, string)
    Cookies() []Cookie
    GetCookie(name string) string
    SetCookie(cookie *SetCookie)
    SetCookieValue(string, string, int)
    FormValue(string) string
    FormValues() map[string][]string
    FormFile(string) *multipart.FileHeader
    FormFiles() map[string][]*multipart.FileHeader
    ...
}

Params

Params() Params方法获取全部上下文参数。

GetParam(string) string方法获取一个上下文参数。

SetParam(string, string)方法设置一个上下文参数。

AddParam(string, string)方法添加一个上下文参数。

Query

Querys() url.Values方法获取全部请求参数。

GetQuery(string) string方法获得请求uri中的参数,可以使用RequestReader.RequestURI()获得请求行中的uri。

Header

GetHeader(name string) string方法获取请求Header,相当于ctx.Request().Header().Get()。

SetHeader(string, string)方法设置响应Header,相对于ctx.Response().Header().Set()

Cookie

Cookies() []*Cookie方法获取全部请求Cookies。

GetCookie(name string) string方法获取指定请求Cookie的值。

SetCookie(cookie *SetCookie)方法设置响应Cookie,实现为给响应设置一个Set-Cookie header。

SetCookieValue(string, string, int)方法设置响应Cookie。

Form

FormValue(string) string方法获得指定的表单数据。

FormValues() map[string][]string方法获得全部的表单数据。

FormFile(string) *multipart.FileHeader方法获得指定的表单文件。

FormFiles() map[string][]*multipart.FileHeader方法获得全部的表单文件。

响应

响应部分Write和WriteHeader是主要部分,其他方法就是封装写入不同的类型,header可以使用ctx.SetHeader和ctx.Response().Header()来操作。

type Context interface {
    // response
    Write([]byte) (int, error)
    WriteHeader(int)
    Redirect(int, string)
    Push(string, *protocol.PushOptions) error
    Render(interface{}) error
    RenderWith(interface{}, Renderer) error
    // render writer
    WriteString(string) error
    WriteJSON(interface{}) error
    WriteFile(string) error
    ...
}

Write([]byte) (int, error)方法写入响应数据,和ResponseWriter.Write()一样,net/http实现中,在第一次数据后无法写入Header和Status。

WriteHeader(int)方法写入响应状态码。

Redirect(int, string)方法返回重定向,实现通过返回30x状态码和Location header记录重定向地址。

Push(string, *protocol.PushOptions) error方法h2 Push资源,调用ResponseWriter.Push()。

WriteString(string) error方法写入字符串。

WriteView(string, interface{}) error方法写入渲染模板,调用View对象渲染。

WriteJSON(interface{}) error方法写入Json数据。

WriteFile(string) error方法写入文件内容。

Render(interface{}) error方法调用Renderer渲染数据成对于格式,根据请求Accept Header来决定Render方法。

RenderWith(interface{}, Renderer) error方法使用指定Renderer处理数据渲染。

日志

日志和Logout接口相同,定义输出日志信息,默认Context会输出调用文件行和请求id信息。

type Context interface {
    // log Logout interface
    Debug(...interface{})
    Info(...interface{})
    Warning(...interface{})
    Error(...interface{})
    Fatal(...interface{})
    Debugf(string, ...interface{})
    Infof(string, ...interface{})
    Warningf(string, ...interface{})
    Errorf(string, ...interface{})
    Fatalf(string, ...interface{})
    WithField(key string, value interface{}) Logout
    WithFields(fields Fields) Logout
    ...
}

其他

曾经Context实现了context.Context接口,后来删除了实现改为Context() context.Context方法返回对象,因为自己实现的Context对象在context中会出现一些无法处理的问题,例如cancel取消子ctx,在cancelCtx对象的parentCancelCtx方法实现中使用了断言,自己实现的ctx无法被断言到会出现问题,具体参考context包源码。

反馈和交流请加群组:QQ群373278915

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~