github.com/go-swagger/go-swagger@v0.31.0/docs/reference/middleware.md (about)

     1  ---
     2  title: Injecting middleware
     3  date: 2023-01-01T01:01:01-08:00
     4  draft: true
     5  ---
     6  # Build Your Own middleware
     7  
     8  Go-swagger chose the golang `net/http` package as base abstraction. That means that for _any_ supported transport by the toolkit you can reuse _any_ middleware existing middlewares that following the stdlib middleware pattern.
     9  
    10  <!--more-->
    11  
    12  There are several projects providing middleware libraries for weaving all kinds of functionality into your request handling. None of those things are the job of go-swagger, go-swagger just serves your specs.
    13  
    14  The server takes care of a number of things when a request arrives:
    15  
    16  * routing
    17  * authentication
    18  * input validation
    19  * content negotiation
    20  * parameter and body binding
    21  
    22  If you're unfamiliar with the concept of golang net/http middlewares you can read up on it here:  
    23  [Making and Using HTTP Middleware](http://www.alexedwards.net/blog/making-and-using-middleware)
    24  
    25  Besides serving the swagger specification as an API, the toolkit also serves the actual swagger specification document.
    26  The convention is to use the `/swagger.json` location for serving up the specification document, so we serve the
    27  specification at that path.
    28  
    29  ### Add middleware
    30  
    31  The generated server allows for 3 extension points to inject middleware in its middleware chain. These have to do with
    32  the lifecycle of a request. You can find those hooks in the configure_xxx_api.go file.
    33  
    34  The first one is to add middleware all the way to the top of the middleware stack. To do this you add them in the
    35  `setupGlobalMiddleware` method. This middleware applies to everything in the go-swagger managed API.
    36  
    37  ```go
    38  func setupGlobalMiddleware(handler http.Handler) http.Handler {
    39  	return handler
    40  }
    41  ```
    42  
    43  The second extension point allows for middleware to be injected right before actually handling a matched request.
    44  This excludes the swagger.json document from being affected by this middleware though.  This extension point makes the
    45  middlewares execute right after routing but right before authentication, binding and validation.  You add middlewares
    46  to this point by editing the `setupMiddlewares` method in configure_xxx_api.go
    47  
    48  ```go
    49  func setupMiddlewares(handler http.Handler) http.Handler {
    50  	return handler
    51  }
    52  ```
    53  
    54  The third point allows you to set the middleware for existing handler by its route and HTTP method. It can be done in the `configureAPI` function by calling `api.AddMiddlewareFor` method.
    55  
    56  ```go
    57  func configureAPI(api *operations.SomeAPI) http.Handler {
    58      api.AddMiddlewareFor('GET', '/', customMiddlewareFunc)
    59  }
    60  ```
    61  
    62  The global middleware is an excellent place to do things like panic handling, request logging or adding metrics.  While
    63  the plain middleware allows you to kind of filter this by request path without having to take care of routing. You also
    64  get access to the full context that the go-swagger toolkit uses throughout the lifecycle of a request.
    65  
    66  #### Add logging and panic handling
    67  
    68  A very common requirement for HTTP APIs is to include some form of logging. Another one is to handle panics from your
    69  API requests.  The example for a possible implementation of this uses [this community provided
    70  middleware](https://github.com/dre1080/recover) to catch panics.
    71  
    72  ```go
    73  func setupGlobalMiddleware(handler http.Handler) http.Handler {
    74    recovery := recover.New(&recover.Options{
    75      Log: log.Print,
    76    })
    77    return recovery(handler)
    78  }
    79  ```
    80  
    81  There are tons of middlewares out there, some are framework specific and some frameworks don't really use the plain
    82  vanilla golang net/http as base abstraction. For those you can use a project like [interpose](https://github.com/carbocation/interpose) that serves as an adapter
    83  layer so you can still reuse middlewares. Of course nobody is stopping you to just implement your own middlewares.
    84  
    85  For example using interpose to integrate with [logrus](https://github.com/carbocation/interpose/blob/master/middleware/negronilogrus.go).
    86  
    87  ```go
    88  import (
    89    interpose "github.com/carbocation/interpose/middleware"
    90  )
    91  func setupGlobalMiddleware(handler http.Handler) http.Handler {
    92    logViaLogrus := interpose.NegroniLogrus()
    93    return logViaLogrus(handler)
    94  }
    95  ```
    96  
    97  And you can compose these middlewares into a stack using functions.
    98  
    99  ```go
   100  func setupGlobalMiddleware(handler http.Handler) http.Handler {
   101    handlePanic := recover.New(&recover.Options{
   102      Log: log.Print,
   103    })
   104  
   105    logViaLogrus := interpose.NegroniLogrus()
   106  
   107    return handlePanic(
   108      logViaLogrus(
   109        handler
   110      )
   111    )
   112  }
   113  ```
   114  
   115  #### Add rate limiting
   116  
   117  You can also add rate limiting in a similar way. Let's say we just want to rate limit the valid requests to our swagger
   118  API. To do so we could use [tollbooth](https://github.com/didip/tollbooth).
   119  
   120  ```go
   121  func setupMiddlewares(handler http.Handler) http.Handler {
   122    limiter := tollbooth.NewLimiter(1, time.Second)
   123    limiter.IPLookups = []string{"RemoteAddr", "X-Forwarded-For", "X-Real-IP"}
   124  	return tollbooth.LimitFuncHandler(handler)
   125  }
   126  ```
   127  
   128  And with this you've added rate limiting to your application.
   129  
   130  #### Add middleware to certain routes
   131  
   132  You can add standard `net/http` middleware to certain routes.
   133  
   134  ```go
   135  func myMiddleware(handler http.Handler) http.Handler {
   136      return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){
   137      		// do some middleware logic here
   138      		handler.ServeHTTP(w, r)
   139      	})
   140  }
   141  
   142  ...
   143  api.AddMiddlewareFor("POST", "/example", myMiddleware)
   144  ```