🔀 Middlewares
To keep things simple, you can use already existing middlewares with little to no change, and you can use the simple control flow from There in your middlewares.
Full example
package main
import (
"errors"
"github.com/Gebes/there/v2/header"
"github.com/Gebes/there/v2/status"
"log"
"github.com/Gebes/there/v2"
"github.com/Gebes/there/v2/middlewares"
)
func main() {
router := there.NewRouter()
// Register global middlewares
router.Use(middlewares.Recoverer)
router.Use(middlewares.RequireHost("localhost:8080"))
router.Use(middlewares.Cors(middlewares.AllowAllConfiguration()))
router.Use(GlobalMiddleware)
router.
Get("/", Get).With(RouteSpecificMiddleware) // Register route with middleware
err := router.Listen(8080)
if err != nil {
log.Fatalln("Could not listen to 8080:", err)
}
}
func GlobalMiddleware(request there.Request, next there.Response) there.Response {
// Check the request content-type
if request.Headers.GetDefault(header.ContentType, "") != there.ContentTypeApplicationJson {
return there.Error(status.UnsupportedMediaType, errors.New("header "+header.ContentType+" is not "+there.ContentTypeApplicationJson))
}
return next // Everything is fine until here, continue
}
func RouteSpecificMiddleware(request there.Request, next there.Response) there.Response {
return there.Headers(map[string]string{
header.ResponseContentLanguage: "en",
}, next) // Set the content-language header by wrapping next with Headers
}
func Get(request there.Request) there.Response {
return there.Json(status.OK, map[string]string{
"Hello": "World",
"How": "are you?",
})
}
With the .Use
method, you can add a global middleware. No matter on which group you call it, it will be global.
On the other side, if you use the .With
method you can only add a middleware to one handler! Not to a whole group.
The GlobalMiddleware
in this code checks if the request has application/json
as content-type. If not, the request will fail with an error.
Compared to the GlobalMiddleware
, the RouteSpecificMiddleware
does not change the control flow but adds data to the response.
Be careful in this example. Global middlewares will always be called first, so if the global middleware returns an error, the content-language header won't be set by the RouteSpecificMiddleware
middleware.
Using already existing middlewares
If you have other middlewares, which you created using other routers, then there is a high chance that you can use it in There without changing much.
As an example, let us have a look at the Recoverer middleware.
func Recoverer(request there.Request, next there.Response) there.Response {
fn := func(w http.ResponseWriter, r *http.Request) {
defer func() {
if rvr := recover(); rvr != nil && rvr != http.ErrAbortHandler {
switch t := rvr.(type) {
case error:
there.Error(status.InternalServerError, t).ServeHTTP(w, r)
default:
there.Error(status.InternalServerError, errors.New(fmt.Sprint(t))).ServeHTTP(w, r)
}
}
}()
next.ServeHTTP(w, r)
}
return there.ResponseFunc(fn)
}
It is a trivial Recoverer. The only things you need to change are the types and the parameters. There provides you all the types required, so that you don't need to import net/http
.