reader.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. package storage
  2. import (
  3. "context"
  4. "io"
  5. "net/http"
  6. "strconv"
  7. "strings"
  8. "github.com/imgproxy/imgproxy/v3/httpheaders"
  9. )
  10. // Reader represents a generic storage interface, which can read
  11. // objects from a storage backend.
  12. type Reader interface {
  13. // GetObject retrieves an object from the storage and returns
  14. // ObjectReader with the result.
  15. GetObject(
  16. ctx context.Context,
  17. reqHeader http.Header,
  18. bucket, key, query string,
  19. ) (*ObjectReader, error)
  20. }
  21. // ObjectReader represents a generic reader for a storage object.
  22. // It can be in any state: success, error, not found, etc.
  23. // It can be converted to HTTP response or used as-is.
  24. type ObjectReader struct {
  25. Status int // HTTP status code
  26. Headers http.Header // Response headers harvested from the engine response
  27. Body io.ReadCloser // Response body reader
  28. contentLength int64
  29. }
  30. // NewObjectOK creates a new Reader with a 200 OK status.
  31. func NewObjectOK(headers http.Header, body io.ReadCloser) *ObjectReader {
  32. return &ObjectReader{
  33. Status: http.StatusOK,
  34. Headers: headers,
  35. Body: body,
  36. contentLength: -1, // is set in Response()
  37. }
  38. }
  39. // NewObjectPartialContent creates a new Reader with a 206 Partial Content status.
  40. func NewObjectPartialContent(headers http.Header, body io.ReadCloser) *ObjectReader {
  41. return &ObjectReader{
  42. Status: http.StatusPartialContent,
  43. Headers: headers,
  44. Body: body,
  45. contentLength: -1, // is set in Response()
  46. }
  47. }
  48. // NewObjectNotFound creates a new Reader with a 404 Not Found status.
  49. func NewObjectNotFound(message string) *ObjectReader {
  50. return NewObjectError(http.StatusNotFound, message)
  51. }
  52. // NewObjectError creates a new Reader with a custom status code
  53. func NewObjectError(statusCode int, message string) *ObjectReader {
  54. return &ObjectReader{
  55. Status: statusCode,
  56. Body: io.NopCloser(strings.NewReader(message)),
  57. Headers: http.Header{httpheaders.ContentType: {"text/plain"}},
  58. contentLength: int64(len(message)),
  59. }
  60. }
  61. // NewObjectNotModified creates a new Reader with a 304 Not Modified status.
  62. func NewObjectNotModified(headers http.Header) *ObjectReader {
  63. // Copy headers relevant to NotModified response only
  64. nmHeaders := make(http.Header)
  65. httpheaders.Copy(
  66. headers,
  67. nmHeaders,
  68. []string{httpheaders.Etag, httpheaders.LastModified},
  69. )
  70. return &ObjectReader{
  71. Status: http.StatusNotModified,
  72. Headers: nmHeaders,
  73. contentLength: 0,
  74. }
  75. }
  76. // NewInvalidRang creates a new Reader with a 416 Range Not Satisfiable status.
  77. func NewObjectInvalidRange() *ObjectReader {
  78. return &ObjectReader{
  79. Status: http.StatusRequestedRangeNotSatisfiable,
  80. contentLength: 0,
  81. }
  82. }
  83. // ContentLength returns the content length of the response.
  84. func (r *ObjectReader) ContentLength() int64 {
  85. if r.contentLength > 0 {
  86. return r.contentLength
  87. }
  88. h := r.Headers.Get(httpheaders.ContentLength)
  89. if len(h) > 0 {
  90. p, err := strconv.ParseInt(h, 10, 64)
  91. if err != nil {
  92. return p
  93. }
  94. }
  95. return -1
  96. }
  97. // Response converts Reader to http.Response
  98. func (r *ObjectReader) Response(req *http.Request) *http.Response {
  99. return &http.Response{
  100. Status: http.StatusText(r.Status),
  101. StatusCode: r.Status,
  102. Proto: "HTTP/1.0",
  103. ProtoMajor: 1,
  104. ProtoMinor: 0,
  105. Header: r.Headers,
  106. Body: r.Body,
  107. Close: true,
  108. Request: req,
  109. ContentLength: r.ContentLength(),
  110. }
  111. }