How does ServeHTTP work?

golang http request header
servemux pattern
golang servemux
golang http client middleware
missing method servehttp
mux middleware
golang http redirect
golang handler pattern

I am studying web development in Golang (Beginner) I came across some code I played around with and I'm not too sure why it works, I looked through the library source code and docs but I only have a vague idea it still isn't clicking. Note the code below:

package main

import (
    "fmt"
    "net/http"
)

type foo int

func (m foo) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "Some text")
}

func main() {
    var bar foo
    http.ListenAndServe(":8080", bar)
}

From what I understand adding ServeHTTP(w http.ResponseWriter, r *http.Request) as a function method, invokes the handler interface (if I'm saying that correctly) and now foo is of type handler as well. I also understand that http.ListenAndServe takes an input of type handler so that is where my variable bar comes into play. When I run the code and go to localhost:8080 on my browser I get "Some Text" appearing.

EDIT: Implements the interface is the proper term NOT invoke.

Question:

How does this exactly work? How is that ServeHTTP function being accessed?

I tried looking at the source code of the libraries but couldn't pinpoint exactly how ServeHTTP worked. I found these two pieces of code (not sure if this is applicable) that sort of gave me the idea it was implementing a function but need clarification:

// The HandlerFunc type is an adapter to allow the use of
// ordinary functions as HTTP handlers. If f is a function
// with the appropriate signature, HandlerFunc(f) is a
// Handler that calls f.
type HandlerFunc func(ResponseWriter, *Request)

// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
    f(w, r)
}

I have never seen a type declaration as the one above with HandlerFunc that has a function after the name of the type. I have also seen how methods are declared but not sure what is happening in the code above.

How does this exactly work? How is that ServeHTTP function being accessed?

To answer this question we need to look how http.ListenAndServe works:

func ListenAndServe(addr string, handler Handler) error {
    server := &Server{Addr: addr, Handler: handler}
    return server.ListenAndServe()
}

Here we create a Server with given address and handler and call the ListenAndServer method so let's take a look there:

func (srv *Server) ListenAndServe() error {
    addr := srv.Addr
    if addr == "" {
        addr = ":http"
    }
    ln, err := net.Listen("tcp", addr)
    if err != nil {
        return err
    }
    return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
}

This method just starts listening given address and calls the Server method with our freshly created listener so let's follow the trail there:

func (srv *Server) Serve(l net.Listener) error {
    defer l.Close()

    ...

    for {
        rw, e := l.Accept()

        ...

        c := srv.newConn(rw)
        c.setState(c.rwc, StateNew) // before Serve can return
        go c.serve(ctx)
    }
}

From the Serve method we can see that this is the point where we accept the new connection and start handling it in it's own goroutine.

// Serve a new connection.
func (c *conn) serve(ctx context.Context) {
    ...
    for {
        w, err := c.readRequest(ctx)
        ...
        serverHandler{c.server}.ServeHTTP(w, w.req)
        ...
    }
}

Here we finally call the ServeHTTP method but as we can see this is not yet our implementation of that function but something from the standard library so let's take a look what that serverHandler struct contains:

// serverHandler delegates to either the server's Handler or
// DefaultServeMux and also handles "OPTIONS *" requests.
type serverHandler struct {
    srv *Server
}

func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
    handler := sh.srv.Handler
    if handler == nil {
        handler = DefaultServeMux
    }
    if req.RequestURI == "*" && req.Method == "OPTIONS" {
        handler = globalOptionsHandler{}
    }
    handler.ServeHTTP(rw, req)
}

So here it is finally. If we didn't provide any Handler the DefaultServeMux will be used but since we provided our foo handler ServeHTTP from foo get's called.

And that's it. All of this can be found from server.go

A Recap of Request Handling in Go, A ServeMux is essentially a HTTP request router (or multiplexor). In lay terms, that simply means it must have a ServeHTTP method with the following Most of the time using a function as a handler like this works well. Enter your email address to follow this blog and receive notifications of new posts by email. Join 131 other followers. Follow

Go's HTTP server takes in an address to listen on, and a handler. Internally, it creates a TCP listener to accept connections on the given address, and whenever a request comes in, it:

  1. Parses the raw HTTP request (path, headers, etc) into a http.Request
  2. Creates a http.ResponseWriter for sending the response
  3. Invokes the handler by calling its ServeHTTP method, passing in the Request and ResponseWriter

