Table of Contents
It is often useful to create a Web Service interface to a BigWorld server. This allows other standard services to be used to access game functionality via standard HTTP requests.
One way to expose a web service interface is to use the TwistedWeb Service provided. This uses the Twisted Python framework and its Twisted.Web module to map HTTP requests to script calls on game entities. Any of an entity's methods can be called on it in this way.
See http://twistedmatrix.com/documents/current/web for more detailed information on Twisted.Web.
A BigWorld Service is a scripted object like a Base-only entity. See Server Overview's section Design Introduction for more information.
BigWorld provides a standard TwistedWeb Service located at
bigworld/res/scripts/service/TwistedWeb.py
. This
service listens for HTTP requests on port 8000. It supports four types of
URL paths.
-
db/
<dbCommand>
?<arguments>
- This is used to invoke a command on the database such as logging on a player's entity. -
entities_by_id/
<entityType>
/<databaseID>
/<methodName>
?<arguments>
- This calls a method on an entity. -
entities_by_name/
<entityType>
/<entityName>
/<methodName>
?<arguments>
- This calls a method on a named entity. -
global_entities/
<globalName>
/<methodName>
?<arguments>
- This calls a method on an entity inBigWorld.globalBases
.
The responses to these requests are structured as JSON documents.
For example, in FantasyDemo, the method webTestMethod
for the global entity AuctionHouse
is used to test the
functionality of method calls using Twisted.Web.
In
fantasydemo/res/scripts/entity_defs/AuctionHouse.def
,
the method is declared as:
... <BaseMethods> ... <webTestMethod> <Args> <first_arg> INT32 </first_arg> <second_arg> STRING </second_arg> </Args> <ReturnValues> <first_result> INT32 </first_result> <second_result> STRING </second_result> </ReturnValues> </webTestMethod> ...
And in fantasydemo/res/scripts/base/AuctionHouse.py as:
class AuctionHouse( ... ): ... def webTestMethod( self, first_arg, second_arg ): return (2 * first_arg, second_arg.upper())
An instance of AuctionHouse has been registered with
BigWorld.globalBases
as 'AuctionHouse'
.
Therefore, requesting:
http://machine_name
:8000/global_entities/AuctionHouse/webTestMethod?first_arg=5&second_arg=Test
returns the JSON object:
{ "first_result": 10, "second_result": "TEST" }
There is currently only one command supported by the /db/ path. This has the form:
http://machine_name
:8000/db/logOn?username=username
&password=password
This attempts to log on the user. On success it returns the new entity's type and database id. For example,
{ "type": "Account", "id": 2 }
This information can then be used to make queries on this entity
using the path starting with
/entities_by_id/<entity_type>
/<database_id>
/<methodName>
.
Queries of the form
/entities_by_id/<entity_type>
/<database_id>
/<methodName>
?<args>
can be used to call methods on a specific entity.
For example, requesting:
http://machine_name
:8000/entities_by_id/Account/2/webGetCharacterList
might return:
{ "characters": [{"type": "Avatar", "databaseID": 1, "realm": "fantasy", "charClass": "ranger", "name": "MyChar"}] }
The details of one of the characters on this account can be
retrieved using
http://machine_name
:8000/entities_by_id/Account/2/webChooseCharacter?name=MyChar&type=Avatar:
{ "type": "Avatar", "id": 1 }
These queries are similar to entities_by_id expect that the database string identifier is expected instead of the database id. The entities_by_id form is preferred as queries by name need to query the database each time while repeated queries via database id will likely hit a local cache of the entity's mailbox on the ServiceApp. See KeepAlive messages below.
These queries allow calling methods on a base entity that has been
registered with BigWorld.globalBases
. The base entity must be
registered with a single string as the key. These queries have the
form:
http://machine_name
:8000/global_entities/<global_key>
/<methodName>
?<args>
The TwistedWeb service is defined in
bigworld/res/scripts/service_defs/TwistedWeb.def
, and
its methods are implemented in
bigworld/res/scripts/service/TwistedWeb.py
. Here, the
resource tree is built up using Twisted.Web's putChild
function, which takes as arguments the name of the path segment and the
type of the resource that will be returned by a request for it:
from TWResources.EntitiesResource import EntitiesByNameResource, EntitiesByIDResource from TWResources.GlobalEntitiesResource import GlobalEntitiesResource from TWResources.DBResource import DBResource class TwistedWeb( BigWorld.Service ): def __init__( self ): root = resource.Resource() root.putChild( "entities_by_name", EntitiesByNameResource() ) root.putChild( "entities_by_id", EntitiesByIDResource() ) root.putChild( "global_entities", GlobalEntitiesResource() ) root.putChild( "db", DBResource() ) reactor.listenTCP( 8000, server.Site( root ) ) reactor.startRunning() def onDestroy( self ): reactor.stop()
The various resources used by the TwistedWeb service are implemented
in the TWResources package, which is located at
bigworld/res/scripts/service/TWResources
.
In order to make use of the TwistedWeb service, it must be given an
entry in the
file in your project directory:
<res>
/scripts/services.xml
<root> ... <TwistedWeb/> </root>
This file contains a list of all Services that will be initialised when a ServiceApp process is started.
See http://twistedmatrix.com for more detailed information on the Twisted Python framework.
Two-way calls to the game server using the TwistedWeb service will
always return a JSON object. If an error occurs, the object that is
returned will have a specific error format. It will consist of two fields:
a string named excType
containing the error type, and
an array of strings named args
containing the
arguments. The returned document also uses the HTTP error code 403
(Forbidden).
For example, the sample /db/ queries given in section Queries to /db/ could fail in a number of ways. If the account does not exist on the server, the call will return:
{ "excType": "BWAuthenticateError", "args": [ "No such user" ] }
If the password is invalid, it will return:
{ "excType": "BWAuthenticateError", "args": [ "Invalid password" ] }
The
regular format of error objects returned from TwistedWeb means that
differentiating them from successful return objects only requires the
caller to check for the existence of the excType
key.
For details about the different types of errors that can be returned by a two-way call, refer to theServer Programming Guide's sectionBWStandardError.