text: # Copyright L.P.Klyne 2013 
  # Licenced under 3 clause BSD licence 
  
  from turbogears import controllers, expose, flash
  import cherrypy
  from cherrypy.filters import basefilter
  
  import logging
  log = logging.getLogger("jsproxy.controllers")
  
  import httplib
  
  def makeQuery(kwargs):
      """
      Make query element of URI from a supplied dictionary
      """
      return (kwargs and "?"+"&".join([ k+"="+v for (k,v) in kwargs.iteritems()])) or ""
  
  def makePath(path):
      """
      Make path element of URI from a supplied list of segments.
      The leadfing '/' is not included.
      """
      return "/".join(path)
  
  class LeavePostDataFilter(basefilter.BaseFilter):
      """
      Filter supresses parsing of request body - I'm not sure why I have to do this,
      as CherryPy isn't supposed to try and parse field values unless the content-type 
      indicates a suitable form response.
      
      Er, it seems that 'application/x-www-form-urlencoded' is the default content-type
      generated by CURL, or maybe supplied in absence of given content-type?
      """
      def before_request_body(self):
          if cherrypy.request.path[0:6] == '/Proxy':
              # if you don't check that it is a post method the server might lock up
              # we also check to make shour something was submitted
              if not 'Content-Length' in cherrypy.request.headerMap or cherrypy.request.method != 'POST':
                  """ the file is empty you might want to redirect"""
              else:
                  # Tell CherryPy not to parse the POST data itself for this URL
                  cl = cherrypy.request.headers["Content-Length"]
                  if cl:
                      cherrypy.request.body = cherrypy.request.rfile.read(int(cl))
                      cherrypy.request.processRequestBody = False
  
  class Proxy:
      """
      Requests proxied to servers on other ports
  
      Here is a Curl command for texting this:
  
      curl -H "Content-type: text/plain" -i -d "[\"idle\",[]]" http://localhost:8080/Proxy/8082
      """
  
      ### Filter not needed if content-type is OK?
      ### _cp_filters = [LeavePostDataFilter()]
  
      @expose()
      def default(self, *args, **kwargs):
          body = getattr(cherrypy.request, "body", None)
          body = body and body.read()
          logRequest(body, args, kwargs)
          headers = cherrypy.request.headers
          port = int(args[0])
          path = args[1:]
          htc = httplib.HTTPConnection("localhost", port)
          adr = "http://localhost:"+str(port)+"/"
          uri = adr+makePath(path)+makeQuery(kwargs)
          log.debug("Proxy uri %s", uri)
          # request( method, url[, body[, headers]])
          # htc.request("GET", uri, body, headers)
          htc.request(cherrypy.request.method, uri, body)
          rsp = htc.getresponse()
          if not rsp:
              cherrypy.response.status = "500 No response from GET "+adr+uri
              return "500 No response from GET "+adr+uri
          if rsp.status != 200:
              logResponse(rsp)
              cherrypy.response.status = str(rsp.status)+" "+rsp.reason
              return str(rsp.status)+" "+rsp.reason
          cherrypy.response.headers["Cache-control"] = "no-cache"
          cherrypy.response.headers["Pragma"]        = "no-cache"
          cherrypy.response.status = str(rsp.status)+" "+rsp.reason
          rspbody = rsp.read()
          logResponse(rsp, rspbody)
          return rspbody
  
  class Root(controllers.RootController):
      Proxy = Proxy()
  
      @expose(template="jsproxy.templates.Home")
      def index(self):
          logRequest(None, [], {})
          import time
          # log.debug("Happy TurboGears Controller Responding For Duty")
          flash("Your application is now running")
          return dict(now=time.ctime())
  
      @expose()
      def default(self, *args, **kwargs):
          body = getattr(cherrypy.request, "body", None)
          body = body and body.read()
          logRequest(body, args, kwargs)
          line = cherrypy.request.requestLine
          body = getattr(cherrypy.request, "body", None)
          headers = cherrypy.request.headers
          return "<h1>Default response</h1>\n<p>%s</p><p>%s</p><p>%s, %s</p>\n"%(line,headers,args,kwargs)
  
  def logRequest(body, *args, **kwargs):
      log.debug("Request %s", cherrypy.request.requestLine)
      log.debug("Method %s, path %s", cherrypy.request.method, cherrypy.request.path)
      log.debug("Args %s, %s", str(args), str(kwargs))
      headers = cherrypy.request.headers.copy()
      strip_headers = ('Remote-Addr', 'Accept-Language', 'Accept-Encoding', 
          'Keep-Alive', 'Remote-Host', 'Host', 'Accept', 'User-Agent', 
          'Accept-Charset', 'Connection', 'Pragma', 'Cache-Control',
          'X-Requested-With', 'referer')
      for k in strip_headers:
          if k in headers: del headers[k]
      log.debug("Headers '%s'", headers)
      log.debug("Request body '%s'", body)
      return
  
  def logResponse(rsp, body=""):
      log.debug("Response %i, %s", rsp.status, rsp.reason)
      log.debug("Headers %s", repr(rsp.getheaders()))
      log.debug("Response body '%s'", body)
      return
  
  