-
-
Notifications
You must be signed in to change notification settings - Fork 15
/
middleware.go
55 lines (50 loc) · 1.81 KB
/
middleware.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/*
* Copyright (c) 2024 Go IoC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*/
package di
import (
"context"
"io"
"net/http"
)
// BeanKey is as a Context key, because usage of string keys is discouraged (due to obvious reasons).
type BeanKey string
// Middleware is a function that can be used with http routers to perform Request-scoped beans injection into the web
// request context. If such bean implements io.Closer, it will be attempted to close upon corresponding context
// cancellation (but may panic).
func Middleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
requestContext := r.Context()
for beanID, scope := range scopes {
if scope != Request {
continue
}
beanInstance := getRequestBeanInstance(requestContext, beanID)
requestContext = context.WithValue(requestContext, BeanKey(beanID), beanInstance)
if isCloseable(beanInstance) {
go func(ctx context.Context, beanInstance interface{}) {
<-ctx.Done()
err := beanInstance.(io.Closer).Close()
if err != nil {
panic(err)
}
}(r.Context(), beanInstance)
}
}
next.ServeHTTP(w, r.WithContext(requestContext))
})
}
func isCloseable(beanInstance interface{}) bool {
_, ok := beanInstance.(io.Closer)
return ok
}