Utilities for a JSON-based API.
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.

69 lines
1.8 KiB

  1. package impart
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "strconv"
  6. )
  7. type (
  8. // Envelope contains metadata and optional data for a response object.
  9. // Responses will always contain a status code and either:
  10. // - response Data on a 2xx response, or
  11. // - an ErrorMessage on non-2xx responses
  12. //
  13. // ErrorType is not currently used.
  14. Envelope struct {
  15. Code int `json:"code"`
  16. ErrorType string `json:"error_type,omitempty"`
  17. ErrorMessage string `json:"error_msg,omitempty"`
  18. Data interface{} `json:"data,omitempty"`
  19. }
  20. )
  21. func writeBody(w http.ResponseWriter, body []byte, status int, contentType string) error {
  22. w.Header().Set("Content-Type", contentType+"; charset=UTF-8")
  23. w.Header().Set("Content-Length", strconv.Itoa(len(body)))
  24. w.WriteHeader(status)
  25. _, err := w.Write(body)
  26. return err
  27. }
  28. func renderJSON(w http.ResponseWriter, value interface{}, status int) error {
  29. body, err := json.Marshal(value)
  30. if err != nil {
  31. return err
  32. }
  33. return writeBody(w, body, status, "application/json")
  34. }
  35. func renderString(w http.ResponseWriter, status int, msg string) error {
  36. return writeBody(w, []byte(msg), status, "text/plain")
  37. }
  38. // WriteSuccess writes the successful data and metadata to the ResponseWriter as
  39. // JSON.
  40. func WriteSuccess(w http.ResponseWriter, data interface{}, status int) error {
  41. env := &Envelope{
  42. Code: status,
  43. Data: data,
  44. }
  45. return renderJSON(w, env, status)
  46. }
  47. // WriteError writes the error to the ResponseWriter as JSON.
  48. func WriteError(w http.ResponseWriter, e HTTPError) error {
  49. env := &Envelope{
  50. Code: e.Status,
  51. ErrorMessage: e.Message,
  52. }
  53. return renderJSON(w, env, e.Status)
  54. }
  55. // WriteRedirect sends a redirect
  56. func WriteRedirect(w http.ResponseWriter, e HTTPError) int {
  57. w.Header().Set("Location", e.Message)
  58. w.WriteHeader(e.Status)
  59. return e.Status
  60. }