You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 rivejä
4.3 KiB

  1. #!/usr/bin/python
  2. # -*- coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-
  3. import re
  4. import imp
  5. import os
  6. class WSGIRouter(object):
  7. """ parse http uri and call the proper handler (controller in MVC terms)
  8. """
  9. def __init__( self, handlers=(), fallback=None ):
  10. """ handlers = list of tuples in the form ( regex, handler )
  11. groups in regex are passed to handlers within environ['router.args']
  12. fallback = if defined, is the default handler to be called if no
  13. regex in 'handlers' matches
  14. """
  15. self.handlers = handlers
  16. self.fallback = fallback
  17. def __call__( self, environ, start_response ):
  18. #
  19. # search form matching handler
  20. #
  21. for regex, handler in self.handlers:
  22. match = re.match( '^' + regex + '$', environ['SCRIPT_URL'])
  23. if match:
  24. environ['router.args'] = match.groups()
  25. return handler( environ, start_response )
  26. #
  27. # use fallback ( if defined )
  28. #
  29. if self.fallback:
  30. environ['router.args'] = [
  31. token for token in environ['SCRIPT_URL'].split('/') if token ]
  32. return self.fallback( environ, start_response )
  33. #
  34. # last resort
  35. #
  36. start_response( '202 Accepted', [('Content-Type', 'text/plain')] )
  37. return [ "WSGIRouter: I have no route for '%s'" % environ['SCRIPT_URL'] ]
  38. class WSGISmartRouter(object):
  39. """ like WSGIRouter, but before calling fallback handler,
  40. searches in 'cont_dir' folder for a file matching the url.
  41. uri = http://<server[:port]>/lorem/ipsum/dolor/sit
  42. handler: environ['router.args']:
  43. any handler matching in handlers - capture groups -
  44. <cont_dir>/lorem/ipsum/dolor/sit ()
  45. <cont_dir>/lorem/ipsum/dolor ('sit')
  46. <cont_dir>/lorem/ipsum ('dolor','sit')
  47. <cont_dir>/lorem ('ipsum','dolor','sit')
  48. fallback ('lorem','ipsum','dolor','sit')
  49. """
  50. def __init__( self, handlers=(), fallback=None, cont_dir='.' ):
  51. self.handlers = handlers
  52. self.fallback = fallback
  53. self.cont_dir = os.path.normpath( os.path.join( os.path.split(__file__)[0], cont_dir ) ) + '/'
  54. def __call__( self, environ, start_response ):
  55. #
  56. # search form matching handler
  57. #
  58. for regex, handler in self.handlers:
  59. match = re.match( '^' + regex + '$', environ['SCRIPT_URL'])
  60. if match:
  61. environ['router.args'] = match.groups()
  62. return handler( environ, start_response )
  63. #
  64. # search in filesystem for matching file
  65. #
  66. tokens = [ token for token in environ['SCRIPT_URL'].split('/') if token ]
  67. #for idx in range( 1, len( tokens ) + 1 ): # from shortest path to longest one
  68. # from longest path to shortest one
  69. for idx in range( len( tokens ) , 0, -1 ):
  70. module = os.path.normpath( self.cont_dir + '/'.join( tokens[:idx] ) + '.py' )
  71. args = tokens[idx:]
  72. try:
  73. handler = imp.load_source( 'application', module )
  74. environ['router.args'] = args
  75. if environ['REQUEST_METHOD'] == 'GET' and hasattr( handler, 'get' ):
  76. # FIXME: forse è meglio eseguire QUI la start_response
  77. # e compilare il template (solo per GET e POST)
  78. return handler.get( environ, start_response )
  79. elif environ['REQUEST_METHOD'] == 'POST' and hasattr( handler, 'post' ):
  80. return handler.post( environ, start_response )
  81. elif hasattr( handler, 'application' ):
  82. return handler.application( environ, start_response )
  83. except IOError:
  84. # not found! Better luck next time...
  85. pass
  86. #
  87. # use fallback ( if defined )
  88. #
  89. if self.fallback:
  90. environ['router.args'] = tokens
  91. return self.fallback( environ, start_response )
  92. #
  93. # last resort
  94. #
  95. start_response( '202 Accepted', [('Content-Type', 'text/plain')] )
  96. return [ "WSGISmartRouter: I have no route for '%s'" % environ['SCRIPT_URL'] ]