swift_test.go 5.4 KB

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