response_handler_test.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. // SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
  2. // SPDX-License-Identifier: Apache-2.0
  3. package fetcher // import "miniflux.app/v2/internal/reader/fetcher"
  4. import (
  5. "net/http"
  6. "testing"
  7. "time"
  8. )
  9. func TestIsModified(t *testing.T) {
  10. var cachedEtag = "abc123"
  11. var cachedLastModified = "Wed, 21 Oct 2015 07:28:00 GMT"
  12. var testCases = map[string]struct {
  13. Status int
  14. LastModified string
  15. ETag string
  16. IsModified bool
  17. }{
  18. "Unmodified 304": {
  19. Status: 304,
  20. LastModified: cachedLastModified,
  21. ETag: cachedEtag,
  22. IsModified: false,
  23. },
  24. "Unmodified 200": {
  25. Status: 200,
  26. LastModified: cachedLastModified,
  27. ETag: cachedEtag,
  28. IsModified: false,
  29. },
  30. // ETag takes precedence per RFC9110 8.8.1.
  31. "Last-Modified changed only": {
  32. Status: 200,
  33. LastModified: "Thu, 22 Oct 2015 07:28:00 GMT",
  34. ETag: cachedEtag,
  35. IsModified: false,
  36. },
  37. "ETag changed only": {
  38. Status: 200,
  39. LastModified: cachedLastModified,
  40. ETag: "xyz789",
  41. IsModified: true,
  42. },
  43. "ETag and Last-Modified changed": {
  44. Status: 200,
  45. LastModified: "Thu, 22 Oct 2015 07:28:00 GMT",
  46. ETag: "xyz789",
  47. IsModified: true,
  48. },
  49. }
  50. for name, tc := range testCases {
  51. t.Run(name, func(tt *testing.T) {
  52. header := http.Header{}
  53. header.Add("Last-Modified", tc.LastModified)
  54. header.Add("ETag", tc.ETag)
  55. rh := ResponseHandler{
  56. httpResponse: &http.Response{
  57. StatusCode: tc.Status,
  58. Header: header,
  59. },
  60. }
  61. if tc.IsModified != rh.IsModified(cachedEtag, cachedLastModified) {
  62. tt.Error(name)
  63. }
  64. })
  65. }
  66. }
  67. func TestRetryDelay(t *testing.T) {
  68. var testCases = map[string]struct {
  69. RetryAfterHeader string
  70. ExpectedDelay int
  71. }{
  72. "Empty header": {
  73. RetryAfterHeader: "",
  74. ExpectedDelay: 0,
  75. },
  76. "Integer value": {
  77. RetryAfterHeader: "42",
  78. ExpectedDelay: 42,
  79. },
  80. "HTTP-date": {
  81. RetryAfterHeader: time.Now().Add(42 * time.Second).Format(time.RFC1123),
  82. ExpectedDelay: 41,
  83. },
  84. }
  85. for name, tc := range testCases {
  86. t.Run(name, func(tt *testing.T) {
  87. header := http.Header{}
  88. header.Add("Retry-After", tc.RetryAfterHeader)
  89. rh := ResponseHandler{
  90. httpResponse: &http.Response{
  91. Header: header,
  92. },
  93. }
  94. if tc.ExpectedDelay != rh.ParseRetryDelay() {
  95. tt.Errorf("Expected %d, got %d for scenario %q", tc.ExpectedDelay, rh.ParseRetryDelay(), name)
  96. }
  97. })
  98. }
  99. }