Skip to content

Commit

Permalink
Use the default http config for all server UI and rapi operations + I…
Browse files Browse the repository at this point in the history
…ndicate when the UI/echo server is using https (#868)

* go 1.21.5

* Borrow from 4d47b55 and update go.mod

* Indicate when the UI/echo server is using https

* Fix #865: sets the flag based options as the base/default for fetch, runs, rapi/ etc

* better for unit tests if pointers are initialized

* prep for 1.63.0 plus note in the readme about the change
  • Loading branch information
ldemailly committed Dec 9, 2023
1 parent 80eca80 commit 6b492e2
Show file tree
Hide file tree
Showing 7 changed files with 32 additions and 13 deletions.
16 changes: 9 additions & 7 deletions README.md
@@ -1,4 +1,4 @@
<!-- 1.62.1 -->
<!-- 1.63.0 -->
# Fortio

[![Awesome Go](https://fortio.org/mentioned-badge.svg)](https://github.com/avelino/awesome-go#networking)
Expand Down Expand Up @@ -60,13 +60,13 @@ You can install from source:
The [releases](https://github.com/fortio/fortio/releases) page has binaries for many OS/architecture combinations (see assets):

```shell
curl -L https://github.com/fortio/fortio/releases/download/v1.62.1/fortio-linux_amd64-1.62.1.tgz \
curl -L https://github.com/fortio/fortio/releases/download/v1.63.0/fortio-linux_amd64-1.63.0.tgz \
| sudo tar -C / -xvzpf -
# or the debian package
wget https://github.com/fortio/fortio/releases/download/v1.62.1/fortio_1.62.1_amd64.deb
dpkg -i fortio_1.62.1_amd64.deb
wget https://github.com/fortio/fortio/releases/download/v1.63.0/fortio_1.63.0_amd64.deb
dpkg -i fortio_1.63.0_amd64.deb
# or the rpm
rpm -i https://github.com/fortio/fortio/releases/download/v1.62.1/fortio-1.62.1-1.x86_64.rpm
rpm -i https://github.com/fortio/fortio/releases/download/v1.63.0/fortio-1.63.0-1.x86_64.rpm
# and more, see assets in release page
```

Expand All @@ -76,7 +76,7 @@ On a MacOS you can also install Fortio using [Homebrew](https://brew.sh/):
brew install fortio
```

On Windows, download https://github.com/fortio/fortio/releases/download/v1.62.1/fortio_win_1.62.1.zip and extract `fortio.exe` to any location, then using the Windows Command Prompt:
On Windows, download https://github.com/fortio/fortio/releases/download/v1.63.0/fortio_win_1.63.0.zip and extract `fortio.exe` to any location, then using the Windows Command Prompt:
```
fortio.exe server
```
Expand Down Expand Up @@ -123,12 +123,14 @@ Most important flags for http load generation:
| `-logger-force-color` | For interactive runs for color instead of JSON output|
| `-logger-no-color` | Force JSON output even when run from terminal|

Changing the http options like the TLS options `-cert`, `-key`, `-cacert` when launching an echo/UI/rapi server will make these options the default for runs initiated from that server (or fetches/proxies etc).

Full list of command line flags (`fortio help`):
<details>
<!-- use release/updateFlags.sh to update this section -->
<pre>
<!-- USAGE_START -->
Φορτίο 1.62.1 usage:
Φορτίο 1.63.0 usage:
fortio command [flags] target
where command is one of: load (load testing), server (starts ui, rest api,
http-echo, redirect, proxies, tcp-echo, udp-echo and grpc ping servers),
Expand Down
3 changes: 2 additions & 1 deletion bincommon/commonflags.go
Expand Up @@ -194,7 +194,7 @@ func ConnectionReuseRangeValidator(httpOpts *fhttp.HTTPOptions) func(string) err
}

// SharedHTTPOptions is the flag->httpoptions transfer code shared between
// fortio_main and fcurl.
// fortio_main and fcurl. It also sets fhttp.DefaultHTTPOptions.
func SharedHTTPOptions() *fhttp.HTTPOptions {
url := strings.TrimLeft(flag.Arg(0), " \t\r\n")
httpOpts.URL = url
Expand Down Expand Up @@ -235,5 +235,6 @@ func SharedHTTPOptions() *fhttp.HTTPOptions {
httpOpts.SequentialWarmup = *warmupFlag
httpOpts.NoResolveEachConn = *NoReResolveFlag
httpOpts.MethodOverride = *MethodFlag
fhttp.DefaultHTTPOptions = &httpOpts
return &httpOpts
}
7 changes: 7 additions & 0 deletions fhttp/http_client.go
Expand Up @@ -179,6 +179,7 @@ const (
)

// HTTPOptions holds the common options of both http clients and the headers.
// Careful when adding fields that this gets shallow copied through DefaultHTTPOptions copies.
type HTTPOptions struct {
TLSOptions
URL string
Expand Down Expand Up @@ -223,6 +224,12 @@ type HTTPOptions struct {
DataWriter io.Writer `json:"-"` // if set, the response body is written to this writer.
}

// DefaultHTTPOptions is meant to be set by the main() from bincommon.SharedHTTPOptions() and used
// as a starting point for CommonHTTPOptionsFromForm which is used for FetchHandler and forwarder as
// well as the UI.
// Initialized to empty to avoid nil pointer deref in unit tests that do not call bincommon.SharedHTTPOptions().
var DefaultHTTPOptions = &HTTPOptions{}

type CreateClientTrace func(ctx context.Context) *httptrace.ClientTrace

type CreateTransport func(base http.RoundTripper) http.RoundTripper
Expand Down
2 changes: 1 addition & 1 deletion fhttp/http_server.go
Expand Up @@ -464,7 +464,7 @@ func ServeTLS(port, debugPath string, to *TLSOptions) (*http.ServeMux, net.Addr)
startTime = time.Now()
var mux *http.ServeMux
var addr net.Addr
if to.Cert != "" && to.Key != "" {
if to.DoTLS() {
mux, addr = HTTPSServer("https-echo", port, to)
} else {
mux, addr = HTTPServer("http-echo", port)
Expand Down
8 changes: 6 additions & 2 deletions fhttp/http_utils.go
Expand Up @@ -47,6 +47,10 @@ type TLSOptions struct {
UnixDomainSocket string // `Path`` of unix domain socket to use instead of host:port
}

func (to *TLSOptions) DoTLS() bool {
return to.Cert != "" && to.Key != ""
}

// TLSConfig creates a tls.Config based on input TLSOptions.
// For https, ServerName is set later (once host is determined after URL parsing
// and depending on hostOverride). Used for both client and server TLS config.
Expand Down Expand Up @@ -642,7 +646,7 @@ func CommonHTTPOptionsFromForm(r *http.Request) *HTTPOptions {
resolve := r.FormValue("resolve")
timeoutStr := strings.TrimSpace(r.FormValue("timeout"))
timeout, _ := time.ParseDuration(timeoutStr) // will be 0 if empty, which is handled by runner and opts
httpopts := &HTTPOptions{}
httpopts := *DefaultHTTPOptions
// to be normalized in init 0 replaced by default value only in http runner, not here as this could be a tcp or udp runner
httpopts.URL = url // fixes #651 - ie don't normalize here
httpopts.HTTPReqTimeOut = timeout
Expand All @@ -664,5 +668,5 @@ func CommonHTTPOptionsFromForm(r *http.Request) *HTTPOptions {
log.Errf("Error adding custom headers: %v", err)
}
}
return httpopts
return &httpopts
}
3 changes: 2 additions & 1 deletion rapi/restHandler.go
Expand Up @@ -278,7 +278,8 @@ func RESTRunHandler(w http.ResponseWriter, r *http.Request) { //nolint:funlen
runid := NextRunID()
ro.RunID = runid
log.Infof("New run id %d", runid)
httpopts := &fhttp.HTTPOptions{}
defaultOptionsCopy := *fhttp.DefaultHTTPOptions
httpopts := &defaultOptionsCopy
httpopts.HTTPReqTimeOut = timeout // to be normalized in init, 0 is replaced by default value (for all runners)
// We don't call Init because this could be a tcp:// or udp:// url. Was httpopts = httpopts.Init(url) - fixes #651
httpopts.URL = url
Expand Down
6 changes: 5 additions & 1 deletion ui/uihandler.go
Expand Up @@ -733,7 +733,11 @@ func Serve(hook bincommon.FortioHook, cfg *ServerConfig) bool {
if strings.Contains(urlHostPort, "-unix-socket=") {
uiMsg += fmt.Sprintf("fortio curl %s http://localhost%s", urlHostPort, uiPath)
} else {
uiMsg += fmt.Sprintf("http://%s%s", urlHostPort, uiPath)
isHTTPS := ""
if cfg.TLSOptions.DoTLS() {
isHTTPS = "s"
}
uiMsg += fmt.Sprintf("http%s://%s%s", isHTTPS, urlHostPort, uiPath)
if strings.Contains(urlHostPort, "localhost") {
uiMsg += "\n\t (or any host/ip reachable on this server)"
}
Expand Down

0 comments on commit 6b492e2

Please sign in to comment.