Made mock-fts take its base URL from --addr when --base-url isn't given
This commit is contained in:
1 parent
ac44b45f06
commit
88f879d844
3 files changed
+75
-4
No files matched your search
+40
-3
@@ -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(),
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 |
|
||||
|
||||
Reference in new issue
Block a user