title: Gorilla/mux middleware next.ServeHTTP panic
body: <p>I'm having difficulty wrapping my head around a custom handler using gorilla/mux. It's actually working as intended, but fails at the very last step of calling <code>next.ServeHTTP(r, w)</code></p>
  <p>I start an http server, and attach middleware:</p>
  <pre><code>import (
      &quot;fmt&quot;
      &quot;net/http&quot;
      &quot;github.com/gorilla/mux&quot;
  )
  
  func NewServer() (*Server, error) {
      s := &amp;Server{
          // some struct ..
      }
      r := mux.NewRouter()
  
      // Route all requests to /api3
      r.PathPrefix(&quot;/api3&quot;)
      r.Methods(&quot;GET&quot;, &quot;POST&quot;, &quot;PUT&quot;, &quot;DELETE&quot;)
  
      // Attach middleware, log a thing for each request.
      r.Use(LoggingMiddleware)
  
      // .. Some user endpoints
      r.Handle(&quot;/users&quot;, api3.PostUser()).Methods(http.MethodPost)
  
      // Bind to a port and pass our router in
      err := http.ListenAndServe(&quot;:8080&quot;, r)
      if err != nil {
          // handle error.. 
      }
      return s, nil
  }
  
  func LoggingMiddleware(next http.Handler) http.Handler {
      return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
          fmt.Println(&quot;LOGGING MIDDLEWARE&quot;)
          next.ServeHTTP(w, r) &lt;-- panics every time
      })
  }
  </code></pre>
  <p>What's strange is that the above will print <code>LOGGING MIDDLEWARE</code> but promptly panics thereafter, referring to the <code>next.ServeHTTP(w, r)</code> line.</p>
  <p>This example is almost a 1:1 example of Gorilla/mux's <a href="https://github.com/gorilla/mux#middleware" rel="nofollow noreferrer">own middleware examples</a>.</p>
  <p>I've attempted to attach the middleware at the end of the of the function, before calling <code>http.ListenAndServe</code>, thinking order was an issue. It did not work: The same result appears</p>
  <p>PostUser looks like:</p>
  <pre><code>func PostUser() http.Handler {
      return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
          var req AddUserRequest
          err := json.NewDecoder(r.Body).Decode(&amp;req)
          if err != nil {
              w.WriteHeader(http.StatusBadRequest)
              return
          }
  
          err = userDb.Add()
          if err != nil {
              w.WriteHeader(http.StatusBadRequest)
              return
          }
  
          
          w.WriteHeader(http.StatusOK)
          return
      })
  }
  </code></pre>
  <p>I suspected the <code>PostUser()</code> endpoint might be the culprit. However, removing everything and having a basic endpoint still reproduces the error, example:</p>
  <pre><code>import (
      &quot;fmt&quot;
      &quot;net/http&quot;
      &quot;github.com/gorilla/mux&quot;
  )
  
  func NewServer() (*Server, error) {
      s := &amp;Server{
          // some struct ..
      }
      r := mux.NewRouter()
  
      // Route all requests to /api3
      r.PathPrefix(&quot;/api3&quot;)
      r.Methods(&quot;GET&quot;, &quot;POST&quot;, &quot;PUT&quot;, &quot;DELETE&quot;)
  
      // Attach middleware, log a thing for each request.
      r.Use(LoggingMiddleware)
  
      // health endpoint
      r.HandleFunc(&quot;/health&quot;, api3.Health)    
      // Bind to a port and pass our router in
      err := http.ListenAndServe(&quot;:8080&quot;, r)
      if err != nil {
          // handle error.. 
      }
      return s, nil
  }
  
  // Health returns 200 OK if everything is normal
  func Health(w http.ResponseWriter, r *http.Request) {
      w.WriteHeader(http.StatusOK)
      _, _ = fmt.Fprint(w, &quot;OK&quot;)
  }
  </code></pre>
  <p>The above results in the same. I.e:</p>
  <pre><code>curl http://localhost:8081/api3/health
  curl: (52) Empty reply from server
  </code></pre>
  <p>With a stacktrace as such:</p>
  <pre><code>backend-api  | LOGGING MIDDLEWARE &lt;nil&gt;
  backend-api  | 2022/02/15 15:55:22 http: panic serving 192.168.80.1:59370: runtime error: invalid memory address or nil pointer dereference
  backend-api  | goroutine 14 [running]:
  backend-api  | net/http.(*conn).serve.func1(0xc0001dc0a0)
  backend-api  |  /usr/local/go/src/net/http/server.go:1805 +0x153
  backend-api  | panic(0x8bb2e0, 0xc40c70)
  backend-api  |  /usr/local/go/src/runtime/panic.go:971 +0x499
  </code></pre>