vADC Docs

Serving Web Content from Stingray using Python

by on ‎04-22-2013 07:13 AM - edited on ‎07-08-2015 01:36 PM by PaulWallace (3,587 Views)

There are many reasons why you may want to serve web content directly from Stingray Traffic Manager - simplification, performance, ease of administration and, perhaps most importantly, to host a 'Sorry Page' if your entire web infrastructure has failed and Stingray is all that is left.

 

The article Using Stingray Traffic Manager as a Webserver describes the rationale in more detail and presents a simple TrafficScript-based webserver.  However, we can do a lot more with a more complete programming language - mime types, index pages, more control over the location of the document root are all simple to implement with Python.

 

Get started with PyRunner.jar

 

Start with the procedure describe in the article PyRunner.jar: Running Python code in Stingray Traffic Manager.  The PyRunner extension lets you run Python code in Stingray, using the local JVM and the Jython implementation.

 

Note that this example does not work reliably with versions of Jython prior to 2.7 beta1 - I hit problems when a library attempted to import the Jython errno module (possibly related to https://github.com/int3/doppio/issues/177).

 

webserver.py

 

Once you've installed PyRunner (using an appropriate version of Jython), upload the following Python script to your Extra Files catalog.  Make sure to call the script 'webserver.py', and edit the location of the docroot to an appropriate value:

 

from javax.servlet.http import HttpServlet  
from urllib import url2pathname  
from os import listdir  
from os.path import normpath,isdir,isfile,getmtime,getsize  
import mimetypes  
import datetime  
  
docroot = '/tmp'  
  
def dirlist( uri, path, response ):  
   files = ''  
   for f in listdir( path ):  
      if (f[0] == '.') and (f[1] != '.'):  
         continue # hidden files  
  
      if isdir( path+'/'+f ):  
         size = '<DIR>'  
         f += '/' # Add trailing slash for directories  
      else:  
         size = '{:,d} bytes'.format( getsize( path+'/'+f ))  
  
      mtime = datetime.datetime.fromtimestamp( getmtime( path+'/'+f ))  
  
      files += '<a href="{f}">{f:<30}</a> {t:14} {sSmiley Embarassed17}\n'.format(  
         f=f, t=mtime, s=size )  
  
   html = ''''' 
      <html><head><title>{uri}</title></head><body> 
      <h1>Directory listing for {uri}</h1> 
      <pre>{files}<a href="../">Up</a></pre> 
      </body></html>''' .format(uri=uri, files=files )  
   response.setContentType( 'text/html' )  
   toClient = response.getWriter()  
   toClient.write( html )  
  
class webserver(HttpServlet):  
    
   def doGet(self, request, response):  
      uri = request.getRequestURI()  
       
      print "Processing "+uri  
      path =  normpath( docroot + url2pathname( uri ) )  
  
      # Never access files outside the docroot  
      if path.startswith( docroot ) == False:  
         path = docroot  
         uri = '/'  
  
      if isdir( path ):  
         if uri.endswith( '/' ) == False:  
            response.sendRedirect( uri+'/' )  
         if isfile( path + '/index.html' ):  
            response.sendRedirect( uri + 'index.html' )  
         else:  
            dirlist( uri, path, response )  
         return  
  
      try:  
         c = open( path, 'r' ).read()  
      except Exception, e:  
         response.sendError( 400, "Could not read "+path+": "+str( e ) )  
         return  
  
  
      mtype = mimetypes.guess_type( path )[0]  
      if mtype == None:  
         mtype = 'application/octet-stream'  
  
      response.setContentType( mtype )  
      toClient = response.getWriter()  
      toClient.write( c )  

 

If you want to edit the rule and try some changes, they you'll find the publish.py script in Deploying Python code to Stingray Traffic Manager useful, and you should follow the Stingray Event log (tail -f /opt/zeus/zxtm/log/errors) to catch any problems.

 

Performance Optimization

 

The article Using Stingray Traffic Manager as a Webserver describes how to front the web server virtual server with a second virtual server that caches responses and responds directly to web requests.

 

It also presents an alternative webserver implementation written in Java - take your pick!

Contributors