跳到主要内容

http_server

简介

组件接口

http_server.gs

函数原型函数作用
object create_server(int port, object router, map ssl_context = nil)创建服务器实例

request.gs

HTTP请求

函数原型函数作用
string get_header(Request self, string field)返回指定的HTTP请求头部字段,匹配不考虑大小写
object get_session(Request self, bool create_if_not_exists = false)取得会话
array _push_parse(Request self, buffer buf)流式解析

response.gs

响应对象

函数原型函数作用
void set_status(Response self, enum HttpStatus status)设置响应码
void force_close(Response self)强制关闭连接
string get_header(Response self, string field)返回指定的HTTP响应头部字段,匹配不考虑大小写
void set_header(Response self, string field, string value)设置HTTP响应头部字段
void set_cookie(Response self, string name, string value, map options = nil)设置Cookie
void del_cookie(Response self, string name, map options = nil)删除Cookie
void set_content(Response self, mixed data, string content_type = nil)设置响应内容
void set_json(Response self, mixed data)设置json格式的响应内容
void redirect(Response self, string url, bool is_forever = false)重定向

router.gs

路由器

函数原型函数作用
void add_route(string method, string path, function handler)添加路由
mixed resolve(string path, string method = nil)路由解析
bool fixup()冻结路由器

server.gs

函数原型函数作用
int get_port()获取监听端口号
void serve()启动服务器,监听指定端口
void add_filter(object filter)添加过滤器
void set_static_dir(string static_dir)设置静态资源根目录
void set_max_header_size(int max_header_size)设置头部长度限值
void enable_debug(bool enable)启用调试信息

utility.gs

实用函数

函数原型函数作用
string urlencode(string str)URL编码(rfc1738)
string urldecode(string str)URL解码

枚举

HttpMethod


HTTP_DELETE,
HTTP_GET,
HTTP_HEAD,
HTTP_POST,
HTTP_PUT,
/* pathological */
HTTP_CONNECT,
HTTP_OPTIONS,
HTTP_TRACE,
/* WebDAV */
HTTP_COPY,
HTTP_LOCK,
HTTP_MKCOL,
HTTP_MOVE,
HTTP_PROPFIND,
HTTP_PROPPATCH,
HTTP_SEARCH,
HTTP_UNLOCK,
HTTP_BIND,
HTTP_REBIND,
HTTP_UNBIND,
HTTP_ACL,
/* subversion */
HTTP_REPORT,
HTTP_MKACTIVITY,
HTTP_CHECKOUT,
HTTP_MERGE,
/* upnp */
HTTP_MSEARCH,
HTTP_NOTIFY,
HTTP_SUBSCRIBE,
HTTP_UNSUBSCRIBE,
/* RFC-5789 */
HTTP_PATCH,
HTTP_PURGE,
/* CalDAV */
HTTP_MKCALENDAR,
/* RFC-2068, section 19.6.1.2 */
HTTP_LINK,
HTTP_UNLINK,
/* icecast */
HTTP_SOURCE,

HttpStatus


