From d218bee6b8ab4fd10bec88269270a2412bdbbb46 Mon Sep 17 00:00:00 2001 From: Martin Fischer Date: Sun, 6 Apr 2025 14:56:19 +0200 Subject: refactor: make domain configurable --- go.mod | 3 ++ go.sum | 2 + lexsurf.go | 19 +++++--- lexsurf_test.go | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 161 insertions(+), 7 deletions(-) create mode 100644 go.sum create mode 100644 lexsurf_test.go diff --git a/go.mod b/go.mod index fe9bf18..e2f8382 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,6 @@ module push-f.com/lex-surf go 1.23.5 + +// test dependencies +require github.com/peter-evans/patience v0.3.0 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..9d6ce76 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/peter-evans/patience v0.3.0 h1:rX0JdJeepqdQl1Sk9c9uvorjYYzL2TfgLX1adqYm9cA= +github.com/peter-evans/patience v0.3.0/go.mod h1:Kmxu5sY1NmBLFSStvXjX1wS9mIv7wMcP/ubucyMOAu0= diff --git a/lexsurf.go b/lexsurf.go index 9ac8feb..5c1e15a 100644 --- a/lexsurf.go +++ b/lexsurf.go @@ -6,12 +6,18 @@ import ( "log" "net/http" "net/url" + "os" "strings" "text/template" ) func main() { - var handler = handler{lawsByCC: map[string]map[string]law{}} + domain := os.Getenv("DOMAIN") + if domain == "" { + log.Fatal("DOMAIN environment variable must be set") + } + + var handler = handler{domain: domain, lawsByCC: map[string]map[string]law{}} text, _ := ioutil.ReadFile("countries.json") err := json.Unmarshal(text, &handler.countries) if err != nil { @@ -50,12 +56,13 @@ var tpl, _ = template.New("").Funcs(template.FuncMap{ }).ParseGlob("views/*") type handler struct { + domain string countries map[string]country lawsByCC map[string]map[string]law } func (h *handler) handle(w http.ResponseWriter, r *http.Request) { - if r.Host == "lex.surf" || r.Host == "lex.localhost" { + if r.Host == h.domain { if r.URL.Path != "/" { w.WriteHeader(http.StatusNotFound) w.Write([]byte("page not found")) @@ -71,13 +78,11 @@ func (h *handler) handle(w http.ResponseWriter, r *http.Request) { return } - parts := strings.SplitN(r.Host, ".", 2) - if len(parts) != 2 { + cc, isSubdomain := strings.CutSuffix(r.Host, "."+h.domain) + if !isSubdomain { w.Write([]byte("unknown host")) return } - cc := parts[0] - host := parts[1] key := strings.TrimLeft(r.URL.Path, "/") if len(key) > 0 { val, ok := h.lawsByCC[cc][key] @@ -106,7 +111,7 @@ func (h *handler) handle(w http.ResponseWriter, r *http.Request) { _, hasJSONLaws := h.lawsByCC[cc] err := tpl.ExecuteTemplate(w, "search.html", map[string]any{ "TLD": cc, - "Domain": host, + "Domain": h.domain, "Country": h.countries[cc], "HasJSONLaws": hasJSONLaws, }) diff --git a/lexsurf_test.go b/lexsurf_test.go new file mode 100644 index 0000000..e647a2f --- /dev/null +++ b/lexsurf_test.go @@ -0,0 +1,144 @@ +package main + +import ( + "net/http/httptest" + "strings" + "testing" + + "github.com/peter-evans/patience" +) + +func newHandler() handler { + return handler{ + domain: "lex.example", + countries: map[string]country{ + "zu": country{ + Name: "Zubrowka", + SearchURL: "https://lex.gov.zu/?search=%s", + }, + }, + lawsByCC: map[string]map[string]law{}, + } +} + +func TestStartPage(t *testing.T) { + h := newHandler() + + req := httptest.NewRequest("GET", "/", nil) + req.Host = "lex.example" + w := httptest.NewRecorder() + h.handle(w, req) + + resp := w.Result() + if resp.StatusCode != 200 { + t.Errorf("expected status 200 OK, got %d", resp.StatusCode) + } + expected := ` + + + Lex.surf: Portal to National Law + + + + + +

The portal to national law.

+
+ ZU +
+ + +` + assertEqual(t, w.Body.String(), expected) +} + +func TestSearch(t *testing.T) { + h := newHandler() + + req := httptest.NewRequest("GET", "/", nil) + req.Host = "zu.lex.example" + w := httptest.NewRecorder() + h.handle(w, req) + + resp := w.Result() + if resp.StatusCode != 200 { + t.Errorf("expected status 200 OK, got %d", resp.StatusCode) + } + expected := ` + + + National Law of Zubrowka + + + + + +

National Law of Zubrowka

+ + +
+ + + + + + +
+ + + + +` + assertEqual(t, w.Body.String(), expected) +} + +func TestSearchRedirect(t *testing.T) { + h := newHandler() + + req := httptest.NewRequest("GET", "/?q=tourism", nil) + req.Host = "zu.lex.example" + w := httptest.NewRecorder() + h.handle(w, req) + + resp := w.Result() + if resp.StatusCode != 302 { + t.Errorf("expected status 302, got %d", resp.StatusCode) + } + + if resp.Header.Get("Location") != "https://lex.gov.zu/?search=tourism" { + t.Errorf("wrong location, got %s", resp.Header.Get("Location")) + } +} + +func TestLawRedirect(t *testing.T) { + h := newHandler() + + h.lawsByCC["zu"] = map[string]law{} + h.lawsByCC["zu"]["zepl"] = law{ + URL: "https://lex.gov.zu/zeppelin-code", + } + + req := httptest.NewRequest("GET", "/zepl", nil) + req.Host = "zu.lex.example" + w := httptest.NewRecorder() + h.handle(w, req) + + resp := w.Result() + if resp.StatusCode != 302 { + t.Errorf("expected status 302, got %d", resp.StatusCode) + } + + if resp.Header.Get("Location") != "https://lex.gov.zu/zeppelin-code" { + t.Errorf("wrong location, got %s", resp.Header.Get("Location")) + } +} + +func assertEqual(t *testing.T, received string, expected string) { + if received != expected { + a := strings.Split(received, "\n") + b := strings.Split(expected, "\n") + diffs := patience.Diff(a, b) + unidiff := patience.UnifiedDiffText(diffs) + t.Error(unidiff) + } +} -- cgit v1.2.3