拥抱 Go 的 HTTP 工具

zajin · · 1628 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

前段时间我发布了nosurf,它是一个减轻跨站请求伪造攻击的Go中间件。编写了一个看上去就简单小巧的包就足以让你爱上Go对HTTP的处理方式。而拥抱标准的HTTP设施还是使用fragmentate,牺牲组合性和模块化,这全由我们自己决定。

http.Handler是接口

对于为使用特定编程语言,像Python的WSGI和Ruby的Rack编写的Web应用程序统一HTTP接口,是一个很棒的想法,但他们并不你想就有的。例如,Rack出现在2007年,当时的Rails已经版本增强了老长时间了。

与此同时,在Go,唯一需要的接口自2009年以来一直在开发中,虽然从那以后已经通过了一些重大变化,但是到2011年年底,Go1.0在几个月之前发布,它就已经稳定下来。
当然,这里我说的是强大的http.Handler。

type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}
为了能够处理HTTP请求,你的类型只需要实现这一个方法。该方法从给定的请求中读取请求信息,并写入一个响应到给定的ResponseWriter。看起来似乎很简单,对不对?

补充它,但不能取代它

然而,在此基础之上的建立抽象时,有些东西弄错了。举个例子,Mango,被它的作者描述为“一个模块化的Go语言Web应用程序框架,灵感来自Rack和PEP333”。
这是一个Mango应用程序的样子:

func Hello(env mango.Env) (mango.Status, mango.Headers, mango.Body) {
  return 200, mango.Headers{}, mango.Body("Hello World!")
}

看起来简单,简洁,并且非常类似于WSGI或者Rack,对不对?除了一件事情。在使用动态/鸭式类型时,你可以在任何一个body上用上迭代,这里的mango.Body只是一个简单的字符串。从本质上讲,这样就丢掉了做任何形式的流式响应的能力。即便是暴露一个ResponseWriter,任何写入它的东西都将与返回的值冲突,因为它们只在函数结束时返回,在已经调用了ResponseWriter之后。

这不好。你是否需要基于现有的net/http的另外一个接口,只是你的口味问题,但即使你这样做了,它也不应该拿掉其它的功能。一个接口,在其上的编写代码感觉更棒,但是它带走了重要的功能,显然就逊色了。

正确的方法

现在流行的一个“微型”Web框架web.go使用了一种简单,但更好的方法。它的处理程序使用一个指向web.Contextas的指针作为可选的第一个参数。

type Context struct {
    Request *http.Request
    Params  map[string]string
    Server  *Server
    http.ResponseWriter
}
// ...
func hello(ctx *web.Context, val string) string {
    return "hello " + val 
}

web.Context不再采取标准的HTTP处理程序结构。相反,Request参数可作为结构成员和Context,实现ResponseWriter所需要的方法,故而就让它自身就嵌入了原来的ResponseWriter。你从函数返回字符串(如果有的话)只是简单的追加到了response上。

这是一个很好的设计选择,我认为它能迎合Go的理念。尽管你得到一个不错的更高级别的API,但你不必牺牲对请求处理的底层控制。

现在就开始

Go的HTTP库基础设施,尽管增长迅速,还是留下了一定的差距亟需填补。但是,我们最不需要的是由于设计和抽象的问题造成的功能遗失和碎片,进而产生烦人的兼容性问题。拥抱和支持标准的Go语言HTTP设施的,依我的愚见,最直接的方式就是使用功能性的和模块化的第三方HTTP工具。





有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:zajin

查看原文:拥抱 Go 的 HTTP 工具

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1628 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传