user3137124
user3137124

Reputation: 575

How to intercept bad http HEAD request

Is there a way to intercept a bad HEAD request in a Go HTTP server? A bad request here would be to send a JSON payload with a HEAD request. I call this a Bad Request, but when I attempt a HEAD request with a body via curl, I get this error. However, no logging occurs in Go.

package main

import (
    "fmt"
    "log"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    log.Println(r.Method, r.URL)
    _, _ = fmt.Fprintf(w, "Hello")
}

func main() {
    http.HandleFunc("/", handler)
    log.Fatal(http.ListenAndServe(":8080", nil))
}

If I send a curl request without a body, it works as expected and a log entry is generated 2019/11/28 10:58:59 HEAD / .

$ curl -v -X HEAD  http://localhost:8080
curl -i -X HEAD  http://localhost:8080
Warning: Setting custom HTTP method to HEAD with -X/--request may not work the
Warning: way you want. Consider using -I/--head instead.
HTTP/1.1 200 OK
Date: Thu, 28 Nov 2019 16:03:22 GMT
Content-Length: 5
Content-Type: text/plain; charset=utf-8

However, if I send a curl request with a body, then I get a Bad Request status but no log is updated.

$ curl -i -X HEAD  http://localhost:8080 -d '{}'
Warning: Setting custom HTTP method to HEAD with -X/--request may not work the
Warning: way you want. Consider using -I/--head instead.
HTTP/1.1 400 Bad Request
Content-Type: text/plain; charset=utf-8
Connection: close

400 Bad Request

I want to catch this error so I can send my own custom error message back. How can I intercept this?

Upvotes: 2

Views: 1454

Answers (1)

icza
icza

Reputation: 418675

You can't. The HTTP server of the standard lib does not provide any interception point or callback for this case.

The invalid request is "killed" before your handler would be called. You can see this in server.go, conn.serve() method:

    w, err := c.readRequest(ctx)
    // ...
    if err != nil {
        switch {
        // ...
        default:
            publicErr := "400 Bad Request"
            if v, ok := err.(badRequestError); ok {
                publicErr = publicErr + ": " + string(v)
            }

            fmt.Fprintf(c.rwc, "HTTP/1.1 "+publicErr+errorHeaders+publicErr)
            return
        }
    }
    // ...
    serverHandler{c.server}.ServeHTTP(w, w.req)

Go's HTTP server provides you an implementation to handle incoming requests from clients that use / adhere to the HTTP protocol. All browsers and notable clients follow the HTTP protocol. It's not the implementation's goal to provide a fully customizable server.

Upvotes: 3

Related Questions