test(host): check the API path for base URLs with a prefix and a trailing slash
- commit
- 0642256cb931bab276c1752e388bd57b8ebf27b5
- author
- brice · · 2026-10-12 22:23 UTC
- parent
- 2785ef1
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
2 files · +22 -1
M README.md +1 -1
| @@ -91,7 +91,7 @@ the host process; the sandbox receives the workflow and its contexts only. | |||
| 91 | 91 | ||
| 92 | 92 | | Variable | Meaning | | |
| 93 | 93 | | --- | --- | | |
| 94 | - | | `ERMITE_RUNNER_URL` | base URL of ermite | | |
| 94 | + | | `ERMITE_RUNNER_URL` | base URL of ermite, as in a browser (the runner adds `/-/api` itself) | | |
| 95 | 95 | | `ERMITE_RUNNER_NAME` | runner name (default: the host name) | | |
| 96 | 96 | | `ERMITE_RUNNER_LABELS` | extra labels, comma separated (`ubuntu-latest,ubuntu-24.04`) | | |
| 97 | 97 | | `ERMITE_RUNNER_REGISTER_TOKEN` | token for `register` (see above) | | |
| @@ -91,7 +91,7 @@ the host process; the sandbox receives the workflow and its contexts only. | |||||
| 91 | 91 | ||||
| 92 | | Variable | Meaning | | 92 | | Variable | Meaning | | ||
| 93 | | --- | --- | | 93 | | --- | --- | | ||
| 94 | - | | `ERMITE_RUNNER_URL` | base URL of ermite | | 94 | + | | `ERMITE_RUNNER_URL` | base URL of ermite, as in a browser (the runner adds `/-/api` itself) | |
| 95 | | `ERMITE_RUNNER_NAME` | runner name (default: the host name) | | 95 | | `ERMITE_RUNNER_NAME` | runner name (default: the host name) | | ||
| 96 | | `ERMITE_RUNNER_LABELS` | extra labels, comma separated (`ubuntu-latest,ubuntu-24.04`) | | 96 | | `ERMITE_RUNNER_LABELS` | extra labels, comma separated (`ubuntu-latest,ubuntu-24.04`) | | ||
| 97 | | `ERMITE_RUNNER_REGISTER_TOKEN` | token for `register` (see above) | | 97 | | `ERMITE_RUNNER_REGISTER_TOKEN` | token for `register` (see above) | | ||
M internal/host/rpc_test.go +21 -0
| @@ -93,6 +93,27 @@ func TestClientRefusesToSendTheTokenInClear(t *testing.T) { | |||
| 93 | 93 | } | |
| 94 | 94 | } | |
| 95 | 95 | ||
| 96 | + | // The API lives under /-/api of the base URL, which may carry a path prefix | |
| 97 | + | // and a trailing slash. | |
| 98 | + | func TestClientCallsTheAPIPath(t *testing.T) { | |
| 99 | + | for base, want := range map[string]string{ | |
| 100 | + | "https://h": "/-/api/ermite.RunnerService/FetchJob", | |
| 101 | + | "https://h/": "/-/api/ermite.RunnerService/FetchJob", | |
| 102 | + | "https://h/ermite": "/ermite/-/api/ermite.RunnerService/FetchJob", | |
| 103 | + | "https://h/ermite/": "/ermite/-/api/ermite.RunnerService/FetchJob", | |
| 104 | + | } { | |
| 105 | + | var got string | |
| 106 | + | rt := roundTripFunc(func(r *http.Request) (*http.Response, error) { | |
| 107 | + | got = r.URL.Path | |
| 108 | + | return nil, context.Canceled | |
| 109 | + | }) | |
| 110 | + | _, _ = NewClient(base, "ermiterun_secret", rt).FetchJob(context.Background(), connect.NewRequest(&ermite.FetchJobRequest{})) | |
| 111 | + | if got != want { | |
| 112 | + | t.Errorf("%s: called %q, want %q", base, got, want) | |
| 113 | + | } | |
| 114 | + | } | |
| 115 | + | } | |
| 116 | + | ||
| 96 | 117 | type roundTripFunc func(*http.Request) (*http.Response, error) | |
| 97 | 118 | ||
| 98 | 119 | func (f roundTripFunc) RoundTrip(r *http.Request) (*http.Response, error) { return f(r) } | |
| @@ -93,6 +93,27 @@ func TestClientRefusesToSendTheTokenInClear(t *testing.T) { | |||||
| 93 | } | 93 | } | ||
| 94 | } | 94 | } | ||
| 95 | 95 | ||||
| 96 | + | // The API lives under /-/api of the base URL, which may carry a path prefix | |||
| 97 | + | // and a trailing slash. | |||
| 98 | + | func TestClientCallsTheAPIPath(t *testing.T) { | |||
| 99 | + | for base, want := range map[string]string{ | |||
| 100 | + | "https://h": "/-/api/ermite.RunnerService/FetchJob", | |||
| 101 | + | "https://h/": "/-/api/ermite.RunnerService/FetchJob", | |||
| 102 | + | "https://h/ermite": "/ermite/-/api/ermite.RunnerService/FetchJob", | |||
| 103 | + | "https://h/ermite/": "/ermite/-/api/ermite.RunnerService/FetchJob", | |||
| 104 | + | } { | |||
| 105 | + | var got string | |||
| 106 | + | rt := roundTripFunc(func(r *http.Request) (*http.Response, error) { | |||
| 107 | + | got = r.URL.Path | |||
| 108 | + | return nil, context.Canceled | |||
| 109 | + | }) | |||
| 110 | + | _, _ = NewClient(base, "ermiterun_secret", rt).FetchJob(context.Background(), connect.NewRequest(&ermite.FetchJobRequest{})) | |||
| 111 | + | if got != want { | |||
| 112 | + | t.Errorf("%s: called %q, want %q", base, got, want) | |||
| 113 | + | } | |||
| 114 | + | } | |||
| 115 | + | } | |||
| 116 | + | ||||
| 96 | type roundTripFunc func(*http.Request) (*http.Response, error) | 117 | type roundTripFunc func(*http.Request) (*http.Response, error) | ||
| 97 | 118 | ||||
| 98 | func (f roundTripFunc) RoundTrip(r *http.Request) (*http.Response, error) { return f(r) } | 119 | func (f roundTripFunc) RoundTrip(r *http.Request) (*http.Response, error) { return f(r) } | ||