swift_test.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. package swift
  2. import (
  3. "context"
  4. "net/http"
  5. "testing"
  6. "time"
  7. "github.com/ncw/swift/v2"
  8. "github.com/ncw/swift/v2/swifttest"
  9. "github.com/stretchr/testify/suite"
  10. "github.com/imgproxy/imgproxy/v3/config"
  11. )
  12. const (
  13. testContainer = "test"
  14. testObject = "foo/test.png"
  15. )
  16. type SwiftTestSuite struct {
  17. suite.Suite
  18. server *swifttest.SwiftServer
  19. transport http.RoundTripper
  20. etag string
  21. lastModified time.Time
  22. }
  23. func (s *SwiftTestSuite) SetupSuite() {
  24. s.server, _ = swifttest.NewSwiftServer("localhost")
  25. config.Reset()
  26. config.SwiftAuthURL = s.server.AuthURL
  27. config.SwiftUsername = swifttest.TEST_ACCOUNT
  28. config.SwiftAPIKey = swifttest.TEST_ACCOUNT
  29. config.SwiftAuthVersion = 1
  30. s.setupTestFile()
  31. var err error
  32. s.transport, err = New()
  33. s.Require().NoError(err, "failed to initialize swift transport")
  34. }
  35. func (s *SwiftTestSuite) setupTestFile() {
  36. c := &swift.Connection{
  37. UserName: config.SwiftUsername,
  38. ApiKey: config.SwiftAPIKey,
  39. AuthUrl: config.SwiftAuthURL,
  40. AuthVersion: config.SwiftAuthVersion,
  41. }
  42. ctx := context.Background()
  43. err := c.Authenticate(ctx)
  44. s.Require().NoError(err, "failed to authenticate with test server")
  45. err = c.ContainerCreate(ctx, testContainer, nil)
  46. s.Require().NoError(err, "failed to create container")
  47. f, err := c.ObjectCreate(ctx, testContainer, testObject, true, "", "image/png", nil)
  48. s.Require().NoError(err, "failed to create object")
  49. defer f.Close()
  50. data := make([]byte, 32)
  51. n, err := f.Write(data)
  52. s.Require().Len(data, n)
  53. s.Require().NoError(err)
  54. f.Close()
  55. // The Etag is written on file close; but Last-Modified is only available when we get the object again.
  56. _, h, err := c.Object(ctx, testContainer, testObject)
  57. s.Require().NoError(err)
  58. s.etag = h["Etag"]
  59. s.lastModified, err = time.Parse(http.TimeFormat, h["Date"])
  60. s.Require().NoError(err)
  61. }
  62. func (s *SwiftTestSuite) TearDownSuite() {
  63. s.server.Close()
  64. }
  65. func (s *SwiftTestSuite) TestRoundTripWithETagDisabledReturns200() {
  66. config.ETagEnabled = false
  67. request, _ := http.NewRequest("GET", "swift://test/foo/test.png", nil)
  68. response, err := s.transport.RoundTrip(request)
  69. s.Require().NoError(err)
  70. s.Require().Equal(200, response.StatusCode)
  71. }
  72. func (s *SwiftTestSuite) TestRoundTripReturns404WhenObjectNotFound() {
  73. config.ETagEnabled = true
  74. request, _ := http.NewRequest("GET", "swift://test/foo/not-here.png", nil)
  75. response, err := s.transport.RoundTrip(request)
  76. s.Require().NoError(err)
  77. s.Require().Equal(404, response.StatusCode)
  78. }
  79. func (s *SwiftTestSuite) TestRoundTripReturns404WhenContainerNotFound() {
  80. config.ETagEnabled = true
  81. request, _ := http.NewRequest("GET", "swift://invalid/foo/test.png", nil)
  82. response, err := s.transport.RoundTrip(request)
  83. s.Require().NoError(err)
  84. s.Require().Equal(404, response.StatusCode)
  85. }
  86. func (s *SwiftTestSuite) TestRoundTripWithETagEnabled() {
  87. config.ETagEnabled = true
  88. request, _ := http.NewRequest("GET", "swift://test/foo/test.png", nil)
  89. response, err := s.transport.RoundTrip(request)
  90. s.Require().NoError(err)
  91. s.Require().Equal(200, response.StatusCode)
  92. s.Require().Equal(s.etag, response.Header.Get("ETag"))
  93. }
  94. func (s *SwiftTestSuite) TestRoundTripWithIfNoneMatchReturns304() {
  95. config.ETagEnabled = true
  96. request, _ := http.NewRequest("GET", "swift://test/foo/test.png", nil)
  97. request.Header.Set("If-None-Match", s.etag)
  98. response, err := s.transport.RoundTrip(request)
  99. s.Require().NoError(err)
  100. s.Require().Equal(http.StatusNotModified, response.StatusCode)
  101. }
  102. func (s *SwiftTestSuite) TestRoundTripWithUpdatedETagReturns200() {
  103. config.ETagEnabled = true
  104. request, _ := http.NewRequest("GET", "swift://test/foo/test.png", nil)
  105. request.Header.Set("If-None-Match", s.etag+"_wrong")
  106. response, err := s.transport.RoundTrip(request)
  107. s.Require().NoError(err)
  108. s.Require().Equal(http.StatusOK, response.StatusCode)
  109. }
  110. func (s *SwiftTestSuite) TestRoundTripWithLastModifiedDisabledReturns200() {
  111. config.LastModifiedEnabled = false
  112. request, _ := http.NewRequest("GET", "swift://test/foo/test.png", nil)
  113. response, err := s.transport.RoundTrip(request)
  114. s.Require().NoError(err)
  115. s.Require().Equal(200, response.StatusCode)
  116. }
  117. func (s *SwiftTestSuite) TestRoundTripWithLastModifiedEnabled() {
  118. config.LastModifiedEnabled = true
  119. request, _ := http.NewRequest("GET", "swift://test/foo/test.png", nil)
  120. response, err := s.transport.RoundTrip(request)
  121. s.Require().NoError(err)
  122. s.Require().Equal(200, response.StatusCode)
  123. s.Require().Equal(s.lastModified.Format(http.TimeFormat), response.Header.Get("Last-Modified"))
  124. }
  125. func (s *SwiftTestSuite) TestRoundTripWithIfModifiedSinceReturns304() {
  126. config.LastModifiedEnabled = true
  127. request, _ := http.NewRequest("GET", "swift://test/foo/test.png", nil)
  128. request.Header.Set("If-Modified-Since", s.lastModified.Format(http.TimeFormat))
  129. response, err := s.transport.RoundTrip(request)
  130. s.Require().NoError(err)
  131. s.Require().Equal(http.StatusNotModified, response.StatusCode)
  132. }
  133. func (s *SwiftTestSuite) TestRoundTripWithUpdatedLastModifiedReturns200() {
  134. config.LastModifiedEnabled = true
  135. request, _ := http.NewRequest("GET", "swift://test/foo/test.png", nil)
  136. request.Header.Set("If-Modified-Since", s.lastModified.Add(-24*time.Hour).Format(http.TimeFormat))
  137. response, err := s.transport.RoundTrip(request)
  138. s.Require().NoError(err)
  139. s.Require().Equal(http.StatusOK, response.StatusCode)
  140. }
  141. func TestSwiftTransport(t *testing.T) {
  142. suite.Run(t, new(SwiftTestSuite))
  143. }