server.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. import os
  2. import logging
  3. import falcon
  4. # import json
  5. import WikiProcessor
  6. logger = logging.getLogger(f"logger_main")
  7. # base_dir = "." # os.path.abspath(os.path.dirname(__file__)) + "/"
  8. # logger.info(f"base_dir: {base_dir}")
  9. wiki = WikiProcessor.WikiProcessor()
  10. class PageHandler():
  11. def __init__(self):
  12. self.logger = logging.getLogger(f"logger_{__name__}")
  13. self.sink_slug = "/page/"
  14. def on_get(self, req, resp):
  15. # the part after the sink slug is the remaining url
  16. slug = req.relative_uri.split(self.sink_slug)[1]
  17. self.logger.info(f"accessing page: {slug}")
  18. resp.status = falcon.HTTP_200
  19. resp.content_type = "text/html"
  20. resp.body = wiki.get_page_by_name(slug)
  21. return
  22. class IndexHandler():
  23. def __init__(self):
  24. self.logger = logging.getLogger(f"logger_{__name__}")
  25. def on_get(self, req, resp):
  26. self.logger.info("accessing index page")
  27. resp.status = falcon.HTTP_200
  28. resp.content_type = "text/html"
  29. resp.body = wiki.get_index_page()
  30. return
  31. class StaticResource():
  32. def __init__(self):
  33. self.logger = logging.getLogger(f"logger_{__name__}")
  34. self.sink_slug = "/static/"
  35. def get_file_ending(self, url):
  36. return url.split("?")[0].split(".")[-1]
  37. def remove_query_params(self, url):
  38. return url.split("?")[0]
  39. def path_is_parent(self, parent_path, child_path):
  40. # Smooth out relative path names, note: If you are concerned
  41. # about symbolic links, you should use os.path.realpath too.
  42. parent_path = os.path.abspath(parent_path)
  43. child_path = os.path.abspath(child_path)
  44. common = os.path.commonpath([parent_path, child_path])
  45. # Compare the common path of the parent and child path with
  46. # the common path of just the parent path. Using the
  47. # commonpath method on just the parent path will regularise
  48. # the path name in the same way as the comparison that deals
  49. # with both paths, removing any trailing path separator
  50. return os.path.commonpath([parent_path]) == common
  51. def on_get(self, req, resp):
  52. # the part after the sink slug is the remaining url
  53. self.logger.info("uri: {}".format(req.relative_uri))
  54. self.logger.info("part after /static/: {}".format(
  55. req.relative_uri.split(self.sink_slug)[1]))
  56. part_after_static = req.relative_uri.split(self.sink_slug)[1]
  57. slug = os.path.join("static", self.remove_query_params(part_after_static))
  58. # security check
  59. assert self.path_is_parent("static", slug)
  60. self.logger.info(f"accessing static resource: {slug}")
  61. if self.path_is_parent("static", slug):
  62. if "." in req.relative_uri:
  63. file_format = self.get_file_ending(req.relative_uri)
  64. self.logger.info(f"file format is: {file_format}")
  65. if file_format == "css":
  66. self.logger.info(f"serving a css file from {slug}")
  67. resp.content_type = "text/css"
  68. resp.status = falcon.HTTP_200
  69. body = None
  70. with open(slug, mode="r") as resource:
  71. body = resource.read()
  72. resp.body = body
  73. return
  74. elif file_format in ["png", "jpg", "jpeg"]:
  75. self.logger.info("serving an image file")
  76. resp.content_type = "/".join(["image", file_format])
  77. resp.status = falcon.HTTP_200
  78. body = None
  79. with open(slug, mode="rb") as resource:
  80. body = resource.read()
  81. resp.body = body
  82. return
  83. elif file_format == "js": # or file_format.split("?")[0] == "js":
  84. self.logger.info("serving js file")
  85. resp.content_type = "text/javascript"
  86. resp.status = falcon.HTTP_200
  87. body = None
  88. with open(slug, mode="r") as resource:
  89. body = resource.read()
  90. resp.body = body
  91. return
  92. else:
  93. self.logger.info(f"trying to access unknown file format: {file_format}")
  94. resp.status = falcon.HTTP_404
  95. resp.content_type = "text/plain"
  96. resp.body = "404"
  97. return
  98. else:
  99. self.logger.info("Requested file has no file ending. "
  100. "Unsure how to return it.")
  101. resp.status = falcon.HTTP_404
  102. resp.content_type = "text/plain"
  103. resp.body = "404"
  104. return
  105. else:
  106. self.logger.info("Requested file not in static directory. "
  107. "Permission to access supposedly static file denied.")
  108. resp.status = falcon.HTTP_403
  109. resp.content_type = "text/plain"
  110. resp.body = "403"
  111. return
  112. class UnknownRouteHandler():
  113. def __init__(self):
  114. self.logger = logging.getLogger(f"logger_{__name__}")
  115. def on_get(self, req, resp):
  116. self.logger.info("accessing unknown route")
  117. resp.status = falcon.HTTP_404
  118. resp.content_type = "text/html"
  119. resp.body = "404"
  120. return
  121. api = app = falcon.API()
  122. api.add_route("/", IndexHandler())
  123. api.add_sink(PageHandler().on_get, prefix="/page/")
  124. api.add_sink(StaticResource().on_get, prefix="/static/")
  125. api.add_sink(UnknownRouteHandler().on_get, prefix="/")