Made mock-fts take its base URL from --addr when --base-url isn't given

This commit is contained in:
bwilliams committed 2026-10-16 09:19:42 +01:00
1 parent ac44b45f06
commit 88f879d844
3 files changed
+75 -4

No files matched your search

+40 -3
View File
@@ -24,6 +24,7 @@ import (
"errors"
"fmt"
"log/slog"
"net"
"net/http"
"os"
"os/signal"
@@ -75,6 +76,12 @@ and classifications that releases are generated from is embedded in the
build from internal/mock/findatender/data/catalog.json. The mock stops with an
error if it is invalid.
Paging: each package's uri and links.next start with --base-url, which
clients follow as given. Without it, the base URL is taken from --addr, with
an unspecified host (":8080", "0.0.0.0", "::") as localhost. Set it when
clients reach the mock by another address, such as through a proxy or a
mapped container port.
Releases are generated from that catalog and appended to
<data-dir>/releases.jsonl, so they survive restarts. A background worker
publishes a new release every --min-gap to --max-gap. On startup the mock
@@ -119,7 +126,16 @@ func newRootCmd() *cobra.Command {
fts-mock --data-dir ./mock-data --reset
fts-mock --min-gap 5s --max-gap 10s --rate-limit 1000`,
PreRunE: func(cmd *cobra.Command, args []string) error {
return opts.validate()
err := opts.validate()
if err != nil {
return err
}
if opts.baseURL == "" {
opts.baseURL, err = baseURLFromAddr(opts.addr)
}
return err
},
RunE: func(cmd *cobra.Command, args []string) error {
return run(cmd.Context(), opts)
@@ -133,8 +149,8 @@ func newRootCmd() *cobra.Command {
flags.StringVar(
&opts.baseURL,
"base-url",
"http://localhost:8080",
"public base URL used in uri and links.next",
"",
"public base URL used in uri and links.next (default from --addr)",
)
flags.StringVar(
&opts.dataDir,
@@ -220,6 +236,26 @@ func (o *options) validate() error {
return nil
}
// baseURLFromAddr returns the base URL clients reach a mock listening on
// addr by: http://host:port, with localhost for an unspecified host. Port 0
// is refused, as the port isn't known until the mock is listening.
func baseURLFromAddr(addr string) (string, error) {
host, port, err := net.SplitHostPort(addr)
if err != nil {
return "", fmt.Errorf("--addr: %w", err)
}
if port == "0" {
return "", errors.New("--addr with port 0 needs --base-url")
}
switch host {
case "", "0.0.0.0", "::":
host = "localhost"
}
return "http://" + net.JoinHostPort(host, port), nil
}
// run starts the mock and blocks until ctx is cancelled or the server fails.
func run(ctx context.Context, opts *options) (err error) {
location, err := time.LoadLocation(opts.timeZone) // already validated
@@ -326,6 +362,7 @@ func run(ctx context.Context, opts *options) (err error) {
slog.Info(
"mock listening",
"addr", opts.addr,
"base_url", opts.baseURL,
"path", mock.BasePath,
"time_zone", location.String(),
)
+34
View File
@@ -0,0 +1,34 @@
package main
import "testing"
// Without --base-url, the base URL comes from --addr, with localhost for an
// unspecified host.
func TestBaseURLFromAddr(t *testing.T) {
tests := []struct {
addr string
want string
}{
{":8080", "http://localhost:8080"},
{"0.0.0.0:8080", "http://localhost:8080"},
{"[::]:8080", "http://localhost:8080"},
{"127.0.0.1:18080", "http://127.0.0.1:18080"},
{"[::1]:8080", "http://[::1]:8080"},
{"mock.example.com:80", "http://mock.example.com:80"},
}
for _, tt := range tests {
got, err := baseURLFromAddr(tt.addr)
if err != nil || got != tt.want {
t.Errorf("baseURLFromAddr(%q) = %q, %v; want %q", tt.addr, got, err, tt.want)
}
}
}
// An address without a port, or with port 0, is refused.
func TestBaseURLFromAddrRefused(t *testing.T) {
for _, addr := range []string{"localhost", ":0"} {
if got, err := baseURLFromAddr(addr); err == nil {
t.Errorf("baseURLFromAddr(%q) = %q; want an error", addr, got)
}
}
}
+1 -1
View File
@@ -40,7 +40,7 @@ Useful flags (`go run ./cmd/mock-fts --help` lists them all):
| Flag | Default | Meaning |
|---|---|---|
| `--addr` | `:8080` | Listen address |
| `--base-url` | `http://localhost:8080` | Public base URL used in `uri` and `links.next` |
| `--base-url` | from `--addr` | Public base URL used in `uri` and `links.next`. Without it, `http://<addr>`, with `localhost` for an unspecified host (`:8080`, `0.0.0.0`, `::`). Set it when clients use another address (a proxy, a mapped container port), or with port 0 |
| `--data-dir` | `./mock-data` | Where `releases.jsonl` is stored |
| `--reset` | | Delete stored releases and regenerate the backfill |
| `--backfill` | `72h` | History to generate on an empty data directory |