OSDN Git Service

restore Tx back to Tx pool when chain is reorganized (#254)
[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         logModule = "reqid"
32 )
33
34 // New generates a random request ID.
35 func New() string {
36         // Given n IDs of length b bits, the probability that there will be a collision is bounded by
37         // the number of pairs of IDs multiplied by the probability that any pair might collide:
38         // p ≤ n(n - 1)/2 * 1/(2^b)
39         //
40         // We assume an upper bound of 1000 req/sec, which means that in a week there will be
41         // n = 1000 * 604800 requests. If l = 10, b = 8*10, then p ≤ 1.512e-7, which is a suitably
42         // low probability.
43         l := 10
44         b := make([]byte, l)
45         _, err := rand.Read(b)
46         if err != nil {
47                 log.WithFields(log.Fields{"module": logModule, "error": err}).Info("error making reqID")
48         }
49         return hex.EncodeToString(b)
50 }
51
52 // NewContext returns a new Context that carries reqid.
53 // It also adds a log prefix to print the request ID using
54 // package bytom/log.
55 func NewContext(ctx context.Context, reqid string) context.Context {
56         ctx = context.WithValue(ctx, reqIDKey, reqid)
57         return ctx
58 }
59
60 // FromContext returns the request ID stored in ctx,
61 // if any.
62 func FromContext(ctx context.Context) string {
63         reqID, _ := ctx.Value(reqIDKey).(string)
64         return reqID
65 }
66
67 // CoreIDFromContext returns the Chain-Core-ID stored in ctx,
68 // or the empty string.
69 func CoreIDFromContext(ctx context.Context) string {
70         id, _ := ctx.Value(coreIDKey).(string)
71         return id
72 }
73
74 // PathFromContext returns the HTTP path stored in ctx,
75 // or the empty string.
76 func PathFromContext(ctx context.Context) string {
77         path, _ := ctx.Value(pathKey).(string)
78         return path
79 }
80
81 func NewSubContext(ctx context.Context, reqid string) context.Context {
82         ctx = context.WithValue(ctx, subReqIDKey, reqid)
83         return ctx
84 }
85
86 // FromSubContext returns the sub-request ID stored in ctx,
87 // if any.
88 func FromSubContext(ctx context.Context) string {
89         subReqID, _ := ctx.Value(subReqIDKey).(string)
90         return subReqID
91 }
92
93 func Handler(handler http.Handler) http.Handler {
94         return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
95         })
96 }