forked from openfaas/of-watchdog
-
Notifications
You must be signed in to change notification settings - Fork 0
/
readiness.go
72 lines (62 loc) · 2.04 KB
/
readiness.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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package main
import (
"log"
"net/http"
"net/url"
"sync/atomic"
limiter "github.com/openfaas/faas-middleware/concurrency-limiter"
)
type readiness struct {
// functionHandler is the function invoke HTTP Handler. Using this allows
// custom ready checks in all invoke modes. For example, in forking mode
// the handler implementation (a bash script) can check the path in the env
// and respond accordingly, exit non-zero when not ready.
functionHandler http.Handler
endpoint string
lockCheck func() bool
limiter limiter.Limiter
}
// LimitMet returns true if the concurrency limit has been reached
// or false if no limiter has been used
func (r *readiness) LimitMet() bool {
if r.limiter == nil {
return false
}
return r.limiter.Met()
}
func (r *readiness) ServeHTTP(w http.ResponseWriter, req *http.Request) {
switch req.Method {
case http.MethodGet:
status := http.StatusOK
switch {
case atomic.LoadInt32(&acceptingConnections) == 0, !r.lockCheck():
status = http.StatusServiceUnavailable
case r.LimitMet():
status = http.StatusTooManyRequests
case r.endpoint != "":
upstream := url.URL{
Scheme: req.URL.Scheme,
Host: req.URL.Host,
Path: r.endpoint,
}
readyReq, err := http.NewRequestWithContext(req.Context(), http.MethodGet, upstream.String(), nil)
if err != nil {
log.Printf("Error creating readiness request to: %s : %s", upstream.String(), err)
status = http.StatusInternalServerError
break
}
// we need to set the raw RequestURI for the function invoker to see our URL path,
// otherwise it will just route to `/`, typically this shouldn't be used or set
readyReq.RequestURI = r.endpoint
readyReq.Header = req.Header.Clone()
// Instead of calling http.DefaultClient.Do(), which only works with http mode
// calling this handler can fork a process to run a request, such as when
// using bash as the function.
r.functionHandler.ServeHTTP(w, readyReq)
return
}
w.WriteHeader(status)
default:
w.WriteHeader(http.StatusMethodNotAllowed)
}
}