"""
Program:

  Simple HTTP redirector.

Metadata:

  Author: Michal Guerquin (michalg@gmail.com)
  Date: January, 2005
  Version: 0.1
  License: GNU General Public License

Documentation:

  URL_TO_RESPONSE is a mapping of url regular expressions to responses.
  
    The regex is matched against the requested path (this includes the
    first slash).
    
    The response is a three element tuple:
      1. the response code (301, 404, etc.)
      2. a dictionary of header name to header value mappings to send with
         the response (i.e., "Content-type" or "Location")
      3. the content of the page
    
    If a regex doesn't match the requested URL, a 404 is returned. If
    something is broken (the dictionary of header names isn't a dictionary
    at all, for example) then a 500 is returned.
  
  PORTNUMS is a list of port numbers to which the server should bind.
  
  HOWLONG indicates how long the server should be up in seconds. 0 means
  infintely long.
  
  Stdout will receive lines like "YYYY-MM-DD HH:MM:SS - port - host - path"
  where port is the port number that was queried, host is the client host,
  and path is the requested path.
"""

import BaseHTTPServer
import re
import thread
import time

# --- config starts here

PORTNUMBERS = (8000,8001,8002) # port numbers to listen on
HOWLONG     = 0                # how many seconds to run before exiting
URL_TO_RESPONSE = {}
# add new responses after this template:
URL_TO_RESPONSE[".*"] = (301, {"Content-type":"text/plain", "Location":"http://www.google.com" }, "You are being redirected.")

# --- config ends here

class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler):

  def version_string(self):
    return "Redirector/1.0"

  def do_GET(self):
    self.answer_request(self.path)
    return

  def do_POST(self):
    self.answer_request(self.path)
    return

  def answer_request(self, path):
    try:
      for url in URL_TO_RESPONSE.keys():
        if re.compile(url).match(self.path,0):
          self.respond(URL_TO_RESPONSE[url])
          return
      self.respond((404, {"Content-type":"text/plain"}, "404 Not Found"))
      return
    except:
      self.respond((500, {"Content-type":"text/plain"}, "500 Internal Server Error"))

  def respond(self, r):
    self.send_response(r[0])
    for k,v in r[1].items():
      self.send_header(k, v)
    self.end_headers()
    self.wfile.write(r[2])
    return

  def log_request(self, code=200, size=0):
    print "%s - %s - %s - %s" % ( time.strftime("%F %T") , self.server.server_port, self.address_string(), self.path)

def run(portnum):
  portnum = portnum or 8000
  server_address = ('', portnum)
  httpd = BaseHTTPServer.HTTPServer(server_address, MyHandler)
  print "Starting server on port", portnum
  httpd.serve_forever()

for p in PORTNUMBERS:
  thread.start_new_thread( run , (p,) )

if HOWLONG == 0:
  while 1: time.sleep(10)
else:
  time.sleep(HOWLONG)

print "Done."
