html.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. // SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
  2. // SPDX-License-Identifier: Apache-2.0
  3. package html // import "miniflux.app/v2/internal/http/response/html"
  4. import (
  5. "log/slog"
  6. "net/http"
  7. "miniflux.app/v2/internal/http/request"
  8. "miniflux.app/v2/internal/http/response"
  9. )
  10. // OK creates a new HTML response with a 200 status code.
  11. func OK(w http.ResponseWriter, r *http.Request, body interface{}) {
  12. builder := response.New(w, r)
  13. builder.WithHeader("Content-Type", "text/html; charset=utf-8")
  14. builder.WithHeader("Cache-Control", "no-cache, max-age=0, must-revalidate, no-store")
  15. builder.WithBody(body)
  16. builder.Write()
  17. }
  18. // ServerError sends an internal error to the client.
  19. func ServerError(w http.ResponseWriter, r *http.Request, err error) {
  20. slog.Error(http.StatusText(http.StatusInternalServerError),
  21. slog.Any("error", err),
  22. slog.String("client_ip", request.ClientIP(r)),
  23. slog.Group("request",
  24. slog.String("method", r.Method),
  25. slog.String("uri", r.RequestURI),
  26. slog.String("user_agent", r.UserAgent()),
  27. ),
  28. slog.Group("response",
  29. slog.Int("status_code", http.StatusInternalServerError),
  30. ),
  31. )
  32. builder := response.New(w, r)
  33. builder.WithStatus(http.StatusInternalServerError)
  34. builder.WithHeader("Content-Security-Policy", `default-src 'self'`)
  35. builder.WithHeader("Content-Type", "text/html; charset=utf-8")
  36. builder.WithHeader("Cache-Control", "no-cache, max-age=0, must-revalidate, no-store")
  37. builder.WithBody(err)
  38. builder.Write()
  39. }
  40. // BadRequest sends a bad request error to the client.
  41. func BadRequest(w http.ResponseWriter, r *http.Request, err error) {
  42. slog.Warn(http.StatusText(http.StatusBadRequest),
  43. slog.Any("error", err),
  44. slog.String("client_ip", request.ClientIP(r)),
  45. slog.Group("request",
  46. slog.String("method", r.Method),
  47. slog.String("uri", r.RequestURI),
  48. slog.String("user_agent", r.UserAgent()),
  49. ),
  50. slog.Group("response",
  51. slog.Int("status_code", http.StatusBadRequest),
  52. ),
  53. )
  54. builder := response.New(w, r)
  55. builder.WithStatus(http.StatusBadRequest)
  56. builder.WithHeader("Content-Security-Policy", `default-src 'self'`)
  57. builder.WithHeader("Content-Type", "text/html; charset=utf-8")
  58. builder.WithHeader("Cache-Control", "no-cache, max-age=0, must-revalidate, no-store")
  59. builder.WithBody(err)
  60. builder.Write()
  61. }
  62. // Forbidden sends a forbidden error to the client.
  63. func Forbidden(w http.ResponseWriter, r *http.Request) {
  64. slog.Warn(http.StatusText(http.StatusForbidden),
  65. slog.String("client_ip", request.ClientIP(r)),
  66. slog.Group("request",
  67. slog.String("method", r.Method),
  68. slog.String("uri", r.RequestURI),
  69. slog.String("user_agent", r.UserAgent()),
  70. ),
  71. slog.Group("response",
  72. slog.Int("status_code", http.StatusForbidden),
  73. ),
  74. )
  75. builder := response.New(w, r)
  76. builder.WithStatus(http.StatusForbidden)
  77. builder.WithHeader("Content-Type", "text/html; charset=utf-8")
  78. builder.WithHeader("Cache-Control", "no-cache, max-age=0, must-revalidate, no-store")
  79. builder.WithBody("Access Forbidden")
  80. builder.Write()
  81. }
  82. // NotFound sends a page not found error to the client.
  83. func NotFound(w http.ResponseWriter, r *http.Request) {
  84. slog.Warn(http.StatusText(http.StatusNotFound),
  85. slog.String("client_ip", request.ClientIP(r)),
  86. slog.Group("request",
  87. slog.String("method", r.Method),
  88. slog.String("uri", r.RequestURI),
  89. slog.String("user_agent", r.UserAgent()),
  90. ),
  91. slog.Group("response",
  92. slog.Int("status_code", http.StatusNotFound),
  93. ),
  94. )
  95. builder := response.New(w, r)
  96. builder.WithStatus(http.StatusNotFound)
  97. builder.WithHeader("Content-Type", "text/html; charset=utf-8")
  98. builder.WithHeader("Cache-Control", "no-cache, max-age=0, must-revalidate, no-store")
  99. builder.WithBody("Page Not Found")
  100. builder.Write()
  101. }
  102. // Redirect redirects the user to another location.
  103. func Redirect(w http.ResponseWriter, r *http.Request, uri string) {
  104. http.Redirect(w, r, uri, http.StatusFound)
  105. }
  106. // RequestedRangeNotSatisfiable sends a range not satisfiable error to the client.
  107. func RequestedRangeNotSatisfiable(w http.ResponseWriter, r *http.Request, contentRange string) {
  108. slog.Warn(http.StatusText(http.StatusRequestedRangeNotSatisfiable),
  109. slog.String("client_ip", request.ClientIP(r)),
  110. slog.Group("request",
  111. slog.String("method", r.Method),
  112. slog.String("uri", r.RequestURI),
  113. slog.String("user_agent", r.UserAgent()),
  114. ),
  115. slog.Group("response",
  116. slog.Int("status_code", http.StatusRequestedRangeNotSatisfiable),
  117. ),
  118. )
  119. builder := response.New(w, r)
  120. builder.WithStatus(http.StatusRequestedRangeNotSatisfiable)
  121. builder.WithHeader("Content-Type", "text/html; charset=utf-8")
  122. builder.WithHeader("Cache-Control", "no-cache, max-age=0, must-revalidate, no-store")
  123. builder.WithHeader("Content-Range", contentRange)
  124. builder.WithBody("Range Not Satisfiable")
  125. builder.Write()
  126. }