The handler can be anything that satisfies the Handler interface, which your foo type does:

type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}

The standard library also includes some conveniences, like HandlerFunc (which allows you to pass any func(ResponseWriter, *Request) and use it as a Handler) and ServeMux, which allows you to register many Handlers and choose which one handles which request based on the incoming request path.

Making and Using HTTP Middleware, In Go a common place to use middleware is between a router (such as http. I'm going to explain how to make custom middleware that works in this pattern, control to this next handler by calling it's ServeHTTP() method. Serve definition, to act as a servant. See more.

The relevant type in net/http is

type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}

an interface type. Any concrete type implementing this interface can be used to serve HTTP request. Your bar is of type foo and foo implements the Handler interface. If the builtin HTTP server has to handle a request it will call the ServeHTTP method of your bar.

http, The prefix is stripped after the ServeHTTP call finishes and the values are sent in the That means that ConnState // cannot be used to do per-request work;� ServeHTTP should write reply headers and data to the ResponseWriter and then return. Returning signals that the request is finished; it is not valid to use the ResponseWriter or read from the Request.Body after or concurrently with the completion of the ServeHTTP call.

Type declaration in this code for

type foo int

is implementing Handler interface. We can create struct or any type to implement ServeHTTP method. like

type Foo struct{}
func (m foo) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "Some text")
}

For implementing Handler interface or any other interface It is been required to implement all methods declared in the interface on a type which is foo here.

HandlerFunc is implementing ServeHttp method of Handler interface and hence can be passed to http.ListenAndServe as a handler. It can be used to create middlewares wrapping around ServeHttp.

For more information on HanlderFunc use go doc in terminal

godoc net/http HanlderFunc

HandlerFunc, Handle and DefaultServeMux in Golang, Any type which has a ServeHTTP() method is said to implement the Handler interface: type HandlerFunc func(ResponseWriter, *Request)� The idea is that you take in an http.Handler and return a new one that does something else before and/or after calling the ServeHTTP method on the original. For example, a simple logging wrapper

I recommend going through these blog posts for anyone trying to understand about http.Handler A Recap of Request Handling in Go Making and Using HTTP Middleware

Middleware Patterns in Go, To see how this works, let's build a simple web server with a logging Start by defining a new struct that implements the ServeHTTP() method of the http. // Logger is a middleware handler that does request logging type� It means ServeHTTP is not a standalone function. The parenthesis before the function name is the Go way of defining the object on which these functions will operate. So, essentially ServeHTTP is a method of type handler and can be invoked using any object, say h, of type handler. h.ServeHTTP(w, r) They are also called receivers.

Why Cant I Pass This Function as an Http Handler?!, The compiler can automatically convert those functions int. help out anyone who can't afford a course, and I will be writing posts about working from home r *Request) func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { f(w, � Serve definition is - to be a servant. How to use serve in a sentence.

An Overview of Server-Side HTTP APIs in Go, Simply put, ServeMux is an HTTP request multiplexer. Internally, it works by dispatching or routing to the appropriate handler based on the path (URL) in func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request). If you use two-factor authentication, you need a trusted device or trusted phone number to reset your Apple ID password and unlock your account. If you have a recovery key, you can also use it to help you regain access to your account.

The http.Handler wrapper technique in #golang UPDATED, The idea is that you take in an http.Handler and return a new one that does something else before and/or after calling the ServeHTTP method� The data in SRSPlus's WHOIS database is provided to you by SRSPlus for information purposes only, that is, to assist you in obtaining information about or related to a domain name registration record. SRSPlus makes this information available "as is," and does not guarantee its accuracy.

Comments
  • The HandlerFunc has nothing to do with your actual question ("How is that ServeHTTP function being accessed?") but to clarify, it is just a normal type declaration, just as you did type foo int defining foo as being of kind integer so you can do type fn func() where fn is a type of kind func with that specific signature (no args, no return values). So HandlerFunc is a type whose definition is: a function with two arguments (whose types are ResponseWriter and *Request) and no return values.
  • ... and in Go you can define methods on any kind of type that you declare, so having a ServeHTTP method on HandlerFunc is no different from having it on foo.
  • ... and you're right being uncertain in your choice of words. "invokes the handler interface" is incorrect, it doesn't invoke, it implements the interface, these are two different things, actually "invoke an interface" is not a thing in Go. It's also not handler interface it's http.Handler interface, this is important because the former could mean anything the latter is specific and can be found in the documentation.