8. Integrating With Operation Tools via REST API

You definitely need operation tools once your game service goes live (for monitoring what’s happening in your game and for managing your players). There might be many ways to integrate with operation tools, but we found from our experience that it’s simple and convenient to have the game server expose REST APIs and to make the operation tools invoke the APIs. For this purpose, iFun Engine supports to easily add RESTful APIs.

8.1. Adding REST API for operation tools

Let’s assume we need APIs to ban/unban a player. To figure out if a given player has been banned, we will have a flag named Banned in Character in hello_world-source/src/object_model/example.json.

{
  "User": {
    "Id": "String KEY",
    "MyCharacter": "Character"
  },
  "Character": {
    "Name": "String KEY",
    "Exp": "Integer",
    "Level": "Integer",
    "Hp": "Integer",
    "Mp": "Integer",
    "Sp": "Integer",
    "Banned": "bool"
  }
}

We now know iFun Engine will automatically alter the Character DB table according to this change. Next, we register a REST API POST /v1/cs/ban/<character>/<state>/ in hello_world-source/src/event_handlers.cc. We also need to implement a handler for the API URL.

Here’s a working implementation. Please note that API URL pattern follows the Perl’s regular expression. So, (?<user>\\w+) matches a word and gives it a name user.

void OnBlockCharacter(
    Ptr<http::Response> response,
    const http::Request &request,
    const ApiService::MatchResult &params) {
  string character = params["character"];
  string state = params["state"];
  LOG(INFO) << "character: [" << character << "]";
  LOG(INFO) << "state: [" << state << "]";

  bool result = false;
  Ptr<Character> c = Character::FetchByName(character);
  if (c) {
    c->SetBanned(state == "1");
    result = true;
  }

  response->status_code = http::kOk;
  response->header.insert(std::make_pair("Content-Type", "plain/text"));
  response->body = result;
}


void RegisterEventHandlers() {
  ...
  ApiService::RegisterHandler(
      http::kPost,
      boost::regex("/v1/cs/ban/(?<character>\\w+)/(?<state>\\w+)"),
      OnBlockCharacter);

  ...
}

8.2. Enabling the API feature

API service listens at port 8014, by default. If you want to change it, simply edit hello_world-source/src/MANIFEST.lobby.json like this:

...
"ApiService": {
  "api_service_port": 8014
},
...

Note

As explained in Adding a client-server message, iFun Engine supports client messages on HTTP and so matching URLs also look like REST APIs. Though the API for the client messages and the API for operation tools look similar, it’s desirable to separate management traffic from regular client-server traffic. That’s why iFun Engine uses a separate port for the management API service.

8.3. Testing the added API

Let’s give a try to invoke the API. As before, it’s OK to use either Terminal, Chrome, or Firefox. Please note that we have registered the API with the http::kPost method.

First, run the lobby server.

$ ./hello_world.lobby-local

Then, invoke the added API.

$ wget --post-data="{}" -qO- http://localhost:8014/v1/cs/ban/ifun/1

Do you see a log message from the server like this?

I0309 16:43:52.674099 17302 api_service.cc:81] "POST /v1/cs/ban/ifun/1" 200

We implemented the player ban feature very easily!

8.4. REST APIs given by default for operation tools

iFun Engine is shipped with predefined APIs to help game server monitoring. Just GET /v1/ and you will find what APIs are there.

$ wget -qO- http://localhost:8014/v1/
[
    {
        "method": "GET",
        "url": "/v1/"
    },
    {
        "method": "GET",
        "url": "/v1/counters/"
    },
    {
        "method": "GET",
        "url": "/v1/counters/all/"
    },
    {
        "method": "GET",
        "url": "/v1/counters/(?<type>\\w+)/"
    },
    {
        "method": "GET",
        "url": "/v1/counters/(?<type>\\w+)/(?<id>\\w+)/"
    },
    {
        "method": "GET",
        "url": "/v1/counters/(?<type>\\w+)/(?<id>\\w+)/description/"
    },
    {
        "method": "GET",
        "url": "/v1/maintenance/"
    },
    {
        "method": "GET",
        "url": "/v1/configurations/"
    },
    {
        "method": "GET",
        "url": "/v1/configurations/(?<name>\\w+)/"
    },
    {
        "method": "POST",
        "url": "/v1/cs/ban/(?<character>\\w+)/(?<state>\\w+)/"
    },
    {
        "method": "PUT",
        "url": "/v1/maintenance/update/"
    },
    {
        "method": "PUT",
        "url": "/v1/configurations/(?<name>\\w+)/(?<value>\\w+)/"
    }
]

Among the APIs, counter-related ones are especially useful for they can be used to monitor your server. You can get stats on the host, OS, and iFun Engine from the counter. And you can also augment the counter to emit stats on your game logic. For example, you can export information about the number of an expensive item through the counter. If you find this number rapidly goes up, you may detect game economy anomalies or item duplication bugs. Please refer to iFun Engine reference manual to learn how to augment the counter.

$ wget -qO- http://localhost:8014/v1/counters
[
  "process",
  "funapi_object_model",
  "os",
  "funapi"
]
$ wget -qO- http://localhost:8014/v1/counters/funapi/sessions
0