Go语言Web框架gwk介绍 3
Go语言Web框架gwk介绍 (三)
上一篇忘了ChanResult
ChanResult
可以用来模拟BigPipe,定义如下
type ChanResult struct {
Wait sync.WaitGroup
Chan chan string
ContentType string
Start []byte
End []byte
Timeout time.Duration
}
ChanResult会先输出Start,然后读取Chan中的字符串输出到客户端,最后输出End。
还忘了Controller的事件。
如果Controller的每个Action执行前后需要执行一些相同的代码怎么办?这就需要用到ActionSubscriber接口:
type ActionSubscriber interface {
OnActionExecuting(action *ActionContext)
OnActionExecuted(action *ActionContext)
OnException(action *ActionContext)
}
OnActionExecuting在具体的Action执行之前执行,OnActionExecuted在具体的Action执行之后执行,OnException在具体的Action执行出错后执行。
通过ActionSubscriber可以做权限验证,数据验证,记录日志,同一错误处理等等。
------
GWK内部机制
gwk的内部逻辑十分简单,它的核心对象是HttpServer,HttpContent, HttpProcessor。下面分别介绍。
HttpServer
前面的例子里已经演示了怎么用函数NewDefaultServer创建一个缺省配置的HttpServer实例,NewDefaultServer会调用函数ReadDefaultConfigFile来尝试读取默认的配置文件,如果./conf/web.conf存在,则解析这个配置文件,如果解析出错或者文件不存在则调用函数NewDefaultConfig获得缺省配置。
你也可以用NewHttpServer传入WebConfig参数创建HttpServer实例。
func NewHttpServer(config *WebConfig) (srv *HttpServer, err error)
WebConfig的定义在后面介绍。
创建好HttpServer后,调用它的Start方法来监听http请求,启动Web服务。如果你的代码运行在Google App Engine这样不需要监听端口的平台,可以调用Setup方法来初始化HttpServer。Start方法内部实际上是先调用Setup方法,再调用http.Server的ListenAndServe方法。
HttpServer内部会创建一个http.Server实例,可以通过InnerServer方法来获得这个http.Server。
HttpServer有一个Variables字段,如果你有什么整个HttpServer共享的全局变量,可以放在Variables中。
//server variables
Variables map[string]interface{}
HttpServer实现了http.Handler接口,ServeHTTP函数的内部流程是:
- 创建HttpContext
- 循环执行每一个HttpProcessor的Execute方法
我们先介绍HttpContext。
HttpContext
HttpContext是对当前http请求的封装,定义如下:
type HttpContext struct {
Server *HttpServer
Request *http.Request
Resonse http.ResponseWriter
Method string
RequestPath string
PhysicalPath string
RouteData RouteData
ViewData map[string]interface{}
Result HttpResult
Error error
Flash map[string]interface{}
Session Session
SessionIsNew bool
}
- Server: 当前的HttpServer
- Request: http.Request
- Resonse: http.ResponseWriter
- Method: http请求的method,比如GET,PUT,DELETE,POST...
- RequestPath: http请求url的path部分
- PhysicalPath: 请求对应的物理文件,只有请求的是静态文件时,该字段才有值
- RouteData: RequestPath解析后的路由参数
- ViewData: 存放传递给View模板的数据
- Result: 此次请求的HttpResult
- Error: 此次请求中的Error
- Flash: 可以存放临时变量,生命周期为此次请求
- Session: Session
- SessionIsNew: Session是否此次在请求创建
HttpContext还定义了若干方法简化一些常见的操作:
RouteValue,读取RouteData里的数据
func (ctx *HttpContext) RouteValue(name string) (string, bool)
FormValue,调用http.Request的FormValue,FV也是相同的逻辑
func (ctx *HttpContext) FV(name string) string
func (ctx *HttpContext) FormValue(name string) string
另外还有FormInt,FormIntOr,FormBool,FormBoolOr,FormFloat,FormFloatOr,前面已经做过介绍。
ReqHeader,读取Http request header的数据
func (ctx *HttpContext) ReqHeader(name string) string
SetHeader,设置Http resonse header的数据
func (ctx *HttpContext) SetHeader(key string, value string)
AddHeader,向http response header添加数据
func (ctx *HttpContext) AddHeader(key string, value string)
ContentType,设置http response header的"Content-Type"
func (ctx *HttpContext) ContentType(ctype string)
Status,设置返回http status code
func (ctx *HttpContext) Status(code int)
Accept,读取http request header的"Accept"
func (ctx *HttpContext) Accept() string
Write,调用http response的Write方法
func (ctx *HttpContext) Write(b []byte) (int, error)
Expires,设置http response header的"Expires"
func (ctx *HttpContext) Expires(t string)
SetCookie,设置cookie
func (ctx *HttpContext) SetCookie(cookie *http.Cookie)
Cookie,读取Cookie
func (ctx *HttpContext) Cookie(name string) (*http.Cookie, error)
SessionId,返回SessionId,只有启用了Session才有效
func (ctx *HttpContext) SessionId() string
GetFlash,读取Flash中的变量
func (ctx *HttpContext) GetFlash(key string) (v interface{}, ok bool)
SetFlash,设置Flash中的变量
func (ctx *HttpContext) SetFlash(key string, v interface{})
ReadBody,读取整个http request的内容
func (ctx *HttpContext) ReadBody() ([]byte, error)
Flush,Flush当前Response中的数据到客户端
func (ctx *HttpContext) Flush() {
前面介绍的ChanResult就是调用Flush把内容输出到客户端,代码基本逻辑如下:
ctx.Write(c.Start)
ctx.Flush()
if c.Timeout < time.Millisecond {
c.Timeout = defaultChanResultTimeout
}
waitchan := make(chan bool)
donechan := make(chan bool)
go func() {
for s := range c.Chan {
ctx.Write([]byte(s))
ctx.Flush()
}
donechan <- true
}()
go func() {
c.Wait.Wait()
close(c.Chan)
waitchan <- true
}()
select {
case <-waitchan:
case <-time.After(c.Timeout):
}
<-donechan
ctx.Write(c.End)
HttpProcessor
HttpProcessor的定义如下
type HttpProcessor interface {
Execute(ctx *HttpContext)
Register(server *HttpServer)
}
Execute负责处理http请求,Register会在HttpServer初始化时调用一次,如果你的HttpProcessor需要执行一些初始化代码,可以放在Register方法中。
调用RegisterProcessor可以注册一个HttpProcessor
func RegisterProcessor(name string, p HttpProcessor)
注册的HttpProcessor存在ProcessTable类型的全局变量中
type ProcessTable []*Process
type Process struct {
Name string
Path string
Method string
Handler HttpProcessor
}
如果一个Processor需要特定的条件才执行,可以设置它的Path和Method字段,Method是要匹配的http method,既GET、PUT、POST、DELETE...,"*"或者""匹配所有的http method,Path是要匹配的Request Path,目前版本是前缀匹配,以后可能改成支持通配符。
HttpServer启动时,默认注册三个HttpProcessor:StaticProcessor、RouteProcessor、RenderProcessor。
StaticProcessor
StaticProcessor负责处理静态文件,如果请求的路径能匹配到物理文件,则将HttpContext的的Result设置为FileResult。
StaticProcessor支持缓存静态文件以及自定义http response header。缓存静态文件在缓存一节详细介绍,自定义输出的http header是指为每个静态文件的Response设置你定义的http header,比如统一为静态文件设置Cache-Control。下面是配置的例子:
#static processor config
static_processor: {
cache_enable: true
cache_expire: 3600
header: {
Cache-Control: max-age=43200
X-Title: gwk-demo
}
}
# -->end static processor
RouteProcessor
RouteProcessor负责按照你定义的路由规则调用具体的处理代码,逻辑很简单,只有几十行代码。
RenderProcessor
RenderProcessor负责执行HttpResult的Execute,也只有几十行代码。HttpResult没有赋值的话则返回404错误。
自定义HttpProcessor
你可以增删HttpProcessor或者调整顺序来改变默认的处理逻辑,比如你的程序是一个web api服务,不需要处理静态文件,则可以去掉RouteProcessor。ProcessTable定义了Append、InsertBefore、InsertAfter、Remove方法来简化对HttpProcessor的调整。
http gzip压缩
CompressProcessor可以对http输出做gzip压缩,需要注册到RenderProcessor之前才有效,其本质是用compressResponseWriter来代替默认的ResponseWriter。
type CompressProcessor struct {
Enable bool
Level int
MimeType string
}
type compressResponseWriter struct {
rw http.ResponseWriter
writer compresser
contentType string
format string
headerWritten bool
}
CompressProcessor设计时考虑能够按照MimeType或者RequestPath来过滤需要压缩的内容,但一直没实现,因为访问量小流量小的网站开不开启gzip压缩意义不大,访问量大的网站一般会用一些http反向代理或者http缓存的服务,自己没必要处理gzip压缩。
通过自定义HttpProcessor,你可以为全网站做统一的权限验证,访问限制,日志处理,错误处理等等。
除了HttpProcessor,你还可以通过gwk的事件机制来实现这些逻辑。
Go语言Web框架gwk介绍 3的更多相关文章
- Go语言Web框架gwk介绍4
Go语言Web框架gwk介绍 (四) 事件 gwk支持事件系统,但并没有硬编码有哪些事件,而是采用了比较松散的定义方式. 订阅事件有两种方式: 调用On函数或者OnFunc函数 func On(m ...
- Go语言Web框架gwk介绍2
Go语言Web框架gwk介绍 (二) HttpResult 凡是实现了HttpResult接口的对象,都可以作为gwk返回Web客户端的内容.HttpResult接口定义非常简单,只有一个方法: ty ...
- Go语言Web框架gwk介绍 1
Go语言Web框架gwk介绍 (一) 今天看到Golang排名到前30名了,看来关注的人越来越多了,接下来几天详细介绍Golang一个web开发框架GWK. 现在博客园支持markdown格式发布 ...
- Go语言Web框架gwk介绍 (一)
今天看到Golang排名到前30名了,看来关注的人越来越多了,接下来几天详细介绍Golang一个web开发框架GWK. 现在博客园支持markdown格式发布文章么?后台的编辑器不太好用嘛. GWK ...
- Go语言Web框架gwk介绍 (五)
Session Go的net/http本身不带session的机制,需要开发人员自行实现,gwk实现了内存中的session存储机制,如果需要将session存在其他地方比如redis或者memcac ...
- Go语言Web框架gwk介绍 (四)
事件 gwk支持事件系统,但并没有硬编码有哪些事件,而是采用了比较松散的定义方式. 订阅事件有两种方式: 调用On函数或者OnFunc函数 func On(moudle, name string, h ...
- Go语言Web框架gwk介绍 (二)
HttpResult 凡是实现了HttpResult接口的对象,都可以作为gwk返回Web客户端的内容.HttpResult接口定义非常简单,只有一个方法: type HttpResult inter ...
- Go语言Web框架gwk介绍 (三)
上一篇忘了ChanResult ChanResult 可以用来模拟BigPipe,定义如下 type ChanResult struct { Wait sync.WaitGroup Chan chan ...
- 最好的6个Go语言Web框架
原文:Top 6 web frameworks for Go as of 2017 作者:Edward Marinescu 译者:roy 译者注:本文介绍截至目前(2017年)最好的6个Go语言Web ...
随机推荐
- 欧拉计划·Q8
题目8:找出这个1000位数字中连续13个数字乘积的最大值. 找出下面这个1000位的整数中连续13个数字的最大乘积. 7316717653133062491922511967442657474235 ...
- veridata实验举例(2)验证表BONUS与表SALGRADE两节点同步情况
veridata实验举例(2)验证表BONUS与表SALGRADE两节点同步情况 续接前几篇文章: 1.GoldenGate配置(一)之单向复制配置 地址:点击打开链接 2.GoldenGate配置( ...
- $.each()方法详解
$.each()方法详解 each()函数具有十分强大的遍历功能,可以遍历一维数组.多维数组.Dom.Json等. 在JavaScript中使用$.each可以大大减轻我们的工作量. 1.处理一维数组 ...
- jQuery+PHP掷色子抽奖
原文 jQuery+PHP掷色子抽奖 本文以大富翁游戏为背景,综合运用jQuery和PHP知识,设计出以掷色子点数来达成抽奖的效果,当然抽奖概率是可控的,开发者可以将本实例稍作修改即可运用到网站中的抽 ...
- VS2013中实现angular代码智能提示
第一步:在项目同添加angular js文件的引用: 这里使用NuGet包管理器来给项目添加angular js install-package angularjs 第二步:添加智能提示js文件 我们 ...
- SQLServer 2005 数据库定阅复制实现双机热备(主要是sharepoint 内容数据库)
原文:SQLServer 2005 数据库定阅复制实现双机热备(主要是sharepoint 内容数据库) 场景 公司最近的sharepoint的数据库服务器老是出问题,并且在一旦出现问题,就导致无法正 ...
- AutoMapper 创建嵌套对象映射(原创)
之前在做DTO转换时,用到AutoMapper.但DTO的层次太深了,无奈官方没针对嵌套类型提供好的解决方案,于是自己实现了一下: 思路:采用递归和反射很好的避免手工创建嵌套对象的映射. 第一个版本, ...
- 企业部署Windows 8 Store 风格应用
原文:企业部署Windows 8 Store 风格应用 引言 之前我们都知道可以将应用程序发布到Windows 商店中供用户下载使用.如果我们是企业开发人员,则我们的应用可能属于以下两种类别之一: 1 ...
- Zend Server更新至6.2版本——虚拟主机全方位管理
Zend Server自从发布6.0以来,并支持云服务,成为很多PHP程序所选择的Web服务器. Zend Server 6.2版本从更新内容来看,解决了Web服务器与虚拟主机之间的协同管理.并在细节 ...
- html5 图片上传版本1.0
1.代码如下: /* autor:shzihouyu date:2015-12-11 ver:1.0 */ var szyFile = { fileDom:null,//html 文件上传控件 pre ...