diff --git a/cmd/scrape-server/main.go b/cmd/scrape-server/main.go index 759781b..ab2020c 100644 --- a/cmd/scrape-server/main.go +++ b/cmd/scrape-server/main.go @@ -43,6 +43,7 @@ var ( dbFlags *cmd.DatabaseFlags headlessEnabled *envflags.Value[bool] profile *envflags.Value[bool] + publicHome *envflags.Value[bool] logWriter io.Writer ) @@ -77,7 +78,7 @@ func main() { slog.Info("scrape-server authorization is disabled, running in open access mode") } - mux, err := server.InitMux(ss, dbh) + mux, err := server.InitMux(ss, dbh, publicHome.Get()) if err != nil { slog.Error("scrape-server error initializing the server's mux", "error", err) os.Exit(1) @@ -137,6 +138,9 @@ func init() { profile = envflags.NewBool("PROFILE", false) profile.AddTo(&flags, "profile", "Enable profiling at /debug/pprof") + publicHome = envflags.NewBool("PUBLIC_HOME", false) + publicHome.AddTo(&flags, "public-home", "Enable the homepage without requiring a token (when auth is enabled)") + logLevel := envflags.NewLogLevel("LOG_LEVEL", slog.LevelInfo) logLevel.AddTo(&flags, "log-level", "Set the log level [debug|error|info|warn]") flags.Parse(os.Args[1:]) diff --git a/internal/server/home.go b/internal/server/home.go index 1edd860..b668d3f 100644 --- a/internal/server/home.go +++ b/internal/server/home.go @@ -14,11 +14,20 @@ import ( //go:embed templates/index.html var home embed.FS -func mustHomeTemplate(ss *scrapeServer) *template.Template { +// mustHomeTemplate creates a template for the home page. +// To enable usage of the home page without a token when auth is enabled, +// for API endpoint, set openHome to true. +func mustHomeTemplate(ss *scrapeServer, openHome bool) *template.Template { tmpl := template.New("home") var authTokenF = func() string { return "" } - var authEnabledF = func() bool { return ss.AuthEnabled() } - if authEnabledF() { + var showTokenWidget = func() bool { + // when openHome is true don't show the token entry widget + if openHome { + return false + } + return ss.AuthEnabled() + } + if ss.AuthEnabled() && openHome { authTokenF = func() string { c, err := auth.NewClaims( auth.WithSubject("home"), @@ -37,8 +46,8 @@ func mustHomeTemplate(ss *scrapeServer) *template.Template { } } funcMap := template.FuncMap{ - "AuthToken": authTokenF, - "AuthEnabled": authEnabledF, + "AuthToken": authTokenF, + "ShowTokenWidget": showTokenWidget, } tmpl = tmpl.Funcs(funcMap) homeSource, _ := home.ReadFile("templates/index.html") @@ -46,8 +55,8 @@ func mustHomeTemplate(ss *scrapeServer) *template.Template { return tmpl } -func homeHandler(ss *scrapeServer) http.HandlerFunc { - tmpl := mustHomeTemplate(ss) +func homeHandler(ss *scrapeServer, openHome bool) http.HandlerFunc { + tmpl := mustHomeTemplate(ss, openHome) return func(w http.ResponseWriter, r *http.Request) { var buf bytes.Buffer if err := tmpl.Execute(&buf, nil); err != nil { diff --git a/internal/server/home_test.go b/internal/server/home_test.go index 27ed95c..2f03c5c 100644 --- a/internal/server/home_test.go +++ b/internal/server/home_test.go @@ -12,21 +12,31 @@ func TestMustTemplate(t *testing.T) { tests := []struct { name string key auth.HMACBase64Key + openHome bool expectToken bool }{ { - name: "with key", + name: "auth enabled", key: auth.MustNewHS256SigningKey(), + openHome: false, + expectToken: false, + }, + { + name: "auth enabled with open home", + key: auth.MustNewHS256SigningKey(), + openHome: true, expectToken: true, }, { - name: "no key", + name: "auth disabled", key: nil, + openHome: false, expectToken: false, }, { name: "empty key", key: auth.HMACBase64Key([]byte{}), + openHome: false, expectToken: false, }, } @@ -36,7 +46,7 @@ func TestMustTemplate(t *testing.T) { WithURLFetcher(&mockUrlFetcher{}), WithAuthorizationIf(test.key), ) - tmpl := mustHomeTemplate(ss) + tmpl := mustHomeTemplate(ss, test.openHome) tmpl, err := tmpl.Parse("{{AuthToken}}") if err != nil { t.Fatalf("[%s] Error parsing template: %s", test.name, err) diff --git a/internal/server/routes.go b/internal/server/routes.go index 31173a4..33e7540 100644 --- a/internal/server/routes.go +++ b/internal/server/routes.go @@ -8,19 +8,19 @@ import ( "github.com/efixler/scrape/internal/server/healthchecks" ) -func InitMux(scrapeServer *scrapeServer, db *database.DBHandle) (*http.ServeMux, error) { +func InitMux(ss *scrapeServer, db *database.DBHandle, openHome bool) (*http.ServeMux, error) { mux := http.NewServeMux() - mux.HandleFunc("GET /{$}", homeHandler(scrapeServer)) + mux.HandleFunc("GET /{$}", homeHandler(ss, openHome)) mux.Handle("/assets/", assetsHandler()) - h := scrapeServer.singleHandler() + h := ss.singleHandler() mux.HandleFunc("GET /extract", h) mux.HandleFunc("POST /extract", h) - h = scrapeServer.singleHeadlessHandler() + h = ss.singleHeadlessHandler() mux.HandleFunc("GET /extract/headless", h) mux.HandleFunc("POST /extract/headless", h) - mux.HandleFunc("POST /batch", scrapeServer.batchHandler()) - mux.HandleFunc("DELETE /extract", scrapeServer.deleteHandler()) - h = scrapeServer.feedHandler() + mux.HandleFunc("POST /batch", ss.batchHandler()) + mux.HandleFunc("DELETE /extract", ss.deleteHandler()) + h = ss.feedHandler() mux.HandleFunc("GET /feed", h) mux.HandleFunc("POST /feed", h) mux.Handle("GET /.well-known/", healthchecks.Handler("/.well-known", db)) diff --git a/internal/server/routes_test.go b/internal/server/routes_test.go index 0f090a4..6018563 100644 --- a/internal/server/routes_test.go +++ b/internal/server/routes_test.go @@ -15,7 +15,7 @@ func TestWellknown(t *testing.T) { //ctx, cancel := context.WithCancel(context.Background()) //defer cancel() - mux, err := InitMux(&scrapeServer{}, nil) + mux, err := InitMux(&scrapeServer{}, nil, false) if err != nil { t.Fatal(err) } @@ -61,7 +61,7 @@ func TestExtractErrors(t *testing.T) { WithURLFetcher(trafilatura.MustNew(nil)), ) - mux, err := InitMux(ss, nil) + mux, err := InitMux(ss, nil, false) if err != nil { t.Fatal(err) } @@ -105,12 +105,14 @@ func TestHomeHandlerAuth(t *testing.T) { WithURLFetcher(&mockUrlFetcher{}), WithAuthorizationIf(test.key), ) - req := httptest.NewRequest("GET", "http://foo.bar/", nil) - w := httptest.NewRecorder() - homeHandler(ss)(w, req) - resp := w.Result() - if resp.StatusCode != test.expectedResult { - t.Errorf("[%s] Expected %d, got %d", test.name, test.expectedResult, resp.StatusCode) + for _, openHome := range []bool{true, false} { + req := httptest.NewRequest("GET", "http://foo.bar/", nil) + w := httptest.NewRecorder() + homeHandler(ss, openHome)(w, req) + resp := w.Result() + if resp.StatusCode != test.expectedResult { + t.Errorf("[%s] Expected %d, got %d", test.name, test.expectedResult, resp.StatusCode) + } } } } diff --git a/internal/server/server_test.go b/internal/server/server_test.go index 902dfee..6809fad 100644 --- a/internal/server/server_test.go +++ b/internal/server/server_test.go @@ -106,7 +106,7 @@ func TestBatchReponseIsValid(t *testing.T) { WithURLFetcher(fetcher), ) - mux, err := InitMux(ss, nil) + mux, err := InitMux(ss, nil, false) if err != nil { t.Fatal(err) } diff --git a/internal/server/templates/index.html b/internal/server/templates/index.html index dc99d7d..5db82aa 100644 --- a/internal/server/templates/index.html +++ b/internal/server/templates/index.html @@ -149,6 +149,7 @@ } +
@@ -167,7 +168,7 @@
- +
@@ -257,4 +258,5 @@ } + \ No newline at end of file