A fork of hyde, the static site generation. Some patches will be pushed upstream.
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.
 
 
 

162 lines
5.6 KiB

  1. # -*- coding: utf-8 -*-
  2. """
  3. Contains classes and utilities for serving a site
  4. generated from hyde.
  5. """
  6. import os
  7. import urlparse
  8. import urllib
  9. from SimpleHTTPServer import SimpleHTTPRequestHandler
  10. from BaseHTTPServer import HTTPServer
  11. from hyde.fs import File, Folder
  12. from hyde.site import Site
  13. from hyde.generator import Generator
  14. from hyde.exceptions import HydeException
  15. from hyde.util import getLoggerWithNullHandler
  16. logger = getLoggerWithNullHandler('hyde.server')
  17. from datetime import datetime
  18. class HydeRequestHandler(SimpleHTTPRequestHandler):
  19. """
  20. Serves files by regenerating the resource (or)
  21. everything when a request is issued.
  22. """
  23. def do_GET(self):
  24. """
  25. Identify the requested path. If the query string
  26. contains `refresh`, regenerat the entire site.
  27. Otherwise, regenerate only the requested resource
  28. and serve.
  29. """
  30. self.server.request_time = datetime.now()
  31. logger.info("Processing request:[%s]" % self.path)
  32. result = urlparse.urlparse(self.path)
  33. query = urlparse.parse_qs(result.query)
  34. if 'refresh' in query:
  35. self.server.regenerate()
  36. del query['refresh']
  37. parts = tuple(result)
  38. parts[4] = urllib.urlencode(query)
  39. new_url = urlparse.urlunparse(parts)
  40. logger.info('Redirecting...[%s]' % new_url)
  41. self.redirect(new_url)
  42. else:
  43. SimpleHTTPRequestHandler.do_GET(self)
  44. def translate_path(self, path):
  45. """
  46. Finds the absolute path of the requested file by
  47. referring to the `site` variable in the server.
  48. """
  49. path = SimpleHTTPRequestHandler.translate_path(self, path)
  50. site = self.server.site
  51. result = urlparse.urlparse(self.path)
  52. logger.debug("Trying to load file based on request:[%s]" % result.path)
  53. path = result.path.lstrip('/')
  54. if path.strip() == "" or File(path).kind.strip() == "":
  55. return site.config.deploy_root_path.child(path)
  56. res = site.content.resource_from_relative_deploy_path(path)
  57. if not res:
  58. # Check if its a new request
  59. if self.server.request_time > self.server.regeneration_time:
  60. # Cannot find the source file using the given path.
  61. # Check if the target file exists in the deploy folder.
  62. # this file is probably new or being generated by a plugin.
  63. # lets not try too hard, just regenerate
  64. logger.info("Attempting regeneration for:[%s]" % path)
  65. self.server.regenerate()
  66. res = site.content.resource_from_relative_deploy_path(path)
  67. if not res:
  68. # Nothing much we can do.
  69. logger.error("Cannot load file:[%s]" % path)
  70. return site.config.deploy_root_path.child(path)
  71. else:
  72. self.server.generate_resource(res)
  73. new_path = site.config.deploy_root_path.child(
  74. res.relative_deploy_path)
  75. return new_path
  76. def do_404(self):
  77. """
  78. Sends a 'not found' response.
  79. """
  80. site = self.server.site
  81. if self.path != site.config.not_found:
  82. self.redirect(site.config.not_found)
  83. else:
  84. res = site.content.resource_from_relative_deploy_path(
  85. site.config.not_found)
  86. message = "Requested resource not found"
  87. if not res:
  88. logger.error(
  89. "Cannot find the 404 template[%s]."
  90. % site.config.not_found)
  91. else:
  92. f404 = File(self.translate_path(site.config.not_found))
  93. if f404.exists:
  94. message = f404.read_all()
  95. self.send_response(200, message)
  96. def redirect(self, path, temporary=True):
  97. """
  98. Sends a redirect header with the new location.
  99. """
  100. self.send_response(302 if temporary else 301)
  101. self.send_header('Location', path)
  102. self.end_headers()
  103. class HydeWebServer(HTTPServer):
  104. """
  105. The hyde web server that regenerates the resource, node or site when
  106. a request is issued.
  107. """
  108. def __init__(self, site, address, port):
  109. self.site = site
  110. self.site.load()
  111. self.generator = Generator(self.site)
  112. self.request_time = datetime.strptime('1-1-1999', '%m-%d-%Y')
  113. self.regeneration_time = datetime.strptime('1-1-1998', '%m-%d-%Y')
  114. HTTPServer.__init__(self, (address, port),
  115. HydeRequestHandler)
  116. def regenerate(self):
  117. """
  118. Regenerates the entire site.
  119. """
  120. try:
  121. logger.info('Regenerating the entire site')
  122. self.regeneration_time = datetime.now()
  123. self.site.load()
  124. self.generator.generate_all()
  125. except Exception, exception:
  126. logger.error('Error occured when regenerating the site [%s]'
  127. % exception.message)
  128. def generate_resource(self, resource):
  129. """
  130. Regenerates the given resource.
  131. """
  132. target = self.site.config.deploy_root_path.child(
  133. resource.relative_deploy_path)
  134. if self.generator.has_resource_changed(resource):
  135. try:
  136. logger.info('Generating resource [%s]' % resource)
  137. self.generator.generate_resource(resource)
  138. except Exception, exception:
  139. logger.error(
  140. 'Error [%s] occured when generating the resource [%s]'
  141. % (repr(exception), resource))