Files
lrc-local/public_server_test.go
T

94 lines
3.1 KiB
Go

package main
import (
"net/http"
"net/http/httptest"
"strings"
"testing"
"testing/fstest"
)
func newTestPublicApp(t *testing.T) (*publicApp, http.Handler) {
t.Helper()
web := fstest.MapFS{
"app.html": &fstest.MapFile{Data: []byte("public app")},
"app.js": &fstest.MapFile{Data: []byte("js")},
"styles.css": &fstest.MapFile{Data: []byte("css")},
}
app, err := newPublicApp("https://lrc.flechazo.xin", web, fakeQQ{})
if err != nil {
t.Fatal(err)
}
return app, app.routes()
}
func publicRequest(method, path, body string) *http.Request {
request := httptest.NewRequest(method, "https://lrc.flechazo.xin"+path, strings.NewReader(body))
request.Header.Set("Origin", "https://lrc.flechazo.xin")
request.Header.Set("Content-Type", "application/json")
request.Header.Set("X-Real-IP", "203.0.113.7")
return request
}
func TestPublicPageNeedsNoSession(t *testing.T) {
_, handler := newTestPublicApp(t)
w := httptest.NewRecorder()
handler.ServeHTTP(w, publicRequest(http.MethodGet, "/", ""))
if w.Code != http.StatusOK || w.Body.String() != "public app" {
t.Fatalf("status=%d body=%q", w.Code, w.Body.String())
}
if w.Header().Get("Cache-Control") != "no-store" || w.Header().Get("X-Frame-Options") != "DENY" {
t.Fatal("public application safety headers are missing")
}
}
func TestPublicAPIRejectsWrongOrigin(t *testing.T) {
_, handler := newTestPublicApp(t)
request := publicRequest(http.MethodPost, "/api/search", `{"keyword":"test","limit":2}`)
request.Header.Set("Origin", "https://attacker.example")
w := httptest.NewRecorder()
handler.ServeHTTP(w, request)
if w.Code != http.StatusForbidden {
t.Fatalf("expected 403, got %d", w.Code)
}
}
func TestPublicSearchWorksWithoutCookie(t *testing.T) {
_, handler := newTestPublicApp(t)
w := httptest.NewRecorder()
handler.ServeHTTP(w, publicRequest(http.MethodPost, "/api/search", `{"keyword":"测试","limit":2}`))
if w.Code != http.StatusOK || !strings.Contains(w.Body.String(), "测试") {
t.Fatalf("status=%d body=%s", w.Code, w.Body.String())
}
}
func TestPublicPerClientRateLimit(t *testing.T) {
_, handler := newTestPublicApp(t)
for attempt := 1; attempt <= publicClientLimit+1; attempt++ {
w := httptest.NewRecorder()
handler.ServeHTTP(w, publicRequest(http.MethodPost, "/api/search", `{"keyword":"test","limit":1}`))
if attempt <= publicClientLimit && w.Code != http.StatusOK {
t.Fatalf("attempt %d unexpectedly returned %d", attempt, w.Code)
}
if attempt == publicClientLimit+1 && w.Code != http.StatusTooManyRequests {
t.Fatalf("expected final attempt to return 429, got %d", w.Code)
}
}
}
func TestPublicDoesNotServeLocalBinaries(t *testing.T) {
_, handler := newTestPublicApp(t)
w := httptest.NewRecorder()
handler.ServeHTTP(w, publicRequest(http.MethodGet, "/download/lrc-local-windows-amd64.exe", ""))
if w.Code != http.StatusNotFound {
t.Fatalf("expected removed local download route to return 404, got %d", w.Code)
}
}
func TestPublicOriginConfigurationMustUseHTTPS(t *testing.T) {
_, err := newPublicApp("http://lrc.flechazo.xin", fstest.MapFS{}, fakeQQ{})
if err == nil {
t.Fatal("expected insecure public origin to be rejected")
}
}