summaryrefslogtreecommitdiff
path: root/lex-serve/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'lex-serve/main.go')
-rw-r--r--lex-serve/main.go74
1 files changed, 50 insertions, 24 deletions
diff --git a/lex-serve/main.go b/lex-serve/main.go
index ac67ad4..98cc403 100644
--- a/lex-serve/main.go
+++ b/lex-serve/main.go
@@ -10,7 +10,9 @@ import (
"net/http"
"net/url"
"os"
+ "path"
"strings"
+ "sync"
"github.com/BurntSushi/toml"
)
@@ -33,7 +35,13 @@ func main() {
os.Exit(1)
}
- var handler = handler{logger: log, domain: domain, lawsByCC: map[string]map[string]law{}}
+ lawsDir := os.Getenv("LAWS_DIR")
+ if lawsDir == "" {
+ log.Error("LAWS_DIR must be set")
+ os.Exit(1)
+ }
+
+ var handler = handler{logger: log, domain: domain, lawsDir: lawsDir, lawsByCC: map[string]map[string]law{}}
meta, err := toml.NewDecoder(bytes.NewReader(countriesTOML)).Decode(&handler.countries)
if err != nil {
log.Error("failed to parse countries.toml", Error(err))
@@ -44,30 +52,15 @@ func main() {
os.Exit(1)
}
- lawFiles, err := os.ReadDir("laws")
- if err != nil {
- log.Error("failed to read laws/ directory", Error(err))
- os.Exit(1)
- }
- for _, file := range lawFiles {
- text, err := os.ReadFile("laws/" + file.Name())
- if err != nil {
- log.Error("failed to read file", Error(err), "path", "laws/"+file.Name())
- os.Exit(1)
- }
- var laws []law
- err = json.Unmarshal([]byte(text), &laws)
- if err != nil {
- log.Error("failed to parse file", Error(err), "path", file.Name())
- os.Exit(1)
- }
- cc := strings.SplitN(file.Name(), ".", 2)[0]
- handler.lawsByCC[cc] = map[string]law{}
- for _, law := range laws {
- if law.Redir != "" {
- handler.lawsByCC[cc][law.Redir] = law
- }
+ lawFiles, err := os.ReadDir(lawsDir)
+ if err == nil {
+ for _, file := range lawFiles {
+ cc := strings.SplitN(file.Name(), ".", 2)[0]
+ handler.loadLaws(cc)
}
+ } else if !os.IsNotExist(err) {
+ log.Error("failed to read laws directory", Error(err), "path", lawsDir)
+ os.Exit(1)
}
http.HandleFunc("/", handler.handle)
listener, err := net.Listen("unix", socketPath)
@@ -94,10 +87,16 @@ type handler struct {
logger *slog.Logger
domain string
countries map[string]country
+ lawsDir string
lawsByCC map[string]map[string]law
+ lawsMu sync.RWMutex
}
func (h *handler) handle(w http.ResponseWriter, r *http.Request) {
+ if r.Host == "internal.invalid" {
+ h.loadLaws(r.URL.Query().Get("country"))
+ return
+ }
if r.Host == h.domain {
if r.URL.Path != "/" {
w.WriteHeader(http.StatusNotFound)
@@ -126,6 +125,8 @@ func (h *handler) handle(w http.ResponseWriter, r *http.Request) {
}
key := strings.TrimLeft(r.URL.Path, "/")
if len(key) > 0 {
+ h.lawsMu.RLock()
+ defer h.lawsMu.RUnlock()
val, ok := h.lawsByCC[cc][key]
if !ok {
w.WriteHeader(http.StatusNotFound)
@@ -149,6 +150,8 @@ func (h *handler) handle(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusBadRequest)
}
}
+ h.lawsMu.RLock()
+ defer h.lawsMu.RUnlock()
_, hasJSONLaws := h.lawsByCC[cc]
var html bytes.Buffer
err := tpl.ExecuteTemplate(&html, "search.html.tmpl", map[string]any{
@@ -166,6 +169,29 @@ func (h *handler) handle(w http.ResponseWriter, r *http.Request) {
}
}
+func (h *handler) loadLaws(country string) {
+ filePath := path.Join(h.lawsDir, country+".json")
+ text, err := os.ReadFile(filePath)
+ if err != nil {
+ h.logger.Error("failed to read file", Error(err), "path", filePath)
+ return
+ }
+ var laws []law
+ err = json.Unmarshal([]byte(text), &laws)
+ if err != nil {
+ h.logger.Error("failed to parse file", Error(err), "path", filePath)
+ return
+ }
+ h.lawsMu.Lock()
+ defer h.lawsMu.Unlock()
+ h.lawsByCC[country] = map[string]law{}
+ for _, law := range laws {
+ if law.Redir != "" {
+ h.lawsByCC[country][law.Redir] = law
+ }
+ }
+}
+
type law struct {
URL string
Title string