OSDN Git Service

Merge pull request #41 from Bytom/dev
[bytom/vapor.git] / net / http / reqid / reqid.go
1 // Package reqid creates request IDs and stores them in Contexts.
2 package reqid
3
4 import (
5         "context"
6         "crypto/rand"
7         "encoding/hex"
8         "net/http"
9
10         log "github.com/sirupsen/logrus"
11 )
12
13 // key is an unexported type for keys defined in this package.
14 // This prevents collisions with keys defined in other packages.
15 type key int
16
17 const (
18         // reqIDKey is the key for request IDs in Contexts.  It is
19         // unexported; clients use NewContext and FromContext
20         // instead of using this key directly.
21         reqIDKey key = iota
22         // subReqIDKey is the key for sub-request IDs in Contexts.  It is
23         // unexported; clients use NewSubContext and FromSubContext
24         // instead of using this key directly.
25         subReqIDKey
26         // coreIDKey is the key for Chain-Core-ID request header field values.
27         // It is only for statistics; don't use it for authorization.
28         coreIDKey
29         // pathKey is the key for the request path being handled.
30         pathKey
31 )
32
33 // New generates a random request ID.
34 func New() string {
35         // Given n IDs of length b bits, the probability that there will be a collision is bounded by
36         // the number of pairs of IDs multiplied by the probability that any pair might collide:
37         // p ≤ n(n - 1)/2 * 1/(2^b)
38         //
39         // We assume an upper bound of 1000 req/sec, which means that in a week there will be
40         // n = 1000 * 604800 requests. If l = 10, b = 8*10, then p ≤ 1.512e-7, which is a suitably
41         // low probability.
42         l := 10
43         b := make([]byte, l)
44         _, err := rand.Read(b)
45         if err != nil {
46                 log.WithField("error", err).Info("error making reqID")
47         }
48         return hex.EncodeToString(b)
49 }
50
51 // NewContext returns a new Context that carries reqid.
52 // It also adds a log prefix to print the request ID using
53 // package bytom/log.
54 func NewContext(ctx context.Context, reqid string) context.Context {
55         ctx = context.WithValue(ctx, reqIDKey, reqid)
56         return ctx
57 }
58
59 // FromContext returns the request ID stored in ctx,
60 // if any.
61 func FromContext(ctx context.Context) string {
62         reqID, _ := ctx.Value(reqIDKey).(string)
63         return reqID
64 }
65
66 // CoreIDFromContext returns the Chain-Core-ID stored in ctx,
67 // or the empty string.
68 func CoreIDFromContext(ctx context.Context) string {
69         id, _ := ctx.Value(coreIDKey).(string)
70         return id
71 }
72
73 // PathFromContext returns the HTTP path stored in ctx,
74 // or the empty string.
75 func PathFromContext(ctx context.Context) string {
76         path, _ := ctx.Value(pathKey).(string)
77         return path
78 }
79
80 func NewSubContext(ctx context.Context, reqid string) context.Context {
81         ctx = context.WithValue(ctx, subReqIDKey, reqid)
82         return ctx
83 }
84
85 // FromSubContext returns the sub-request ID stored in ctx,
86 // if any.
87 func FromSubContext(ctx context.Context) string {
88         subReqID, _ := ctx.Value(subReqIDKey).(string)
89         return subReqID
90 }
91
92 func Handler(handler http.Handler) http.Handler {
93         return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
94         })
95 }