33. 服务器管理Part 1: 添加RESTful APIs¶
iFun引擎提供了可以在game server内轻松实现RESTful API的功能。 使用该功能,可通过HTTP协议轻松与不同外部系统进行联动。
33.1. 注册REST API URL和处理器¶
可运用以下函数注册URL、URL Pattern,以及对其进行处理的处理器。
static void ApiService::RegisterHandler(const http::Method &method,
const boost::regex &path_pattern,
const Handler &handler)
static void ApiService::RegisterHandler2(const http::Method &method,
const boost::regex &path_pattern,
const Handler2 &handler)
static void ApiService::RegisterHandler3 (const http::Method &method,
const boost::regex &path_pattern,
const Handler3 &handler)
public static void ApiService.RegisterHandler (http.Method method,
string path,
Handler handler)
public static void ApiService.RegisterHandler (http.Method method,
string path,
AsyncHandler handler)
public static void ApiService.RegisterHandler (http.Method method,
Regex path_pattern,
HandlerForRegexPath handler)
public static void ApiService.RegisterHandler (http.Method method,
Regex path_pattern,
AsyncHandlerForRegexPath handler)
method:
http::kGet
,http::kPut
,http::kPost
,http::kDelete
,http::kHead
.path: 要处理的URL字符串。指定某个特定URL时使用。
path_pattern: 要处理的URL pattern。以
(?<NAME>pattern)
的形式将parameter包含在URL中,可在代码中通过NAME
读取。(参照以下示例)handler: 处理相应URL的handler函数。
typedef boost::function<
void(const Ptr<http::Response> &)>
ResponseWriter ASSERT_NO_ROLLBACK;
typedef boost::function<
void(Ptr<http::Response> ret,
const http::Request &request,
const MatchResult ¶ms)> Handler;
typedef boost::function<
void(Ptr<http::Response> ret,
const http::Request2 &request,
const MatchResult ¶ms)> Handler2;
typedef boost::function<
void(const http::Request2 &request,
const MatchResult ¶ms,
const ResponseWriter &finisher)> Handler3;
public delegate void ResponseWriter(http.Response response);
public delegate http.Response Handler (http.Request request);
public delegate void AsyncHandler (http.Request request,
ResponseWriter response_writer);
public delegate http.Response HandlerForRegexPath (http.Request request,
MatchCollection matches);
public delegate void AsyncHandlerForRegexPath (http.Request request,
MatchCollection matches,
ResponseWriter response_writer);
Important
만약 HTTP 응답을 바로 보내지 않고 비동기적으로 처리해야 한다면 (다른 처리를 비동기로 진행한 후에 HTTP 응답을 보내고 싶다면) 아래 함수로 핸들러를 등록하시면 비동기로 처리 할 수 있습니다.
static void ApiService::RegisterHandler3 (const http::Method &method,
const boost::regex &path_pattern,
const Handler3 &handler)
public static void ApiService.RegisterHandler (http.Method method,
string path,
AsyncHandler handler)
public static void ApiService.RegisterHandler (http.Method method,
Regex path_pattern,
AsyncHandlerForRegexPath handler)
33.2. 编写处理器¶
handler函数可按如下所示编写。
通过HTTP GET传过来的参数中不允许有重复的key时
void MyHandler( Ptr<http::Response> response, const http::Request &request, const ApiService::MatchResult ¶ms) { response->status_code = http::kOk; response->body = ... }
通过HTTP GET传过来的参数中允许有重复的key时
void MyHandler2( Ptr<http::Response> response, const http::Request2 &request, const ApiService::MatchResult ¶ms) { response->status_code = http::kOk; response->body = ... }
非同步生成Response body时(HTTP GET的参数允许重复的key)
void MyHandler3( const http::Request2 &request, const ApiService::MatchResult ¶ms, const ApiService::ResponseWriter &finisher) { some_async_func(finisher); } void some_async_func(const ApiService::ResponseWriter &finisher) { Ptr<http::Response> response(new http::Response); finisher(response); }
同步处理单一URL
funapi.http.Response MySyncHandler1(funapi.http.Request request) { funapi.http.Response response = new funapi.http.Response (); response.status_code = funapi.http.StatusCode.kOk; response.body = ... return response; }
URL已通过pattern指定时,同步处理
funapi.http.Response MySyncHandler2(funapi.http.Request request, MatchCollection matches) { funapi.http.Response response = new funapi.http.Response (); response.status_code = funapi.http.StatusCode.kOk; response.body = ... return response; }
非同步处理单一URL
void MyAsyncHandler1(funapi.http.Request request, ResponseWriter finisher) { some_async_func(finisher) } void some_async_func(ResponseWriter finisher) { funapi.http.Response response = new funapi.http.Response (); response.status_code = funapi.http.StatusCode.kOk; response.body = ... finisher(response); }
URL已通过pattern指定时,非同步处理
void MyAsyncHandler2(funapi.http.Request request, MatchCollection matches, ResponseWriter finisher) { some_async_func(finisher) } void some_async_func(ResponseWriter finisher) { funapi.http.Response response = new funapi.http.Response (); response.status_code = funapi.http.StatusCode.kOk; response.body = ... finisher(response); }
33.3. API Service注册示例¶
下面是注册如下所示的2个API的示例。
-
GET
/example/hello
¶
-
GET
/example/hello2/*/*
¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | // request: http://localhost:8014/example/hello
// response: hello!
void OnHello(Ptr<http::Response> response,
const http::Request &request,
const ApiService::MatchResult ¶ms) {
response->status_code = http::kOk;
response->header.insert(std::make_pair("Content-Type", "text/plain"));
response->body = "hello!";
}
// request: http://localhost:8014/example/hello2/bob/24
// response:
// {
// "name": "bob",
// "age": "24"
// }
void OnHello2(Ptr<http::Response> response,
const http::Request &request,
const ApiService::MatchResult ¶ms) {
Json msg;
msg["name"] = params["name"];
msg["age"] = params["age"];
response->status_code = http::kOk;
response->header.insert(std::make_pair("Content-Type", "application/json"));
response->body = msg.ToString();
}
static bool Install(const ArgumentMap &arguments) {
...
ApiService::RegisterHandler(
http::kGet, boost::regex("/example/hello"), OnHello);
ApiService::RegisterHandler(http::kGet,
boost::regex("/example/hello2/(?<name>\\w+)/(?<age>\\w+)/"), OnHello2);
...
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | using System.Text.RegularExpressions;
using System.Collections.Specialized;
using funapi;
// request: http://localhost:8014/example/hello
// response: hello!
public static funapi.http.Response OnHello(funapi.http.Request request)
{
funapi.http.Response response = new funapi.http.Response ();
response.status_code = funapi.http.StatusCode.kOk;
response.body = "hello"; // response body
return response;
}
// request: http://localhost:8014/example/hello2/bob/24
// response:
// {
// "name": "bob",
// "age": "24"
// }
public static funapi.http.Response OnHello2(
funapi.http.Request request,
MatchCollection collection)
{
funapi.http.Response response = new funapi.http.Response ();
response.header = new NameValueCollection ();
response.header.Add ("Content-Type", "application/json");
response.status_code = funapi.http.StatusCode.kOk;
JObject msg = new JObject ();
GroupCollection groups = collection [0]. Groups;
msg ["name"] = groups ["name"].Value;
msg ["age"] = groups ["age"].Value;
response.body = msg.ToString ();
return response;
}
public static void Install(ArgumentMap arguments)
{
...
ApiService.RegisterHandler (
funapi.http.Method.kGet, "/example/hello", OnHello);
ApiService.RegisterHandler (
funapi.http.Method.kGet,
new Regex("/example/hello2/(?<name>\\w+)/(?<age>\\w+)/"),
OnHello2);
...
}
|
33.4. ApiService功能设置参数¶
api_service_port: 用于运行管理专用RESTful API服务的本地TCP端口编号。(type=uint64, default=8015)
api_service_logging_level: 管理专用RESTful API消息的日志级别。0为不保存日志。1为仅在出错时保存。2为对所有请求保存日志(type=uint64, default=2)
几乎不需要直接更改设置的参数
api_service_event_tags_size: 同时运行管理专用RESTful API服务的个数(type=uint64, default=1)