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"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"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
|
build from internal/mock/findatender/data/catalog.json. The mock stops with an
|
||||||
error if it is invalid.
|
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
|
Releases are generated from that catalog and appended to
|
||||||
<data-dir>/releases.jsonl, so they survive restarts. A background worker
|
<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
|
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 --data-dir ./mock-data --reset
|
||||||
fts-mock --min-gap 5s --max-gap 10s --rate-limit 1000`,
|
fts-mock --min-gap 5s --max-gap 10s --rate-limit 1000`,
|
||||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
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 {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return run(cmd.Context(), opts)
|
return run(cmd.Context(), opts)
|
||||||
@@ -133,8 +149,8 @@ func newRootCmd() *cobra.Command {
|
|||||||
flags.StringVar(
|
flags.StringVar(
|
||||||
&opts.baseURL,
|
&opts.baseURL,
|
||||||
"base-url",
|
"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(
|
flags.StringVar(
|
||||||
&opts.dataDir,
|
&opts.dataDir,
|
||||||
@@ -220,6 +236,26 @@ func (o *options) validate() error {
|
|||||||
return nil
|
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.
|
// run starts the mock and blocks until ctx is cancelled or the server fails.
|
||||||
func run(ctx context.Context, opts *options) (err error) {
|
func run(ctx context.Context, opts *options) (err error) {
|
||||||
location, err := time.LoadLocation(opts.timeZone) // already validated
|
location, err := time.LoadLocation(opts.timeZone) // already validated
|
||||||
@@ -326,6 +362,7 @@ func run(ctx context.Context, opts *options) (err error) {
|
|||||||
slog.Info(
|
slog.Info(
|
||||||
"mock listening",
|
"mock listening",
|
||||||
"addr", opts.addr,
|
"addr", opts.addr,
|
||||||
|
"base_url", opts.baseURL,
|
||||||
"path", mock.BasePath,
|
"path", mock.BasePath,
|
||||||
"time_zone", location.String(),
|
"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 |
|
| Flag | Default | Meaning |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `--addr` | `:8080` | Listen address |
|
| `--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 |
|
| `--data-dir` | `./mock-data` | Where `releases.jsonl` is stored |
|
||||||
| `--reset` | | Delete stored releases and regenerate the backfill |
|
| `--reset` | | Delete stored releases and regenerate the backfill |
|
||||||
| `--backfill` | `72h` | History to generate on an empty data directory |
|
| `--backfill` | `72h` | History to generate on an empty data directory |
|
||||||
|
|||||||
Reference in new issue
Block a user