- httpd库
- httpd 使用
- require("httpd")
- httpd:new()
- httpd:timeout(number)
- httpd:server_name(string)
- httpd:max_path_size(number)
- httpd:max_body_size(number)
- httpd:max_header_size(number)
- httpd:enable_cookie()
- httpd:cookie_secure(secure)
- httpd:before(function)
- httpd:ws(route, handle)
- httpd:use(route, handle)
- httpd:api(route, handle)
- httpd:group(type, prefix, handles)
- httpd:static(folder, ttl)
- httpd:listen(ip, port, backlog)
- httpd:run()
- httpd示例:
- httpd 日志格式:
- httpd中间件设计
- httpd 的content
httpd库
httpd库是基于HTTP 1.1协议实现而来, 内置了高性能的http协议解析器与urldecode解析库.
httpd 使用
require("httpd")
使用之前需要先导入httpd库, local httpd = require "httpd"
httpd:new()
使用new方法创建一个httpd对象.(这没什么好说的)
此方法返回一个httpd对象;
httpd:timeout(number)
设置每个连接到最大空闲(idle)连接等待时间, 超过这个数值httpd将主动断开连接. (默认值为:30秒)
此方法返回值为nil;
httpd:server_name(string)
server_name方法的参数是一个字符串类型的参数, 这个方法设置cf的http response头部Server字段的值;
此方法返回值为nil;
httpd:max_path_size(number)
设置Path的最大长度, 超过这个值httpd将会返回414. (默认值为: 1024)
此方法返回值为nil;
httpd:max_body_size(number)
设置Body的最大长度, 超过这个值将会返回413. (默认为 1024 * 1024)
此方法返回值为nil;
httpd:max_header_size(number)
设置headers最大长度, 超过这个值httpd将会返回431. (默认值为: 65535)
此方法返回值为nil;
httpd:enable_cookie()
此方法将会开启use路由都cookie解析, 默认情况下未开启.
此方法返回值为nil;
httpd:cookie_secure(secure)
此方法设置cookie密匙, 设置之前请先开启enable_cookie.(推荐设置一个复杂的值)
此方法返回值为nil;
httpd:before(function)
before方法决定API与USE路由回调在触发之前的行为, 默认情况下允许所有路由通过.
before方法一般用来设置与修改用户验证路由行为(例如头部验证), 这提供了开发者基于before函数设计中间件的机会.
- local http = require "httpd.http"
- app:before(function(content)
- if content.method == 'GET' then
- return http.ok()
- end
- return http.throw(401, '<h1>未授权</h1>')
- end)
需要注意的是: 只要你注入了funtion, 即使function内部什么都不做也会返回401.
此方法返回值为nil;
httpd:ws(route, handle)
ws方法为使用者注入http -> websocket类型的路由升级.
注册此方法后, httpd在检测到当前路由类型为ws类型后将会为检查请求头部(header), 错误的头部将会被判断并返回错误码.
首先被回调的是注册ws路由的class ctor方法; 这个方法将会有一个opt参数(table类型). ws对象将会被注入其中.
具体使用示例, 请参考script/ws.lua
.
httpd:use(route, handle)
httpd:api(route, handle)
use/api方法为route注入路由处理函数, handle即可以是一个函数, 也可以是一个lua table(class).
注意:
1. 无关乎handle的类型, handle的返回值必须为string类型作为body返回给客户端;
2. api的content-type为Applicaton/json; use则为:text/html;
3. http库不可在此handle内部使用, 否则会出现异常;
如果注入的handle为table:
① 必须使用cf框架内置的lua class语法进行设计;
② new方法会传入http request content(注意: 构造函数异常将会引起路由对应的方法无法被正确调用);
③ get/post/put方法会根据用户请求类型(method)被回调(无参数), 如未实现对应方法将会有框架返回对应状态码;
如果注入的handle为function:
cf会为此function注入当前的http request content, 内部包含所有请求上下文与参数;
handle返回值必须为一个string类型的值, 否则将可能出现警告或返回空值;
方法返回值为nil
httpd:group(type, prefix, handles)
group方法提供了一种批量注册路由的方式, 为一组同一组路由提供简单便方便在注册方法.
第一个参数type为需要批量注册的路由类型; 初始化httpd对象后, 使用app.USE
或app.API
进行传值;
第二个参数prefix为string类型的头部; 例如:/api
、/admin
;
第三个参数为一组路由处理函数或处理类数组; 类型为: {route = '/login', class = class};
注意: 此方法仅支持批量注册API与USE路由, 不可同时注册不同类型路由;
此方法返回值为nil
httpd:static(folder, ttl)
folder定义了静态文件路由的查找根目录, ttl为静态文件是否有缓存周期.
ttl默认为nil(永不缓存), ttl大于0的时候浏览器再次访问相同的资源时会优先从本地读取.
默认情况下未开启static路由;
httpd:listen(ip, port, backlog)
listen方法用于告诉httpd对象监听指定端口.
第一个参数ip暂未被httpd使用(但是必须设置), 默认监听所有网卡的'0.0.0.0'地址与指定的端口号;
backlog为用户最大连接等待队列, 合理的设置能减少连接被重置的情况(默认值为128).
此方法需要在run方法之前被调用, 且此方法返回值为nil.
httpd:run()
在httpd库所有参数与路由设置完毕之后, 调用run方法开启监听模式.
run方法被调用后, 写在run方法之后的代码直到程序结束后可能(maybe)不会被执行.
此方法返回值为nil
httpd示例:
一个最简单的cf web service使用示例:
- local httpd = require "httpd"
- local app = httpd:new('httpd')
- app:use('/view', function(content)
- return '<h1>CF Web Service</h1>'
- end)
- app:api('/api', function(content)
- return '{"code":200,"message":"ok"}' -- json string
- end)
- app:listen("0.0.0.0", 8080)
- app:run()
httpd 日志格式:
日志格式为: [年/月/日 时:分:秒] - [ip] - [x-real-ip] - [path] - [method] - [http code] - [request handle timeline]
httpd中间件设计
中间件是设计模式上的概念, 中间件在本质上定义了软件(框架)层与业务层之间的一系列行为(Access、 Logging等等)
httpd:before
就是httpd
库为了处理中间件设计模式需要而诞生的方法, 使用者有需要根据实际情况来决定是否使用此方法.
httpd 的content
每个http请求都会在调用before
与用户注册的路由时为其传入一个content, 这个Content是客户端请求的所有参数.
args : 支持标准get或者post的参数, 对a[1]=1&a[2]=2将会不会解析为数组类型; 支持multipart/form-data
的参数传递方式;
header: 原始header key-value表, 框架层不会进行header进行内容解析. (一般情况下没这个必要);
body : 目前body支持这些类型: multipart/form-data
、application/x-www-form-urlencoded
、application/json
、application/xml
;
json/xml: 在body为json类型的时候, content的json属性为true; 在body为xml类型的时候, content的xml属性为true.
file : 当客户端使用multipart/form-data
传递数据时将会有这个属性; 这个属性是数组类型;
cf会将后两种数据交换格式根据post content-type类型在content内注入类型标识; 如:
- app:use('/admin', function(content)
- if conten.json then
- return 'json', print('json')
- elseif conten.xml then
- return 'xml', print('xml')
- end
- return '未知类型'
- end)
注意: body为xml
或json
类型时, 框架仅会判断类型做好标识, 为了不依赖相关库所以不会主动解析.