feat(): improve control on streaming protocol

close #51
This commit is contained in:
Nicolas Carlier 2022-02-05 08:55:09 +01:00
parent bf6fe82b54
commit 4e6298dda7
3 changed files with 52 additions and 8 deletions

View File

@ -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

View File

@ -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

38
tooling/html/console.html Normal file
View File

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<title>Basic Webhookd UI</title>
<meta charset="UTF-8">
</head>
<body>
<form onsubmit="return sendRequest(this)">
<input name="action" type="text" value="echo" required />
<button type="submit">GET</button>
</form>
<pre id="result">
<!--Server response will be inserted here-->
</pre>
<script>
/**
* @param {HTMLFormElement} form - Form with action.
*/
function sendRequest(form) {
const action = form.elements.namedItem("action").value;
const source = new EventSource(`http://localhost:8080/${action}`);
source.onopen = () => {
console.log('connected');
};
source.onmessage = (event) => {
console.log(event.data);
document.getElementById("result").innerHTML += event.data + "<br>";
};
source.onerror = event => {
console.log(event);
source.close()
};
return false;
}
</script>
</body>
</html>