5.09 Context-处理输出

本节课工程结构如下:

(base) yanglei@yuanhong 07-respJSON % tree ./
./
├── context.go
├── context_test.go
├── go.mod
├── go.sum
├── handleFunc.go
├── httpServer.go
├── httpServer_test.go
├── matchNode.go
├── node.go
├── router.go
├── router_test.go
├── serverInterface.go
└── stringValue.go

0 directories, 13 files

PART1. JSON响应

1.1 基本实现

这个需求还是比较简单的.其实只有2个步骤:

  • step1. 调用json.Marshal(),拿到JSON反序列化后的字节切片

  • step2. 将反序列化后的字节切片写入到响应(http.ResponseWriter,实际上是http.response)中

1.2 进阶实现

更进一步的,这个方法应该完善的功能点有:

  • 设置响应码

  • 设置响应头中的Content-Typeapplication/json

  • 设置响应头中的Content-Length为字节切片的长度

  • 判断写入响应体的长度和JSON反序列化后的字节切片长度是否相同

这里需要注意的点是:

需要在写入响应状态码之前设置响应头.一旦调用了http.response.WriteHeader()方法,随后对响应头的任何修改都不会生效,因为响应头已经发送给客户端了.因此需要先设置好所有的响应头,然后再调用http.response.WriteHeader()写入状态码

测试用例context_test.go如下:

RespJSON响应体
RespJSON响应头

1.3 基于进阶实现的封装

例如可以封装一个返回HTTP状态码为200的JSON响应

这里有一个问题:如果obj的类型为string或者[]byte,这种场景下用户该怎么办?

答:在这种场景下,用户已经不需要调用RespJSON()方法了,直接操作http.ResponseWriter即可

本部分工程结构如下:

2.1 功能实现

这个功能实现起来也比较容易:

在早期的GO中,是没有http.SetCookie()函数的.但实际上http.SetCookie()函数的实现也是拼接一个Set-Cookie的响应头字段到响应头中.因此早期的GO WEB框架帮助框架使用者拼接了这个Set-Cookie字段.拼接的过程实际上就相当于实现http.Cookie.String()方法.

例如配置同源策略:

不推荐这种做法.因为关于cookie的选项属性不需要挂在Context上.使用者创建cookie自行设置,设置好后调用Context.SetCookie()方法即可.

PART3. 支持错误页面

本节工程结构如下:

我们通常有一个需求:如果一个响应返回了404,那么应该重定向到一个默认页面,比如说重定向到首页.该怎么处理这个需求?

这个需求棘手的点在于:不是所有的404响应都是要重定向的.比如异步加载数据的RESTful请求.假设需求为在打开页面之后异步请求用户详情接口,那么这个场景下,即使响应404了,也不应该再重定向了.

我们现在的实现如下:

我们现在只是返回了一个"Not Found"的字符串,通常而言应该是重定向到一个用于"兜底"的错误页面.

WEB框架确实应该支持这种重定向到错误页面的功能,但这个功能不应该在Context这个抽象层级上支持.因为即使在Context这个抽象层级上支持了这个功能,使用者用起来也非常麻烦,因为使用者每次需要重定向到错误页面时,都需要自己调用

实现:

很明显使用者需要自己调用这个Context.ErrPage()方法,才能返回错误页面.

那么如果在框架内部检测状态码,并确认是否需要重定向到错误页面,是否可行?

这里我们以Context.RespJSON()方法举例:

这里我们检测到响应码为404时,自动重定向到错误页面,也不可行.因为不是所有的404响应都是要重定向的.

在后续的AOP中,我们再来设计这个需求的解决方案

Last updated