From e30eac9c4def6dc366b6e82b9a6c6795744c3fe8 Mon Sep 17 00:00:00 2001 From: Maxime Delporte Date: Thu, 23 Oct 2025 17:16:25 +0200 Subject: [PATCH] Updating README.md adding 'System-generated error responses' and 'Panic recovery in other goroutines' sections. --- README.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/README.md b/README.md index fb28aa0..67c4f85 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,40 @@ So, if we want to customize how something is encoded, all we need to do is imple An example is available here : **internal/data/runtime.go** +### System-generated error responses + +In certain scenarios Go's **http.Server** may still automatically generate and send plain-text HTTP responses. These scenarios include when : + +- The HTTP request specifies an unsupported HTTP protocol version. +- The HTTP request contains a missing or invalid **Host** header, or multiple **Host** headers. +- The HTTP request contains an empty **Content-Length** header. +- The HTTP request contains an unsupported **Transfer-Encoding** header. +- The size of the HTTP request headers exceeds the server's **MaxHeaderBytes** setting. +- The client makes a HTTP request to an HTTPS server. + +For example, if we try sending a request with an invalid **Host** header value, we will get a response like this: + +`$ curl -i -H "Host: こんにちは" http://localhost:4000/v1/healthcheck +HTTP/1.1 400 Bad Request: malformed Host header +Content-Type: text/plain; charset=utf-8 +Connection: close + +400 Bad Request: malformed Host header` + +Unfortunately, these responses are hard-coded into the Go Standard library, and there's nothing we can do to customize them to use JSON instead. + +But while this is something to be aware of, it's not necessarily something to worry about. In a production environment it's relatively unlikely that well-behaved, non-malicious, clients would trigger these responses anyway, and we shouldn't be overly concerned if bad clients are sometimes set a plain-text response instead of JSON. + +### Panic recovery in other goroutines + +It's important to realize that our middleware will only recover panics that happen in the _same goroutine that executed the **recoverPanic()** middleware_. + +If, for example, you have a handler which spins up another goroutine (e.g. to do some background processing), then any panics that happen in the background goroutine will not be recovered - not by the **recoverPanic()** middleware... and not by the panic recovery build into **http.Server**. These panics will cause your application to exit and bring down the server. + +So, if you are spinning up additional goroutines from within your handlers and there is any chance of a panic, you **must make sure** that you recover any panics from within those goroutines too. + +A demonstration will follow when we will use a background goroutine to send welcome emails to our API users. + ### Performance json.MarshalIndent() takes 65% longer to run and uses around 30% more memory than json.Marshal(), as well as making two more heap allocations. Those figures will change depending on what you're encoding, but they're fairly indicative of the performance impact.