File: requestid.go

package info (click to toggle)
golang-github-smallstep-crypto 0.57.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 3,284 kB
  • sloc: sh: 53; makefile: 36
file content (52 lines) | stat: -rw-r--r-- 1,491 bytes parent folder | download | duplicates (2)
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
package attestation

import (
	"context"
	"net/http"

	"go.step.sm/crypto/randutil"
)

type requestIDContextKey struct{}

// NewRequestIDContext returns a new context with the given request ID added to the
// context.
func NewRequestIDContext(ctx context.Context, requestID string) context.Context {
	return context.WithValue(ctx, requestIDContextKey{}, requestID)
}

// RequestIDFromContext returns the request ID from the context if it exists.
// and is not empty.
func RequestIDFromContext(ctx context.Context) (string, bool) {
	v, ok := ctx.Value(requestIDContextKey{}).(string)
	return v, ok && v != ""
}

// requestIDHeader is the header name used for propagating request IDs from
// the attestation client to the attestation CA and back again.
const requestIDHeader = "X-Request-Id"

// newRequestID generates a new random UUIDv4 request ID. If it fails,
// the request ID will be the empty string.
func newRequestID() string {
	requestID, err := randutil.UUIDv4()
	if err != nil {
		return ""
	}

	return requestID
}

// enforceRequestID checks if the X-Request-Id HTTP header is filled. If it's
// empty, the context is searched for a request ID. If that's also empty, a new
// request ID is generated.
func enforceRequestID(r *http.Request) {
	if requestID := r.Header.Get(requestIDHeader); requestID == "" {
		if reqID, ok := RequestIDFromContext(r.Context()); ok {
			requestID = reqID
		} else {
			requestID = newRequestID()
		}
		r.Header.Set(requestIDHeader, requestID)
	}
}