From 4e6298dda713d816855818282cc32caca108c597 Mon Sep 17 00:00:00 2001 From: Nicolas Carlier Date: Sat, 5 Feb 2022 08:55:09 +0100 Subject: [PATCH] feat(): improve control on streaming protocol close #51 --- README.md | 16 ++++++++++------ pkg/api/index.go | 6 ++++-- tooling/html/console.html | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 8 deletions(-) create mode 100644 tooling/html/console.html diff --git a/README.md b/README.md index b38cda8..510a20c 100644 --- a/README.md +++ b/README.md @@ -91,11 +91,15 @@ The directory structure define the webhook URL. You can omit the script extension. If you do, webhookd will search for a `.sh` file. If the script exists, the output the will be streamed to the HTTP response. -The streaming technology depends on the HTTP method used. -With `POST` the response will be chunked. -With `GET` the response will use [Server-sent events][sse]. +The streaming technology depends on the HTTP request: + +- [Server-sent events][sse] is used when: + - Using `GET` verb + - Using `text/event-stream` in `Accept` request header +- [Chunked Transfer Coding][chunked] is used otherwise. [sse]: https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events +[chunked]: https://datatracker.ietf.org/doc/html/rfc2616#section-3.6.1 *Example:* @@ -108,7 +112,7 @@ echo "foo foo foo" echo "bar bar bar" ``` -Output using `POST` (`Chunked transfer encoding`): +Output using `POST` or `GET` (`Chunked Transfer Coding`): ```bash $ curl -v -XPOST http://localhost:8080/foo/bar @@ -120,10 +124,10 @@ foo foo foo bar bar bar ``` -Output using `GET` (`Server-sent events`): +Output using `GET` and `Accept` header (`Server-sent events`): ```bash -$ curl -v -XGET http://localhost:8080/foo/bar +$ curl -v --header "Accept: text/event-stream" -XGET http://localhost:8080/foo/bar < HTTP/1.1 200 OK < Content-Type: text/event-stream < Transfer-Encoding: chunked diff --git a/pkg/api/index.go b/pkg/api/index.go index 5f8b403..ed3210e 100644 --- a/pkg/api/index.go +++ b/pkg/api/index.go @@ -87,7 +87,9 @@ func triggerWebhook(w http.ResponseWriter, r *http.Request) { // Put work in queue worker.WorkQueue <- *work - if r.Method == "GET" { + // Use content negotiation to enable Server-Sent Events + useSSE := r.Method == "GET" && r.Header.Get("Accept") == "text/event-stream" + if useSSE { // Send SSE response w.Header().Set("Content-Type", "text/event-stream") } else { @@ -105,7 +107,7 @@ func triggerWebhook(w http.ResponseWriter, r *http.Request) { break } - if r.Method == "GET" { + if useSSE { fmt.Fprintf(w, "data: %s\n\n", msg) // Send SSE response } else { fmt.Fprintf(w, "%s\n", msg) // Send chunked response diff --git a/tooling/html/console.html b/tooling/html/console.html new file mode 100644 index 0000000..890da0e --- /dev/null +++ b/tooling/html/console.html @@ -0,0 +1,38 @@ + + + + Basic Webhookd UI + + + +
+ + +
+
+        
+    
+ + + + \ No newline at end of file