Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package fortio for openSUSE:Factory checked 
in at 2022-03-20 20:55:38
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/fortio (Old)
 and      /work/SRC/openSUSE:Factory/.fortio.new.25692 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "fortio"

Sun Mar 20 20:55:38 2022 rev:3 rq:963224 version:1.22.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/fortio/fortio.changes    2022-03-18 
16:42:47.701209621 +0100
+++ /work/SRC/openSUSE:Factory/.fortio.new.25692/fortio.changes 2022-03-20 
20:55:54.390557360 +0100
@@ -1,0 +2,8 @@
+Sun Mar 20 10:22:45 UTC 2022 - ka...@b1-systems.de
+
+- Update to version 1.22.0:
+  * allow a headers json array in json rest api payload ... (#523)
+  * Echo prefix after /debug/ (#525)
+  * `-server-idle-timeout` and close=x as a % instead of just true/false for 
all echo requests, `-calc-qps` client side (#522)
+
+-------------------------------------------------------------------

Old:
----
  fortio-1.21.2.tar.gz

New:
----
  fortio-1.22.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ fortio.spec ++++++
--- /var/tmp/diff_new_pack.pKhkfu/_old  2022-03-20 20:55:55.622559133 +0100
+++ /var/tmp/diff_new_pack.pKhkfu/_new  2022-03-20 20:55:55.626559138 +0100
@@ -19,7 +19,7 @@
 %define __arch_install_post export NO_BRP_STRIP_DEBUG=true
 
 Name:           fortio
-Version:        1.21.2
+Version:        1.22.0
 Release:        0
 Summary:        Load testing library, command line tool, advanced echo server 
and web UI
 License:        Apache-2.0

++++++ _service ++++++
--- /var/tmp/diff_new_pack.pKhkfu/_old  2022-03-20 20:55:55.666559196 +0100
+++ /var/tmp/diff_new_pack.pKhkfu/_new  2022-03-20 20:55:55.670559202 +0100
@@ -3,7 +3,7 @@
     <param name="url">https://github.com/fortio/fortio</param>
     <param name="scm">git</param>
     <param name="exclude">.git</param>
-    <param name="revision">v1.21.2</param>
+    <param name="revision">v1.22.0</param>
     <param name="versionformat">@PARENT_TAG@</param>
     <param name="changesgenerate">enable</param>
     <param name="versionrewrite-pattern">v(.*)</param>
@@ -16,7 +16,7 @@
     <param name="compression">gz</param>
   </service>
   <service name="go_modules" mode="disabled">
-    <param name="archive">fortio-1.21.2.tar.gz</param>
+    <param name="archive">fortio-1.22.0.tar.gz</param>
   </service>
 </services>
 

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.pKhkfu/_old  2022-03-20 20:55:55.690559230 +0100
+++ /var/tmp/diff_new_pack.pKhkfu/_new  2022-03-20 20:55:55.694559236 +0100
@@ -1,6 +1,6 @@
 <servicedata>
 <service name="tar_scm">
                 <param name="url">https://github.com/fortio/fortio</param>
-              <param 
name="changesrevision">f82e822e2dec925e7a7c85368971560b80bfcdec</param></service></servicedata>
+              <param 
name="changesrevision">b0adf910295107f689dcca6afb9fe2b397cbb977</param></service></servicedata>
 (No newline at EOF)
 

++++++ fortio-1.21.2.tar.gz -> fortio-1.22.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fortio-1.21.2/README.md new/fortio-1.22.0/README.md
--- old/fortio-1.21.2/README.md 2022-03-18 02:34:29.000000000 +0100
+++ new/fortio-1.22.0/README.md 2022-03-20 02:19:30.000000000 +0100
@@ -46,13 +46,13 @@
 Or download one of the binary distributions, from the 
[releases](https://github.com/fortio/fortio/releases) assets page or for 
instance:
 
 ```shell
-curl -L 
https://github.com/fortio/fortio/releases/download/v1.21.2/fortio-linux_x64-1.21.2.tgz
 \
+curl -L 
https://github.com/fortio/fortio/releases/download/v1.22.0/fortio-linux_x64-1.22.0.tgz
 \
  | sudo tar -C / -xvzpf -
 # or the debian package
-wget 
https://github.com/fortio/fortio/releases/download/v1.21.2/fortio_1.21.2_amd64.deb
-dpkg -i fortio_1.21.2_amd64.deb
+wget 
https://github.com/fortio/fortio/releases/download/v1.22.0/fortio_1.22.0_amd64.deb
+dpkg -i fortio_1.22.0_amd64.deb
 # or the rpm
-rpm -i 
https://github.com/fortio/fortio/releases/download/v1.21.2/fortio-1.21.2-1.x86_64.rpm
+rpm -i 
https://github.com/fortio/fortio/releases/download/v1.22.0/fortio-1.22.0-1.x86_64.rpm
 ```
 
 On a MacOS you can also install Fortio using [Homebrew](https://brew.sh/):
@@ -61,7 +61,7 @@
 brew install fortio
 ```
 
-On Windows, download 
https://github.com/fortio/fortio/releases/download/v1.21.2/fortio_win_1.21.2.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.22.0/fortio_win_1.22.0.zip
 and extract `fortio.exe` to any location, then using the Windows Command 
Prompt:
 ```
 fortio.exe server
 ```
@@ -92,6 +92,8 @@
 | `-c connections` | Number of parallel simultaneous connections (and matching 
go routine) |
 | `-t duration` | How long to run the test  (for instance `-t 30m` for 30 
minutes) or 0 to run until ^C, example (default 5s) |
 | `-n numcalls` | Run for exactly this number of calls instead of duration. 
Default (0) is to use duration (-t). |
+| `-payload str` or `-payload-file fname` | Switch to using POST with the 
given payload (see also `-payload-size` for random payload)|
+| `-uniform` | Spread the calls across threads |
 | `-r resolution` | Resolution of the histogram lowest buckets in seconds 
(default 0.001 i.e 1ms), use 1/10th of your expected typical latency |
 | `-H "header: value"` | Can be specified multiple times to add headers 
(including Host:) |
 | `-a`     |  Automatically save JSON result with filename based on labels and 
timestamp |
@@ -104,7 +106,7 @@
 <details>
 <!-- use release/updateFlags.sh to update this section -->
 <pre>
-???????????? 1.21.2 usage:
+???????????? 1.22.0 usage:
 where command is one of: load (load testing), server (starts ui, http-echo,
  redirect, proxies, tcp-echo and grpc ping servers), tcp-echo (only the 
tcp-echo
  server), report (report only UI server), redirect (only the redirect server),
@@ -140,6 +142,8 @@
   -cacert Path
         Path to a custom CA certificate file to be used for the TLS client
 connections, if empty, use https:// prefix for standard internet/system CAs
+  -calc-qps
+        Calculate the qps based on number of requests (-n) and duration (-t)
   -cert Path
         Path to the certificate file to be used for client or server TLS
   -compression
@@ -152,6 +156,9 @@
 from GET to POST.
   -curl
         Just fetch the content once
+  -curl-stdout-headers
+        Restore pre 1.22 behavior where http headers of the fast client are
+output to stdout in curl mode. now stderr by default.
   -data-dir Directory
         Directory where JSON results are stored/read (default ".")
   -echo-debug-path URI
@@ -269,6 +276,8 @@
   -sequential-warmup
         http(s) runner warmup done in parallel instead of sequentially. When
 set, restores pre 1.21 behavior
+  -server-idle-timeout value
+        Default IdleTimeout for servers (default 30s)
   -static-dir path
         Deprecated/unused path.
   -stdclient
@@ -319,7 +328,7 @@
 | delay     | duration to delay the response by. Can be a single value or a 
comma separated list of probabilities, e.g `delay=150us:10,2ms:5,0.5s:1` for 
10% of chance of a 150 us delay, 5% of a 2ms delay and 1% of a 1/2 second delay 
|
 | status    | http status to return instead of 200. Can be a single value or a 
comma separated list of probabilities, e.g `status=404:10,503:5,429:1` for 10% 
of chance of a 404 status, 5% of a 503 status and 1% of a 429 status |
 | size      | size of the payload to reply instead of echoing input. Also 
works as probabilities list. `size=1024:10,512:5` 10% of response will be 1k 
and 5% will be 512 bytes payload and the rest defaults to echoing back. |
-| close     | close the socket after answering e.g `close=true` |
+| close     | close the socket after answering e.g `close=true` to close after 
all requests or `close=5.3` to close after approximately 5.3% of requests|
 | header    | header(s) to add to the reply e.g. `&header=Foo:Bar&header=X:Y` |
 
 You can set a default value for all these by passing 
`-echo-server-default-params` to the server command line, for instance:
@@ -336,7 +345,7 @@
   * Download/sync from an Amazon S3 or Google Cloud compatible bucket listings 
[XML URLs](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGET.html)
 
 * API to trigger and cancel runs from the running server (like the form ui but 
more directly and with `async=on` option)
-  * `/fortio/rest/run` starts a run; the arguments are either from the command 
line or from POSTed JSON; `jsonPath` can be provided to look for in a subset of 
the json object, for instance `jsonPath=metadata` allows to use the flagger 
webhook meta data for fortio run parameters (see 
[#493](https://github.com/fortio/fortio/pull/493)).
+  * `/fortio/rest/run` starts a run; the arguments are either from the command 
line or from POSTed JSON; `jsonPath` can be provided to look for in a subset of 
the json object, for instance `jsonPath=metadata` allows to use the flagger 
webhook meta data for fortio run parameters (see [Remote Triggered load test 
section below](#remote-triggered-load-test-server-mode-rest-api)).
   * `/fortio/rest/stop` stops all current run or by run id.
 
 The `report` mode is a readonly subset of the above directly on `/`.
@@ -596,6 +605,186 @@
 All done 40 calls (plus 4 warmup) 60.588 ms avg, 7.9 qps
 ```
 
+
+### Remote triggered load test (server mode rest API)
+
+New since 1.18 the server has a `fortio/rest/run` endpoint similar to what the 
form UI submit in `fortio/` to start a run.
+  - plus `async` query arg or json value `"on"` will make the run asynchronous 
(returns just the runid of the run instead of waiting for the result)
+  - plus read all the run configuration from either query args or jsonPath 
POSTed info
+  - compatible with [flagger](https://github.com/fluxcd/flagger) and other 
webhooks
+  - New in 1.22: use `headers` json array to send headers (or multiple `&H=` 
query args)
+
+Examples:
+
+```shell
+$ curl -v -d '{"metadata": {"url":"localhost:8080", "c":"1", "n":"1", 
"async":"on", "save":"on"}}' \
+     "localhost:8080/fortio/rest/run?jsonPath=.metadata"
+{"started": 3}
+```
+makes a 1 connection 1 query run for localhost:8080 url asynchronously and 
saves results
+
+or minimally:
+```shell
+curl -s -d '{"url":"localhost:8080"}' "localhost:8080/fortio/rest/run" | jq
+```
+
+More complete example:
+
+With sample.json (all values must be strings, even the numbers):
+```json
+{
+    "metadata": {
+        "url": "localhost:8080",
+        "payload": "foo",
+        "qps": "40",
+        "c": "2",
+        "t": "0.1s",
+        "headers": [
+            "Foo:Bar",
+            "X-Blah: Something else"
+        ],
+        "save": "on"
+    }
+}
+```
+You can run:
+```shell
+$ fortio curl -stdclient -payload-file sample.json 
"http://localhost:8080/fortio/rest/run?jsonPath=.metadata"; > result.json
+```
+which makes requests like this:
+```
+POST / HTTP/1.1
+Host: localhost:8080
+Content-Length: 3
+Content-Type: application/octet-stream
+Foo: Bar
+X-Blah: Something else
+X-On-Behalf-Of: [::1]:62629
+
+foo
+```
+
+and you get in result.json
+```json
+{
+  "RunType": "HTTP",
+  "Labels": "",
+  "StartTime": "2022-03-19T15:34:23.279389-07:00",
+  "RequestedQPS": "40",
+  "RequestedDuration": "100ms",
+  "ActualQPS": 38.44836361217263,
+  "ActualDuration": 104035637,
+  "NumThreads": 2,
+  "Version": "v1.22.0",
+  "DurationHistogram": {
+    "Count": 4,
+    "Min": 0.00027292,
+    "Max": 0.000930407,
+    "Sum": 0.002332047,
+    "Avg": 0.00058301175,
+    "StdDev": 0.00028491034912527755,
+    "Data": [
+      {
+        "Start": 0.00027292,
+        "End": 0.000930407,
+        "Percent": 100,
+        "Count": 4
+      }
+    ],
+    "Percentiles": [
+      {
+        "Percentile": 50,
+        "Value": 0.0004920823333333334
+      },
+      {
+        "Percentile": 75,
+        "Value": 0.0007112446666666667
+      },
+      {
+        "Percentile": 90,
+        "Value": 0.0008427420666666666
+      },
+      {
+        "Percentile": 99,
+        "Value": 0.0009216405066666668
+      },
+      {
+        "Percentile": 99.9,
+        "Value": 0.0009295303506666667
+      }
+    ]
+  },
+  "Exactly": 0,
+  "Jitter": false,
+  "Uniform": false,
+  "RunID": 7,
+  "AccessLoggerInfo": "",
+  "RetCodes": {
+    "200": 4
+  },
+  "URL": "http://localhost:8080";,
+  "NumConnections": 1,
+  "Compression": false,
+  "DisableFastClient": false,
+  "HTTP10": false,
+  "DisableKeepAlive": false,
+  "AllowHalfClose": false,
+  "Insecure": false,
+  "FollowRedirects": false,
+  "CACert": "",
+  "Cert": "",
+  "Key": "",
+  "Resolve": "",
+  "HTTPReqTimeOut": 3000000000,
+  "UserCredentials": "",
+  "ContentType": "",
+  "Payload": "Zm9v",
+  "UnixDomainSocket": "",
+  "LogErrors": false,
+  "ID": 0,
+  "SequentialWarmup": false,
+  "Sizes": {
+    "Count": 4,
+    "Min": 118,
+    "Max": 118,
+    "Sum": 472,
+    "Avg": 118,
+    "StdDev": 0,
+    "Data": [
+      {
+        "Start": 118,
+        "End": 118,
+        "Percent": 100,
+        "Count": 4
+      }
+    ],
+    "Percentiles": null
+  },
+  "HeaderSizes": {
+    "Count": 4,
+    "Min": 115,
+    "Max": 115,
+    "Sum": 460,
+    "Avg": 115,
+    "StdDev": 0,
+    "Data": [
+      {
+        "Start": 115,
+        "End": 115,
+        "Percent": 100,
+        "Count": 4
+      }
+    ],
+    "Percentiles": null
+  },
+  "SocketCount": 2,
+  "AbortOn": 0
+}
+```
+
+- There is also the `fortio/rest/stop` endpoint to stop a run by its id or all 
runs if not specified
+
+
 ### GRPC load test
 
 Uses `-s` to use multiple (h2/grpc) streams per connection (`-c`), request to 
hit the fortio ping grpc endpoint with a delay in replies of 0.25s and an extra 
payload for 10 bytes and auto save the json result:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fortio-1.21.2/Webtest.sh new/fortio-1.22.0/Webtest.sh
--- old/fortio-1.21.2/Webtest.sh        2022-03-18 02:34:29.000000000 +0100
+++ new/fortio-1.22.0/Webtest.sh        2022-03-20 02:19:30.000000000 +0100
@@ -48,7 +48,7 @@
 $CURL https://www.google.com/robots.txt > /dev/null
 
 # Check that quiet is quiet. Issue #385.
-QUIETCURLTEST="docker exec $DOCKERNAME $FORTIO_BIN_PATH curl -quiet 
www.google.com"
+QUIETCURLTEST="docker exec $DOCKERNAME $FORTIO_BIN_PATH curl -quiet 
-curl-stdout-headers www.google.com"
 if [ "$($QUIETCURLTEST 2>&1 > /dev/null  | wc -l)" -ne 0 ]; then
   echo "Error, -quiet still outputs logs"
   $QUIETCURLTEST > /dev/null
@@ -63,7 +63,7 @@
 $CURL 
"${BASE_FORTIO}fetch/localhost:8080$FORTIO_UI_PREFIX?url=localhost:8079&load=Start&qps=-1&json=on&n=100&runner=grpc"
 | grep '"SERVING": 100'
 # Check we get the logo (need to remove the CR from raw headers)
 VERSION=$(docker exec $DOCKERNAME $FORTIO_BIN_PATH version -s)
-LOGO_TYPE=$($CURL "${BASE_FORTIO}${VERSION}/static/img/${LOGO}" | grep -i 
Content-Type: | tr -d '\r'| awk '{print $2}')
+LOGO_TYPE=$($CURL "${BASE_FORTIO}${VERSION}/static/img/${LOGO}" 2>&1 
>/dev/null | grep -i Content-Type: | tr -d '\r'| awk '{print $2}')
 if [ "$LOGO_TYPE" != "image/svg+xml" ]; then
   echo "Unexpected content type for the logo: $LOGO_TYPE"
   exit 1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fortio-1.21.2/bincommon/commonflags.go 
new/fortio-1.22.0/bincommon/commonflags.go
--- old/fortio-1.21.2/bincommon/commonflags.go  2022-03-18 02:34:29.000000000 
+0100
+++ new/fortio-1.22.0/bincommon/commonflags.go  2022-03-20 02:19:30.000000000 
+0100
@@ -104,6 +104,8 @@
        HelpFlag   = flag.Bool("h", false, "Print usage/help on stdout")
        warmupFlag = flag.Bool("sequential-warmup", false,
                "http(s) runner warmup done in parallel instead of 
sequentially. When set, restores pre 1.21 behavior")
+       curlHeadersStdout = flag.Bool("curl-stdout-headers", false,
+               "Restore pre 1.22 behavior where http headers of the fast 
client are output to stdout in curl mode. now stderr by default.")
 )
 
 // SharedMain is the common part of main from fortio_main and fcurl.
@@ -145,7 +147,12 @@
        }
        code, data, header := client.Fetch()
        log.LogVf("Fetch result code %d, data len %d, headerlen %d", code, 
len(data), header)
-       os.Stdout.Write(data)
+       if *curlHeadersStdout {
+               os.Stdout.Write(data)
+       } else {
+               os.Stderr.Write(data[:header])
+               os.Stdout.Write(data[header:])
+       }
        if code != http.StatusOK {
                log.Errf("Error status %d : %s", code, fhttp.DebugSummary(data, 
512))
                os.Exit(1)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fortio-1.21.2/fhttp/http_server.go 
new/fortio-1.22.0/fhttp/http_server.go
--- old/fortio-1.21.2/fhttp/http_server.go      2022-03-18 02:34:29.000000000 
+0100
+++ new/fortio-1.22.0/fhttp/http_server.go      2022-03-20 02:19:30.000000000 
+0100
@@ -51,6 +51,7 @@
                "Default parameters/querystring to use if there isn't one 
provided explicitly. E.g \"status=404&delay=3s\"")
        fetch2CopiesAllHeader = dflag.DynBool(flag.CommandLine, 
"proxy-all-headers", true,
                "Determines if only tracing or all headers (and cookies) are 
copied from request on the fetch2 ui/server endpoint")
+       serverIdleTimeout = dflag.DynDuration(flag.CommandLine, 
"server-idle-timeout", 30*time.Second, "Default IdleTimeout for servers")
 )
 
 // EchoHandler is an http server handler echoing back the input.
@@ -97,7 +98,7 @@
                rqNum := atomic.AddInt64(&EchoRequests, 1)
                log.Debugf("Request # %v", rqNum)
        }
-       if r.FormValue("close") != "" {
+       if generateClose(r.FormValue("close")) {
                log.Debugf("Adding Connection:close / will close socket")
                w.Header().Set("Connection", "close")
        }
@@ -167,7 +168,8 @@
        m := http.NewServeMux()
        h2s := &http2.Server{}
        s := &http.Server{
-               Handler: h2c.NewHandler(m, h2s),
+               IdleTimeout: serverIdleTimeout.Get(),
+               Handler:     h2c.NewHandler(m, h2s),
        }
        listener, addr := fnet.Listen(name, port)
        if listener == nil {
@@ -349,6 +351,7 @@
        }
        if debugPath != "" {
                mux.HandleFunc(debugPath, DebugHandler)
+               mux.HandleFunc(strings.TrimSuffix(debugPath, "/")+"/echo/", 
EchoHandler) // Fix #524
        }
        mux.HandleFunc("/", EchoHandler)
        return mux, addr
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fortio-1.21.2/fhttp/http_test.go 
new/fortio-1.22.0/fhttp/http_test.go
--- old/fortio-1.21.2/fhttp/http_test.go        2022-03-18 02:34:29.000000000 
+0100
+++ new/fortio-1.22.0/fhttp/http_test.go        2022-03-20 02:19:30.000000000 
+0100
@@ -497,6 +497,28 @@
        }
 }
 
+func TestGenerateClose(t *testing.T) {
+       tests := []struct {
+               input    string
+               expected bool
+       }{
+               // not numbers
+               {"true", true},
+               {"false", false},
+               {"x", true},
+               // Numbers
+               {"0", false},
+               {"0.0", false},
+               {"99.9999999", true}, // well, in theory this should fail once 
in a blue moon
+               {"100", true},
+       }
+       for _, tst := range tests {
+               if actual := generateClose(tst.input); actual != tst.expected {
+                       t.Errorf("Got %v, expected %v for generateClose(%q)", 
actual, tst.expected, tst.input)
+               }
+       }
+}
+
 func TestPayloadWithEchoBack(t *testing.T) {
        tests := []struct {
                payload           []byte
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fortio-1.21.2/fhttp/http_utils.go 
new/fortio-1.22.0/fhttp/http_utils.go
--- old/fortio-1.21.2/fhttp/http_utils.go       2022-03-18 02:34:29.000000000 
+0100
+++ new/fortio-1.22.0/fhttp/http_utils.go       2022-03-20 02:19:30.000000000 
+0100
@@ -398,6 +398,28 @@
        return 0
 }
 
+// generateClose from string, format: close=true for 100% close
+// close=true:10 or close=10 for 10% socket close.
+func generateClose(closeStr string) bool {
+       if closeStr == "" || closeStr == "false" {
+               return false
+       }
+       if closeStr == "true" { // avoid throwing error for pre 1.22 syntax
+               return true
+       }
+       p, err := strconv.ParseFloat(closeStr, 32)
+       if err != nil {
+               log.Debugf("error %v parsing close=%q treating as true", err, 
closeStr)
+               return true
+       }
+       res := 100. * rand.Float32() // nolint: gosec // we want fast not crypto
+       log.Debugf("close=%f rolled %f", p, res)
+       if res <= float32(p) {
+               return true
+       }
+       return false
+}
+
 // RoundDuration rounds to 10th of second.
 func RoundDuration(d time.Duration) time.Duration {
        return d.Round(100 * time.Millisecond)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fortio-1.21.2/fhttp/httprunner.go 
new/fortio-1.22.0/fhttp/httprunner.go
--- old/fortio-1.21.2/fhttp/httprunner.go       2022-03-18 02:34:29.000000000 
+0100
+++ new/fortio-1.22.0/fhttp/httprunner.go       2022-03-20 02:19:30.000000000 
+0100
@@ -77,7 +77,7 @@
 }
 
 // RunHTTPTest runs an http test and returns the aggregated stats.
-// nolint: funlen, gocognit
+// nolint: funlen, gocognit, gocyclo
 func RunHTTPTest(o *HTTPRunnerOptions) (*HTTPRunnerResults, error) {
        o.RunType = "HTTP"
        warmupMode := "parallel"
@@ -192,9 +192,10 @@
        r.Options().ReleaseRunners()
        sort.Ints(keys)
        totalCount := float64(total.DurationHistogram.Count)
-       _, _ = fmt.Fprintf(out, "Sockets used: %d (for perfect keepalive, would 
be %d)\n", total.SocketCount, r.Options().NumThreads)
-       _, _ = fmt.Fprintf(out, "Jitter: %t\n", total.Jitter)
-       _, _ = fmt.Fprintf(out, "Uniform: %t\n", total.Uniform)
+       if !o.DisableFastClient {
+               _, _ = fmt.Fprintf(out, "Sockets used: %d (for perfect 
keepalive, would be %d)\n", total.SocketCount, r.Options().NumThreads)
+       }
+       _, _ = fmt.Fprintf(out, "Uniform: %t, Jitter: %t\n", total.Uniform, 
total.Jitter)
        for _, k := range keys {
                _, _ = fmt.Fprintf(out, "Code %3d : %d (%.1f %%)\n", k, 
total.RetCodes[k], 100.*float64(total.RetCodes[k])/totalCount)
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fortio-1.21.2/fhttp/httprunner_test.go 
new/fortio-1.22.0/fhttp/httprunner_test.go
--- old/fortio-1.21.2/fhttp/httprunner_test.go  2022-03-18 02:34:29.000000000 
+0100
+++ new/fortio-1.22.0/fhttp/httprunner_test.go  2022-03-20 02:19:30.000000000 
+0100
@@ -187,7 +187,7 @@
 func TestClosingAndSocketCount(t *testing.T) {
        mux, addr := DynamicHTTPServer(false)
        mux.HandleFunc("/echo42/", EchoHandler)
-       URL := fmt.Sprintf("http://localhost:%d/echo42/?close=1";, addr.Port)
+       URL := fmt.Sprintf("http://localhost:%d/echo42/?close=true";, addr.Port)
        opts := HTTPRunnerOptions{}
        opts.Init(URL)
        opts.QPS = 10
@@ -234,10 +234,10 @@
        _, addr := ServeTCP("0", "/debugx1")
        port := addr.Port
        log.Infof("On addr %s found port: %d", addr, port)
-       url := fmt.Sprintf("http://localhost:%d/debugx1?env=dump";, port)
        if port == 0 {
                t.Errorf("outport: %d must be different", port)
        }
+       url := fmt.Sprintf("http://localhost:%d/debugx1?env=dump";, port)
        time.Sleep(100 * time.Millisecond)
        o := NewHTTPOptions(url)
        o.AddAndValidateExtraHeader("X-Header: value1")
@@ -253,6 +253,17 @@
        if !strings.Contains(string(data), "X-Header: value1,value2") {
                t.Errorf("Multi header not found in %s", DebugSummary(data, 
1024))
        }
+       url2 := fmt.Sprintf("http://localhost:%d/debugx1/echo/foo";, port)
+       o2 := NewHTTPOptions(url2)
+       o2.Payload = []byte("abcd")
+       c2, _ := NewClient(o2)
+       code2, data2, header := c2.Fetch()
+       if code2 != http.StatusOK {
+               t.Errorf("Unexpected non 200 ret code for debug url %s : %d", 
url, code)
+       }
+       if string(data2[header:]) != "abcd" {
+               t.Errorf("Unexpected that %s isn't an echo server, got %q", 
url2, string(data2))
+       }
 }
 
 func TestAbortOn(t *testing.T) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fortio-1.21.2/fortio_main.go 
new/fortio-1.22.0/fortio_main.go
--- old/fortio-1.21.2/fortio_main.go    2022-03-18 02:34:29.000000000 +0100
+++ new/fortio-1.22.0/fortio_main.go    2022-03-20 02:19:30.000000000 +0100
@@ -180,6 +180,7 @@
                "file `path` to log all requests to. Maybe have performance 
impacts")
        accessLogFileFormat = flag.String("access-log-format", "json",
                "`format` for access log. Supported values: [json, influx]")
+       calcQPS = flag.Bool("calc-qps", false, "Calculate the qps based on 
number of requests (-n) and duration (-t)")
 )
 
 // nolint: funlen // well yes it's fairly big and lotsa ifs.
@@ -345,7 +346,7 @@
        }
 }
 
-// nolint: funlen // maybe refactor/shorten later.
+// nolint: funlen, gocognit // maybe refactor/shorten later.
 func fortioLoad(justCurl bool, percList []float64) {
        if len(flag.Args()) != 1 {
                usageErr("Error: fortio load/curl needs a url or destination")
@@ -359,6 +360,13 @@
        prevGoMaxProcs := runtime.GOMAXPROCS(*goMaxProcsFlag)
        out := os.Stderr
        qps := *qpsFlag // TODO possibly use translated <=0 to "max" from 
results/options normalization in periodic/
+       if *calcQPS {
+               if *exactlyFlag == 0 || *durationFlag <= 0 {
+                       usageErr("Error: can't use `-calc-qps` without also 
specifying `-n` and `-t`")
+               }
+               qps = float64(*exactlyFlag) / (*durationFlag).Seconds()
+               log.LogVf("Calculated QPS to do %d request in %v: %f", 
*exactlyFlag, *durationFlag, qps)
+       }
        _, _ = fmt.Fprintf(out, "Fortio %s running at %g queries per second, 
%d->%d procs",
                version.Short(), qps, prevGoMaxProcs, runtime.GOMAXPROCS(0))
        if *exactlyFlag > 0 {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fortio-1.21.2/ui/restHandler.go 
new/fortio-1.22.0/ui/restHandler.go
--- old/fortio-1.21.2/ui/restHandler.go 2022-03-18 02:34:29.000000000 +0100
+++ new/fortio-1.22.0/ui/restHandler.go 2022-03-20 02:19:30.000000000 +0100
@@ -100,6 +100,7 @@
 // RESTRunHandler is api version of UI submit handler.
 func RESTRunHandler(w http.ResponseWriter, r *http.Request) { // nolint: funlen
        fhttp.LogRequest(r, "REST Run Api call")
+       w.Header().Set("Content-Type", "application/json")
        data, err := ioutil.ReadAll(r.Body) // must be done before calling 
FormValue
        if err != nil {
                log.Errf("Error reading %v", err)
@@ -136,13 +137,13 @@
        jitter := (FormValue(r, jd, "jitter") == "on")
        uniform := (FormValue(r, jd, "uniform") == "on")
        stdClient := (FormValue(r, jd, "stdclient") == "on")
-       sequentialWarmup := (r.FormValue("sequential-warmup") == "on")
+       sequentialWarmup := (FormValue(r, jd, "sequential-warmup") == "on")
        httpsInsecure := (FormValue(r, jd, "https-insecure") == "on")
        resolve := FormValue(r, jd, "resolve")
        timeoutStr := strings.TrimSpace(FormValue(r, jd, "timeout"))
        timeout, _ := time.ParseDuration(timeoutStr) // will be 0 if empty, 
which is handled by runner and opts
        var dur time.Duration
-       if durStr == "on" || ((len(r.Form["t"]) > 1) && r.Form["t"][1] == "on") 
{
+       if durStr == "on" {
                dur = -1
        } else {
                var err error
@@ -192,7 +193,6 @@
        if len(payload) > 0 {
                httpopts.Payload = []byte(payload)
        }
-       // mode == run case:
        for _, header := range r.Form["H"] {
                if len(header) == 0 {
                        continue
@@ -203,6 +203,26 @@
                        log.Errf("Error adding custom headers: %v", err)
                }
        }
+       jsonHeaders, found := jd["headers"]
+       for found { // really an if, but using while to break out without else 
below
+               res, ok := jsonHeaders.([]interface{})
+               if !ok {
+                       log.Warnf("Json Headers is %T %v / not an array, can't 
be used", jsonHeaders, jsonHeaders)
+                       break
+               }
+               for _, header := range res {
+                       log.LogVf("adding json header %T: %v", header, header)
+                       hStr, ok := header.(string)
+                       if !ok {
+                               log.Errf("Json headers must be an array of 
strings (got %T: %v)", header, header)
+                               continue
+                       }
+                       if err := httpopts.AddAndValidateExtraHeader(hStr); err 
!= nil {
+                               log.Errf("Error adding custom json headers: 
%v", err)
+                       }
+               }
+               break
+       }
        fhttp.OnBehalfOf(httpopts, r)
        if async {
                w.Write([]byte(fmt.Sprintf("{\"started\": %d}", runid)))
@@ -281,7 +301,6 @@
                // async, no result to output
                return
        }
-       w.Header().Set("Content-Type", "application/json")
        _, err = w.Write(json)
        if err != nil {
                log.Errf("Unable to write json output for %v: %v", 
r.RemoteAddr, err)
@@ -291,6 +310,7 @@
 // RESTStatusHandler will print the state of the runs.
 func RESTStatusHandler(w http.ResponseWriter, r *http.Request) {
        fhttp.LogRequest(r, "REST Status Api call")
+       w.Header().Set("Content-Type", "application/json")
        w.WriteHeader(http.StatusServiceUnavailable)
        w.Write([]byte("{\"error\":\"status not yet implemented\"}"))
 }
@@ -298,6 +318,7 @@
 // RESTStopHandler is the api to stop a given run by runid or all the runs if 
unspecified/0.
 func RESTStopHandler(w http.ResponseWriter, r *http.Request) {
        fhttp.LogRequest(r, "REST Stop Api call")
+       w.Header().Set("Content-Type", "application/json")
        runid, _ := strconv.ParseInt(r.FormValue("runid"), 10, 64)
        i := StopByRunID(runid)
        w.Write([]byte(fmt.Sprintf("{\"stopped\": %d}", i)))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fortio-1.21.2/ui/templates/browse.html 
new/fortio-1.22.0/ui/templates/browse.html
--- old/fortio-1.21.2/ui/templates/browse.html  2022-03-18 02:34:29.000000000 
+0100
+++ new/fortio-1.22.0/ui/templates/browse.html  2022-03-20 02:19:30.000000000 
+0100
@@ -1,6 +1,6 @@
 <!DOCTYPE html><html><head><title>???????????? v{{.Version}}</title>
 <script src="{{.ChartJSPath}}"></script>
-<link rel="icon" href="../favicon.ico" />
+<link rel="icon" href="{{.Version}}/static/img/favicon.ico"/>
 <style>
 a:link {
   text-decoration: none;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fortio-1.21.2/ui/templates/main.html 
new/fortio-1.22.0/ui/templates/main.html
--- old/fortio-1.21.2/ui/templates/main.html    2022-03-18 02:34:29.000000000 
+0100
+++ new/fortio-1.22.0/ui/templates/main.html    2022-03-20 02:19:30.000000000 
+0100
@@ -3,7 +3,7 @@
 <head><title>???????????? v{{.Version}}</title>
   <script src="{{.ChartJSPath}}"></script>
   <script src="{{.Version}}/static/js/fortio_chart.js"></script>
-  <link rel="icon" href="../favicon.ico"/>
+  <link rel="icon" href="{{.Version}}/static/img/favicon.ico"/>
   <link rel="stylesheet" href="{{.Version}}/static/css/fortio.css">
 </head>
 {{template "header" .}}
@@ -94,8 +94,11 @@
   </div>
 </form>
 <p><i>Or</i></p>
-<a href="{{.DebugPath}}">debug</a> and <a href="{{.DebugPath}}?env=dump">debug 
with env dump</a> and <a href="{{.DebugPath}}/pprof/">Internal PPROF</a>
+<a href="{{.DebugPath}}">debug</a> and <a href="{{.DebugPath}}?env=dump">debug 
with env dump</a>
+and <a href="{{.DebugPath}}/pprof/">Internal PPROF</a>
 and <a href="flags">Command line flags</a>
+and <a href="{{.DebugPath}}/echo/">Additional echo handler under 
{{.DebugPath}}/echo/</a> (supports all the
+query arguments mentioned on the <a 
href="https://github.com/fortio/fortio#server-urls-and-features";>Echo url 
features</a> github doc)
 <p><i>Or</i></p>
 <form action="sync">
   <div>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fortio-1.21.2/ui/templates/sync.html 
new/fortio-1.22.0/ui/templates/sync.html
--- old/fortio-1.21.2/ui/templates/sync.html    2022-03-18 02:34:29.000000000 
+0100
+++ new/fortio-1.22.0/ui/templates/sync.html    2022-03-20 02:19:30.000000000 
+0100
@@ -1,6 +1,6 @@
 <!DOCTYPE html><html><head><title>???????????? v{{.Version}}</title>
 <script src="{{.Version}}/static/js/fortio_chart.js"></script>
-<link rel="icon" href="../favicon.ico" />
+<link rel="icon" href="{{.Version}}/static/img/favicon.ico" />
 <link rel="stylesheet" href="{{.Version}}/static/css/fortio.css">
 <style>
 .checkmark {

++++++ vendor.tar.gz ++++++

Reply via email to