86 lines
3.4 KiB
Go
86 lines
3.4 KiB
Go
package httpapi_test
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"git.nianxx.cn/wangxuming/NianAIGC/backend/internal/httpapi"
|
|
)
|
|
|
|
type logoutContract struct {
|
|
Version int `json:"version"`
|
|
Path string `json:"path"`
|
|
Methods []string `json:"methods"`
|
|
Status int `json:"status"`
|
|
Location string `json:"location"`
|
|
RequiresAuthentication bool `json:"requiresAuthentication"`
|
|
DuplicateBaseCookieWrite bool `json:"duplicateBaseCookieWrite"`
|
|
}
|
|
|
|
func TestAuthLogoutConsumesSharedContractAndClearsExactlyTwentyCookies(t *testing.T) {
|
|
var contract logoutContract
|
|
loadHTTPFixture(t, "logout-v1.json", &contract)
|
|
cookie := loadPasswordSessionCookieContract(t)
|
|
handler := httpapi.NewAuthLogoutHandler(httpapi.LogoutConfig{PublicBaseURL: "https://app.example.test"})
|
|
|
|
if contract.Version != 1 || contract.RequiresAuthentication || contract.DuplicateBaseCookieWrite {
|
|
t.Fatalf("invalid shared logout contract: %+v", contract)
|
|
}
|
|
for _, method := range contract.Methods {
|
|
t.Run(method, func(t *testing.T) {
|
|
request := httptest.NewRequest(method, "https://app.example.test"+contract.Path, nil)
|
|
response := httptest.NewRecorder()
|
|
handler.ServeHTTP(response, request)
|
|
|
|
if response.Code != contract.Status || response.Header().Get("Location") != contract.Location || response.Body.Len() != 0 {
|
|
t.Fatalf("response = %d location=%q body=%q", response.Code, response.Header().Get("Location"), response.Body.String())
|
|
}
|
|
cookies := response.Result().Cookies()
|
|
if len(cookies) != cookie.Cookie.MaxChunks {
|
|
t.Fatalf("cookies = %d, want %d", len(cookies), cookie.Cookie.MaxChunks)
|
|
}
|
|
for index, got := range cookies {
|
|
if got.Name != cookie.Cookie.ChunkNames[index] || got.Value != cookie.Cookie.Clear.Value || got.MaxAge != -1 || !got.HttpOnly || got.SameSite != http.SameSiteLaxMode || got.Path != "/" || !got.Secure {
|
|
t.Errorf("cookie %d = %#v", index, got)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAuthLogoutUsesRequestOriginAndExplicitCookieSecurity(t *testing.T) {
|
|
handler := httpapi.NewAuthLogoutHandler(httpapi.LogoutConfig{CookieSecure: "false"})
|
|
request := httptest.NewRequest(http.MethodPost, "https://request.example.test/api/auth/logout", nil)
|
|
response := httptest.NewRecorder()
|
|
handler.ServeHTTP(response, request)
|
|
if response.Header().Get("Location") != "https://request.example.test/auth/login?loggedOut=1" {
|
|
t.Fatalf("Location = %q", response.Header().Get("Location"))
|
|
}
|
|
for _, cookie := range response.Result().Cookies() {
|
|
if cookie.Secure {
|
|
t.Fatalf("cookie unexpectedly secure: %#v", cookie)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAuthLogoutMethodAndPathSemantics(t *testing.T) {
|
|
handler := httpapi.NewAuthLogoutHandler(httpapi.LogoutConfig{})
|
|
tests := []struct {
|
|
method, path string
|
|
status int
|
|
}{
|
|
{http.MethodOptions, "/api/auth/logout", http.StatusNoContent},
|
|
{http.MethodHead, "/api/auth/logout", http.StatusTemporaryRedirect},
|
|
{http.MethodPut, "/api/auth/logout", http.StatusMethodNotAllowed},
|
|
{http.MethodGet, "/api/auth/logout/", http.StatusNotFound},
|
|
}
|
|
for _, test := range tests {
|
|
response := httptest.NewRecorder()
|
|
handler.ServeHTTP(response, httptest.NewRequest(test.method, "http://app.test"+test.path, nil))
|
|
if response.Code != test.status || response.Body.Len() != 0 {
|
|
t.Errorf("%s %s = %d %q", test.method, test.path, response.Code, response.Body.String())
|
|
}
|
|
}
|
|
}
|