Data Server App Guide

The Data Server itself is written in Python. Python is also used to write Apps for the Data Server. You will want to brush up on your Python skills before starting out on the development of Apps for the Data Server. Python enables you to wrap any code or programs your organisation may have to integrate the Data Server into your organisation's IT systems in a seamless manner.

There are two types of Apps for the Data Server:

  1. HTTP Apps
  2. TTP Apps

     

See the Server Configuration documentation for information on how to integrate your Apps into the Data Server.


HTTP Apps

Apps for the HTTP Server are built with the Django framework* (included in the installer on Windows). Django is a Python web development framework used at places like the Washington Post. Django is easy to develop with and makes Python code development for the Data Server even faster.

See the Data Server Developer Model Documentation for included model specifications to assist with developing your own Apps for the HTTP Interface.


TTP Apps

Apps for the TTP Server are written in Python, usually a single file, and extend the base TTP Protocol while leveraging the power of the Data Server HTTP App models. Best practice development for the Data Server is to first develop models for your App with Django as HTTP Apps if required (which do not have to have any web facing views). Then import the model definitions into the TTP App and go from there. You can import any existing core model definitions as well.

TTP Apps have some specific implementation guidelines best illustrated with an example: the OK App included with the distribution. Below is the full Python source of the file ok.py in the TTPApps folder in the installation directory of the Data Server.

# -*- coding: utf-8 -*-
#------------------------------------------------------#
# Data Server TTP Interface 'OK' custom TTP extension. #
#------------------------------------------------------#

# DataServer Code listing (similar to HTTP):
# 200: 'OK'
# 201: 'Created'
# 202: 'Accepted'
# 203: 'Partial information'
# 204: 'No response'
# 301: 'Moved'
# 302: 'Found'
# 303: 'Method'
# 304: 'Not modified'
# 400: 'Bad request'
# 401: 'Authorization Required'
# 402: 'Unauthorized'
# 403: 'Forbidden'
# 404: 'Data not found'
# 405: 'Unit not found'
# 406: 'Duplicate sample'
# 500: 'Internal error'
# 501: 'Not implemented'
# 502: 'Service temporarily overloaded'
# 503: 'Gateway timeout'

# Producers are Class objects that have two methods:
# ``__init__`` and ``more``. The init method is given
# the server, request, unit (code) and key for the request.
# more() should return data to be transmitted on the channel.
# The producer indicates exhaustion (i.e. that it contains no more data)
# by having its more() method return the empty string
# Read Documentation on Producers here:
# http://docs.python.org/library/asynchat.html
from texmatedse.core.units.models import Unit

class OKProducer:
    """
    This is an example producer, it sends an OK signal back to
    the Unit sending the request if the Unit can be authenticated.
    The syntax of the request sent from the Unit for this producer is:
    
    ``TTP /ok/unit_code unit_key\r``
    
    And the response will look like:
    
    ``OK\r``
    
    The socket will remain open/closed according to the default
    socket settings in your ``txm.conf`` file.
    """
    
    def __init__(self, server, request, unit, key):
        # Setup environment here,
        # then call self.process_request()
        # to process the request.
        self.server = server    # TTP Data Server
        self.request = request  # TTP Request string
        self.unit = unit        # Unit code
        self.key = key          # Unit key
        self.done = 0           # Used to mark this channel as ready for pushing self.info
                                # and then closure.
        
        # More stuff here as required.
        
        self.process_request()  # Process the request now.
    
    def process_request(self):
        """
        Process the request, do the stuff, then 
        generate the self.info return result string for
        return with the more() method.
        """
        # Authenticate
        error_code = None # Error code.
        try:
            unit = Unit.objects.get(code=self.unit)
        except Unit.DoesNotExist:
            error_code = 405
        else:
            if not unit.check_key(self.key):
                error_code = 402
        if error_code:
            msg = self.server.responses[error_code]
            self.info = self.server.ERROR_MESSAGE % {'code': error_code, 'message': msg}
            self.server.failed_requests.increment()
            return
        # Passed checks:
        # Do stuff here as required.
        self.info = 'OK\r' # Don't forget the trailing \r to keep the TTP Protocol specification.
    
    def more(self):
        if self.done:
            return ''
        else:
            self.done = 1
            self.server.bytes_out.increment(len(self.info)) # Keep track of bytes sent.
            return self.info

# Define Extension to be loaded:
Extension = {
    'code': 'ok',           # eg: TTP /ok/unit_code/<The rest of the command> unit_key
    'run_before': None,     # Callable to run before the producer is called.
    'producer': OKProducer, # TTP Producer to run when ``code`` is detected.
    'run_after': None,      # Callable to run after the producer has exited.
}

There are two parts to TTP Apps: the Producer and the Extension definition. Reading the documentation in the above code should give a pretty clear idea of what each part does.

The Extension part of the App is a Python dictionary, named Extension that defines how the extension is handled by the TTP Server. There are four parts that are valid in the definition: code, run_before, producer, and run_after. Two are required: code, and producer.

  1. code defines the extension to the TTP Protocol, such that in the above example TTP /ok/ what the TTP Parser is looking for to farm off the request to the OK Producer. The next part of the request is the unit code of the sending unit TTP /ok/unit_code.
  2. producer is the name of your Producer. When a request matching your specification is detected, this named producer is called - OKProducer in the above case.
  3. run_before specifies a callable to be run by the server before the request is sent to your producer. Omit this key, or set it to None, if you do not need to run anything before your producer is called.
  4. run_after specifies a callable to be run by the server after the response has been sent by your producer. Omit this key, or set it to None, if you do not need to run anything after your producer has finished.

↑ Top


*The Django Software Foundation does not endorse this product. Django is merely the framework with which this product was written, and which you can use to extend it.

Texmate Data Server Documentation