@@ -81,6 +81,9 @@ type Request struct {
81
81
// TLSInfo collects TLS metadata for incoming requests received over HTTPS.
82
82
TLSInfo TLSInfo
83
83
84
+ // Fingerprint collects fingerprint metadata for incoming requests
85
+ fingerprint * Fingerprint
86
+
84
87
// SendPollInterval determines how often the Send method will check for
85
88
// completed requests. While polling, the Go runtime is suspended, and all
86
89
// user code stops execution. A shorter interval will make Send more
@@ -111,6 +114,9 @@ type Request struct {
111
114
// discarded.
112
115
ManualFramingMode bool
113
116
117
+ // RequestID is the current Fastly request ID
118
+ RequestID string
119
+
114
120
sent bool // a request may only be sent once
115
121
116
122
abi struct {
@@ -165,6 +171,11 @@ func newClientRequest(abiReq *fastly.HTTPRequest, abiReqBody *fastly.HTTPBody) (
165
171
return nil , fmt .Errorf ("get protocol version: %w" , err )
166
172
}
167
173
174
+ reqID , err := abiReq .DownstreamRequestID ()
175
+ if err != nil {
176
+ return nil , fmt .Errorf ("get request id: %w" , err )
177
+ }
178
+
168
179
header := NewHeader ()
169
180
keys := abiReq .GetHeaderNames (RequestLimits .maxHeaderNameLen )
170
181
for keys .Next () {
@@ -214,6 +225,23 @@ func newClientRequest(abiReq *fastly.HTTPRequest, abiReqBody *fastly.HTTPBody) (
214
225
if err != nil {
215
226
return nil , fmt .Errorf ("get TLS JA3 MD5: %w" , err )
216
227
}
228
+
229
+ tlsInfo .JA4 , err = abiReq .DownstreamTLSJA4 ()
230
+ if err != nil {
231
+ return nil , fmt .Errorf ("get TLS JA4: %w" , err )
232
+ }
233
+
234
+ tlsInfo .RawClientCertificate , err = abiReq .DownstreamTLSRawCertificate ()
235
+ if err != nil {
236
+ return nil , fmt .Errorf ("get TLS raw client certificate: %w" , err )
237
+ }
238
+
239
+ if tlsInfo .RawClientCertificate != nil {
240
+ tlsInfo .ClientCertIsVerified , err = abiReq .DownstreamTLSClientCertVerifyResult ()
241
+ if err != nil {
242
+ return nil , fmt .Errorf ("get TLS client certificate verify: %w" , err )
243
+ }
244
+ }
217
245
}
218
246
219
247
// Setting the fsthttp.Request Host field to the url.URL Host field is
@@ -231,6 +259,7 @@ func newClientRequest(abiReq *fastly.HTTPRequest, abiReqBody *fastly.HTTPBody) (
231
259
RemoteAddr : remoteAddr .String (),
232
260
ServerAddr : serverAddr .String (),
233
261
TLSInfo : tlsInfo ,
262
+ RequestID : reqID ,
234
263
}, nil
235
264
}
236
265
@@ -342,6 +371,39 @@ func (req *Request) AddCookie(c *Cookie) {
342
371
}
343
372
}
344
373
374
+ // Fingerprint returns a fleshed-out Fingerprint object for the request.
375
+ func (req * Request ) Fingerprint () (* Fingerprint , error ) {
376
+ if req .fingerprint != nil {
377
+ return req .fingerprint , nil
378
+ }
379
+
380
+ var err error
381
+
382
+ var fingerprint Fingerprint
383
+ fingerprint .H2 , err = req .abi .req .DownstreamH2Fingerprint ()
384
+ if err != nil {
385
+ if status , ok := fastly .IsFastlyError (err ); ok && status != fastly .FastlyStatusNone {
386
+ return nil , fmt .Errorf ("get H2 fingerprint: %w" , err )
387
+ }
388
+ }
389
+
390
+ fingerprint .OH , err = req .abi .req .DownstreamOHFingerprint ()
391
+ if err != nil {
392
+ if status , ok := fastly .IsFastlyError (err ); ok && status != fastly .FastlyStatusNone {
393
+ return nil , fmt .Errorf ("get OH fingerprint: %w" , err )
394
+ }
395
+ }
396
+
397
+ fingerprint .DDOSDetected , err = req .abi .req .DownstreamDDOSDetected ()
398
+ if err != nil {
399
+ return nil , fmt .Errorf ("get ddos detected: %w" , err )
400
+ }
401
+
402
+ req .fingerprint = & fingerprint
403
+
404
+ return req .fingerprint , nil
405
+ }
406
+
345
407
// Send the request to the named backend. Requests may only be sent to
346
408
// backends that have been preconfigured in your service, regardless of
347
409
// their URL. Once sent, a request cannot be sent again.
@@ -945,6 +1007,29 @@ type TLSInfo struct {
945
1007
// JA3MD5 contains the bytes of the JA3 signature of the client TLS request.
946
1008
// See https://www.fastly.com/blog/the-state-of-tls-fingerprinting-whats-working-what-isnt-and-whats-next
947
1009
JA3MD5 []byte
1010
+
1011
+ // JA4 contains the bytes of the JA4 signature of the client TLS request.
1012
+ // See https://github.com/FoxIO-LLC/ja4/blob/main/technical_details/JA4.md
1013
+ JA4 []byte
1014
+
1015
+ // RawClientCertificate contains the bytes of the raw client certificate, if one was provided.
1016
+ RawClientCertificate []byte
1017
+
1018
+ // ClientCertIsVerified is true if the provided client certificate is valid.
1019
+ ClientCertIsVerified bool
1020
+ }
1021
+
1022
+ // Fingerprint holds various fingerprints for a request.
1023
+ type Fingerprint struct {
1024
+
1025
+ // H2 is the HTTP/2 fingerprint of a client request if available
1026
+ H2 []byte
1027
+
1028
+ // OH is a fingerprint of the client request's original headers
1029
+ OH []byte
1030
+
1031
+ // DDOSDetected is true if the request was determined to be part of a DDOS attack.
1032
+ DDOSDetected bool
948
1033
}
949
1034
950
1035
// DecompressResponseOptions control the auto decompress response behaviour.
0 commit comments