pages.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. # -*- test-case-name: twisted.web.test.test_pages -*-
  2. # Copyright (c) Twisted Matrix Laboratories.
  3. # See LICENSE for details.
  4. """
  5. Utility implementations of L{IResource}.
  6. """
  7. __all__ = (
  8. "errorPage",
  9. "notFound",
  10. "forbidden",
  11. )
  12. from typing import cast
  13. from twisted.web import http
  14. from twisted.web.iweb import IRenderable, IRequest
  15. from twisted.web.resource import IResource, Resource
  16. from twisted.web.template import renderElement, tags
  17. class _ErrorPage(Resource):
  18. """
  19. L{_ErrorPage} is a resource that responds to all requests with a particular
  20. (parameterized) HTTP status code and an HTML body containing some
  21. descriptive text. This is useful for rendering simple error pages.
  22. @see: L{twisted.web.pages.errorPage}
  23. @ivar _code: An integer HTTP status code which will be used for the
  24. response.
  25. @ivar _brief: A short string which will be included in the response body as
  26. the page title.
  27. @ivar _detail: A longer string which will be included in the response body.
  28. """
  29. def __init__(self, code: int, brief: str, detail: str) -> None:
  30. super().__init__()
  31. self._code: int = code
  32. self._brief: str = brief
  33. self._detail: str = detail
  34. def render(self, request: IRequest) -> object:
  35. """
  36. Respond to all requests with the given HTTP status code and an HTML
  37. document containing the explanatory strings.
  38. """
  39. request.setResponseCode(self._code)
  40. request.setHeader(b"content-type", b"text/html; charset=utf-8")
  41. return renderElement(
  42. request,
  43. # cast because the type annotations here seem off; Tag isn't an
  44. # IRenderable but also probably should be? See
  45. # https://github.com/twisted/twisted/issues/4982
  46. cast(
  47. IRenderable,
  48. tags.html(
  49. tags.head(tags.title(f"{self._code} - {self._brief}")),
  50. tags.body(tags.h1(self._brief), tags.p(self._detail)),
  51. ),
  52. ),
  53. )
  54. def getChild(self, path: bytes, request: IRequest) -> Resource:
  55. """
  56. Handle all requests for which L{_ErrorPage} lacks a child by returning
  57. this error page.
  58. @param path: A path segment.
  59. @param request: HTTP request
  60. """
  61. return self
  62. def errorPage(code: int, brief: str, detail: str) -> _ErrorPage:
  63. """
  64. Build a resource that responds to all requests with a particular HTTP
  65. status code and an HTML body containing some descriptive text. This is
  66. useful for rendering simple error pages.
  67. The resource dynamically handles all paths below it. Use
  68. L{IResource.putChild()} to override a specific path.
  69. @param code: An integer HTTP status code which will be used for the
  70. response.
  71. @param brief: A short string which will be included in the response
  72. body as the page title.
  73. @param detail: A longer string which will be included in the
  74. response body.
  75. @returns: An L{IResource}
  76. """
  77. return _ErrorPage(code, brief, detail)
  78. def notFound(
  79. brief: str = "No Such Resource",
  80. message: str = "Sorry. No luck finding that resource.",
  81. ) -> IResource:
  82. """
  83. Generate an L{IResource} with a 404 Not Found status code.
  84. @see: L{twisted.web.pages.errorPage}
  85. @param brief: A short string displayed as the page title.
  86. @param brief: A longer string displayed in the page body.
  87. @returns: An L{IResource}
  88. """
  89. return _ErrorPage(http.NOT_FOUND, brief, message)
  90. def forbidden(
  91. brief: str = "Forbidden Resource", message: str = "Sorry, resource is forbidden."
  92. ) -> IResource:
  93. """
  94. Generate an L{IResource} with a 403 Forbidden status code.
  95. @see: L{twisted.web.pages.errorPage}
  96. @param brief: A short string displayed as the page title.
  97. @param brief: A longer string displayed in the page body.
  98. @returns: An L{IResource}
  99. """
  100. return _ErrorPage(http.FORBIDDEN, brief, message)