CONTINUE = 100,
SWITCHING_PROTOCOLS = 101,
PROCESSING = 102,
EARLY_HINTS = 103,
OK = 200,
CREATED = 201,
ACCEPTED = 202,
NON_AUTHORITATIVE_INFORMATION = 203,
NO_CONTENT = 204,
RESET_CONTENT = 205,
PARTIAL_CONTENT = 206,
MULTI_STATUS = 207,
ALREADY_REPORTED = 208,
IM_USED = 226,
MULTIPLE_CHOICES = 300,
MOVED_PERMANENTLY = 301,
FOUND = 302,
SEE_OTHER = 303,
NOT_MODIFIED = 304,
USE_PROXY = 305,
TEMPORARY_REDIRECT = 307,
PERMANENT_REDIRECT = 308,
BAD_REQUEST = 400,
UNAUTHORIZED = 401,
PAYMENT_REQUIRED = 402,
FORBIDDEN = 403,
NOT_FOUND = 404,
METHOD_NOT_ALLOWED = 405,
NOT_ACCEPTABLE = 406,
PROXY_AUTHENTICATION_REQUIRED = 407,
REQUEST_TIMEOUT = 408,
CONFLICT = 409,
GONE = 410,
LENGTH_REQUIRED = 411,
PRECONDITION_FAILED = 412,
PAYLOAD_TOO_LARGE = 413,
URI_TOO_LONG = 414,
UNSUPPORTED_MEDIA_TYPE = 415,
RANGE_NOT_SATISFIABLE = 416,
EXPECTATION_FAILED = 417,
MISDIRECTED_REQUEST = 421,
UNPROCESSABLE_UNTITY = 422,
LOCKED = 423,
FAILED_DEPENDENCY = 424,
TOO_EARLY = 425,
UPGRADE_REQUIRED = 426,
PRECONDITION_REQUIRED = 428,
TOO_MANY_REQUESTS = 429,
REQUEST_HEADER_FIELDS_TOO_LARGE = 431,
LOGIN_TIMEOUT = 440,
UNAVAILABLE_FOR_LEGAL_REASONS = 451,
INTERNAL_SERVER_ERROR = 500,
NOT_IMPLEMENTED = 501,
BAD_GATEWAY = 502,
SERVICE_UNAVAILABLE = 503,
GATEWAY_TIMEOUT = 504,
HTTP_VERSION_NOT_SUPPORTED = 505,
VARIANT_ALSO_NEGOTIATES = 506,
INSUFFICIENT_STORAGE = 507,
LOOP_DETECTED = 508,
NOT_EXTENDED = 510,
NETWORK_AUTHENTICATION_REQUIRED = 511,

样例

import pkg.http_server;
import pkg.http_server.router;

language.set_internal_encoding("utf-8");

string encoding = "utf-8";
if (get_system_info().os == "windows")
encoding = "GBK";
language.set_io_translator(this_coroutine().get_output(), language.get_internal_encoding(), encoding);


object r = new_object(router);

// 使用会话及重定向
r.add_get("/", parallel (Request req, Response res)
{
object session = req.get_session();
if (session)
res.set_content(string.format("Hello, %s", session=>get("username")));
else
res.redirect("/login.html");
});

// 文件上传
r.add_post("/upload", parallel (Request req, Response res)
{
for (string name, map uploaded_file : req.files)
{
printf("Upload file: %s, %s\n", uploaded_file.filename, uploaded_file.type);
file.write_all("/files/" + uploaded_file.filename, uploaded_file.data);
}
});

// 文件下载
r.add_post("/download", parallel (Request req, Response res)
{
string filename = req.query.file;
if (!filename)
{
res.set_content("Parameter 'file' missing");
return;
}

buffer content = file.read_all("/files/" + filename, "b");
if (!content)
{
res.set_content("File not found");
return;
}

res.set_content(content);
});

// 通过会话保存用户数据
r.add_post("/login", parallel (Request req, Response res)
{
string username = req.body.username;
string password = req.body.password;

object session = req.get_session(true);

if (username == session=>get("username"))
{
res.set_content("Logined");
}
else
{
session=>set("username", username);
res.set_content(string.format("Hello, %s", username));
}
});

// 响应json数据
r.add_get("/json", parallel (Request req, Response res)
{
res.set_content({"America": "New York", "China": "Beijing"});
});

#ifdef ENABLE_SSL
object app = http_server.create_server(9999, r, {
"cert_file": "sample/cert/cert.pem",
"key_file": "sample/cert/key.pem",
});
#else
object app = http_server.create_server(9999, r);
#endif

directory.mkdir("/files");

// 设置静态目录
app.set_static_dir("/www");

#ifdef ENABLE_DEBUG
app.enable_debug(true);
#endif

set_shutdown_callback(make_readonly(()
{
app.stop();
}));

@app.serve();