web_session_middleware_test.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. // SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
  2. // SPDX-License-Identifier: Apache-2.0
  3. package ui // import "miniflux.app/v2/internal/ui"
  4. import (
  5. "net/http"
  6. "net/http/httptest"
  7. "testing"
  8. "miniflux.app/v2/internal/http/request"
  9. )
  10. func TestWebSessionMiddlewareRedirectsWithoutCreatingSession(t *testing.T) {
  11. scenarios := []struct {
  12. name string
  13. cookie *http.Cookie
  14. }{
  15. {"no cookie", nil},
  16. {"malformed cookie", &http.Cookie{Name: sessionCookieName, Value: "invalid"}},
  17. }
  18. for _, scenario := range scenarios {
  19. t.Run(scenario.name, func(t *testing.T) {
  20. // A nil store makes the test fail if the middleware tries to persist a session.
  21. middleware := newWebSessionMiddleware("/base", nil)
  22. handler := middleware.handle(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  23. t.Fatal(`The next handler should not be called`)
  24. }))
  25. r := httptest.NewRequest(http.MethodGet, "/unread?page=2", nil)
  26. if scenario.cookie != nil {
  27. r.AddCookie(scenario.cookie)
  28. }
  29. w := httptest.NewRecorder()
  30. handler.ServeHTTP(w, r)
  31. if w.Code != http.StatusFound {
  32. t.Fatalf(`Unexpected status code, got: %d`, w.Code)
  33. }
  34. if location := w.Header().Get("Location"); location != "/base/?redirect_url=%2Funread%3Fpage%3D2" {
  35. t.Fatalf(`Unexpected redirect location, got: %q`, location)
  36. }
  37. if cookie := w.Header().Get("Set-Cookie"); cookie != "" {
  38. t.Fatalf(`No session cookie should be set, got: %q`, cookie)
  39. }
  40. })
  41. }
  42. }
  43. func TestWebSessionMiddlewareSkipsStaticAssets(t *testing.T) {
  44. middleware := newWebSessionMiddleware("", nil)
  45. called := false
  46. handler := middleware.handle(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  47. called = true
  48. }))
  49. w := httptest.NewRecorder()
  50. handler.ServeHTTP(w, httptest.NewRequest(http.MethodGet, "/favicon.ico", nil))
  51. if !called {
  52. t.Fatal(`The next handler should be called for static assets`)
  53. }
  54. if cookie := w.Header().Get("Set-Cookie"); cookie != "" {
  55. t.Fatalf(`No session cookie should be set, got: %q`, cookie)
  56. }
  57. }
  58. func TestWebSessionMiddlewareUsesInMemorySessionForPublicRoutes(t *testing.T) {
  59. scenarios := []struct {
  60. method string
  61. path string
  62. }{
  63. {http.MethodGet, "/share/code"},
  64. {http.MethodGet, "/manifest.json"},
  65. {http.MethodGet, "/offline"},
  66. {http.MethodGet, "/oauth2/google/callback"},
  67. {http.MethodPost, "/webauthn/login/finish"},
  68. }
  69. for _, scenario := range scenarios {
  70. t.Run(scenario.method+" "+scenario.path, func(t *testing.T) {
  71. configureTestOptions(t, map[string]string{"WEBAUTHN": "1", "OAUTH2_PROVIDER": "google"})
  72. // A nil store makes the test fail if the middleware tries to persist a session.
  73. middleware := newWebSessionMiddleware("", nil)
  74. called := false
  75. handler := middleware.handle(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  76. called = true
  77. session := request.WebSession(r)
  78. if session == nil {
  79. t.Fatal(`A web session should be available in the request context`)
  80. }
  81. if session.Language() != "fr_FR" || session.Theme() != "dark_serif" {
  82. t.Errorf(`Preferences should be seeded from the cookie, got %q and %q`, session.Language(), session.Theme())
  83. }
  84. // Changes to an in-memory session must not be persisted either.
  85. session.SetErrorMessage("error")
  86. }))
  87. r := httptest.NewRequest(scenario.method, scenario.path, nil)
  88. r.AddCookie(&http.Cookie{Name: preferencesCookieName, Value: "fr_FR.dark_serif"})
  89. w := httptest.NewRecorder()
  90. handler.ServeHTTP(w, r)
  91. if !called {
  92. t.Fatal(`The next handler should be called for public routes`)
  93. }
  94. if cookie := w.Header().Get("Set-Cookie"); cookie != "" {
  95. t.Fatalf(`No session cookie should be set, got: %q`, cookie)
  96. }
  97. })
  98. }
  99. }