34. Server management part 1: Adding RESTful APIs¶
iFun Engine provides a function to easily add RESTful APIs inside the game server. By using this function, you can easily connect to various xternal systems using the HTTP protocol.
34.1. Registering handlers and REST API URLs¶
You can use the following function to register a particular URL or URL pattern and the handler to process it.
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 text string to handle. Used when calling only one particular URL.
path_pattern: URL pattern to handle. Parameters can be included in the URL in
(?<NAME>pattern)
form and read asNAME
in the code. (See example below)handler: Handler function to handle that URL.
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)
34.2. Creating handlers¶
You can create a handler function as follows.
If duplicate keys are not allowed during parameter transfer through HTTP GET
void MyHandler( Ptr<http::Response> response, const http::Request &request, const ApiService::MatchResult ¶ms) { response->status_code = http::kOk; response->body = ... }
If duplicate keys are allowed during parameter transfer through HTTP GET
void MyHandler2( Ptr<http::Response> response, const http::Request2 &request, const ApiService::MatchResult ¶ms) { response->status_code = http::kOk; response->body = ... }
If the response body is asynchronously generated (duplicate keys permitted for HTTP GET parameters)
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); }
Handling a single URL synchronously
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; }
Handling synchronously when the URL is given as a 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; }
Handling a single URL asynchronously
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); }
Handling asynchronously when the URL is given as a 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); }
34.3. Example of API service registration¶
The following example shows registration of two APIs.
-
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);
...
}
|
34.4. ApiService parameters¶
api_service_port: Local TCP port number to switch to administrative RESTful API service. (type=uint64, default=8015)
api_service_logging_level: Log level for administrative RESTful API messages. If 0, no logs are kept. If 1, only errors are logged. If 2, all requests are logged (type=uint64, default=2)
Parameters with configurations that are almost never changed manually
api_service_event_tags_size: Number of administrative RESTful API services switching simultaneously (type=uint64, default=1)