v2 / vlib / veb / request_id / request_id.v
74 lines · 63 sloc · 1.65 KB · ab2eb0016ce83f20184fe1e3cf6f727cf17c7272
Raw
1module request_id
2
3import veb
4import rand
5
6@[params]
7pub struct Config {
8pub:
9 // Next defines a function to skip this middleware when returned true.
10 next ?fn (ctx &veb.Context) bool
11 // Generator defines a function to generate the unique identifier.
12 generator fn () string = rand.uuid_v4
13 // Header is the header key where to get/set the unique request ID.
14 header string = 'X-Request-ID'
15 // Allow empty sets whether to allow empty request IDs
16 allow_empty bool
17 // Force determines whether to always generate a new ID even if one exists
18 force bool
19}
20
21@[noinit]
22pub struct RequestIdContext {
23pub mut:
24 request_id_config Config
25 request_id_exempt bool
26 request_id string
27}
28
29// get_request_id returns the current request ID
30pub fn (ctx &RequestIdContext) get_request_id() string {
31 return ctx.request_id
32}
33
34// middleware returns a handler that you can use with veb's middleware
35pub fn middleware[T](config Config) veb.MiddlewareOptions[T] {
36 return veb.MiddlewareOptions[T]{
37 after: false
38 handler: fn [config] [T](mut ctx T) bool {
39 if ctx.request_id_exempt {
40 return true
41 }
42
43 // Don't execute middleware if Next returns true.
44 if next := config.next {
45 if next(ctx) {
46 return true
47 }
48 }
49
50 // Get existing ID from request
51 mut rid := if !config.force {
52 ctx.get_custom_header(config.header) or { '' }
53 } else {
54 ''
55 }
56
57 // Generate new ID if needed
58 if rid == '' || config.force {
59 rid = config.generator()
60 }
61
62 // Set ID to response header if we have one
63 if rid != '' {
64 ctx.set_custom_header(config.header, rid)
65 ctx.request_id = rid
66 }
67
68 // Store config
69 ctx.request_id_config = config
70
71 return true
72 }
73 }
74}
75