@@ -19,12 +19,11 @@ import (
1919// data collection and sends it to the Signal Sciences Agent for
2020// inspection.
2121type Module struct {
22- config * ModuleConfig
23- handler http.Handler
24- inspector Inspector
25- inspInit InspectorInitFunc
26- inspFini InspectorFiniFunc
27- headerExtractor HeaderExtractorFunc
22+ config * ModuleConfig
23+ handler http.Handler
24+ inspector Inspector
25+ inspInit InspectorInitFunc
26+ inspFini InspectorFiniFunc
2827}
2928
3029// NewModule wraps an existing http.Handler with one that extracts data and
@@ -39,12 +38,11 @@ func NewModule(h http.Handler, options ...ModuleConfigOption) (*Module, error) {
3938
4039 // The following are the defaults, overridden by passing in functional options
4140 m := Module {
42- handler : h ,
43- config : config ,
44- inspector : config .Inspector (),
45- inspInit : config .InspectorInit (),
46- inspFini : config .InspectorFini (),
47- headerExtractor : config .HeaderExtractor (),
41+ handler : h ,
42+ config : config ,
43+ inspector : config .Inspector (),
44+ inspInit : config .InspectorInit (),
45+ inspFini : config .InspectorFini (),
4846 }
4947
5048 // By default, use an RPC based inspector if not configured externally
@@ -169,8 +167,7 @@ func (m *Module) ServeHTTP(w http.ResponseWriter, req *http.Request) {
169167 if m .config .Debug () {
170168 log .Printf ("DEBUG: calling 'RPC.PostRequest' due to anomaly: method=%s host=%s url=%s code=%d size=%d duration=%s" , req .Method , req .Host , req .URL , code , size , duration )
171169 }
172- inspin := NewRPCMsgIn (req , nil , code , size , duration , m .config .ModuleIdentifier (), m .config .ServerIdentifier ())
173- m .extractHeaders (req , inspin )
170+ inspin := NewRPCMsgIn (m .config , req , nil , code , size , duration )
174171 inspin .WAFResponse = wafresponse
175172 inspin .HeadersOut = convertHeaders (rw .Header ())
176173
@@ -225,8 +222,7 @@ func (m *Module) inspectorPreRequest(req *http.Request) (inspin2 RPCMsgIn2, out
225222 req .Body = ioutil .NopCloser (bytes .NewBuffer (reqbody ))
226223 }
227224
228- inspin := NewRPCMsgInWithModuleConfig (m .config , req , reqbody )
229- m .extractHeaders (req , inspin )
225+ inspin := NewRPCMsgIn (m .config , req , reqbody , - 1 , - 1 , 0 )
230226
231227 if m .config .Debug () {
232228 log .Printf ("DEBUG: Making PreRequest call to inspector: %s %s" , inspin .Method , inspin .URI )
@@ -276,20 +272,6 @@ func (m *Module) inspectorPreRequest(req *http.Request) (inspin2 RPCMsgIn2, out
276272 return
277273}
278274
279- func (m * Module ) extractHeaders (req * http.Request , inspin * RPCMsgIn ) {
280- // If the user supplied a custom header extractor, use it to unpack the
281- // headers. If there no custom header extractor or it returns an error,
282- // fallback to the native headers on the request.
283- if m .headerExtractor != nil {
284- hin , err := m .headerExtractor (req )
285- if err == nil {
286- inspin .HeadersIn = convertHeaders (hin )
287- } else if m .config .Debug () {
288- log .Printf ("DEBUG: Error extracting custom headers, using native headers: %s" , err )
289- }
290- }
291- }
292-
293275// inspectorPostRequest makes a postrequest call to the inspector
294276func (m * Module ) inspectorPostRequest (inspin * RPCMsgIn ) error {
295277 // Create message to agent from the input request
@@ -329,93 +311,42 @@ func (m *Module) inspectorUpdateRequest(inspin RPCMsgIn2) error {
329311// NewRPCMsgIn creates a message from a go http.Request object
330312// End-users of the golang module never need to use this
331313// directly and it is only exposed for performance testing
332- func NewRPCMsgIn (r * http.Request , postbody []byte , code int , size int64 , dur time.Duration , module , server string ) * RPCMsgIn {
314+ func NewRPCMsgIn (mcfg * ModuleConfig , r * http.Request , postbody []byte , code int , size int64 , dur time.Duration ) * RPCMsgIn {
333315 now := time .Now ()
334316
335- // assemble a message to send to inspector
336- tlsProtocol := ""
337- tlsCipher := ""
338- scheme := "http"
339- if r .TLS != nil {
340- // convert golang/spec integers into something human readable
341- scheme = "https"
342- tlsProtocol = tlstext .Version (r .TLS .Version )
343- tlsCipher = tlstext .CipherSuite (r .TLS .CipherSuite )
344- }
345-
346- // golang removes Host header from req.Header map and
347- // promotes it to r.Host field. Add it back as the first header.
348- hin := convertHeaders (r .Header )
349- if len (r .Host ) > 0 {
350- hin = append ([][2 ]string {{"Host" , r .Host }}, hin ... )
351- }
352-
353- return & RPCMsgIn {
354- ModuleVersion : module ,
355- ServerVersion : server ,
317+ msgIn := RPCMsgIn {
318+ ModuleVersion : mcfg .ModuleIdentifier (),
319+ ServerVersion : mcfg .ServerIdentifier (),
320+ ServerFlavor : mcfg .ServerFlavor (),
356321 ServerName : r .Host ,
357322 Timestamp : now .Unix (),
358- NowMillis : now .UnixNano () / 1e6 ,
323+ NowMillis : now .UnixMilli () ,
359324 RemoteAddr : stripPort (r .RemoteAddr ),
360325 Method : r .Method ,
361- Scheme : scheme ,
362326 URI : r .RequestURI ,
363327 Protocol : r .Proto ,
364- TLSProtocol : tlsProtocol ,
365- TLSCipher : tlsCipher ,
366328 ResponseCode : int32 (code ),
367- ResponseMillis : int64 ( dur / time . Millisecond ),
329+ ResponseMillis : dur . Milliseconds ( ),
368330 ResponseSize : size ,
369331 PostBody : string (postbody ),
370- HeadersIn : hin ,
371332 }
372- }
373-
374- // NewRPCMsgInWithModuleConfig creates a message from a ModuleConfig object
375- // End-users of the golang module never need to use this
376- // directly and it is only exposed for performance testing
377- func NewRPCMsgInWithModuleConfig (mcfg * ModuleConfig , r * http.Request , postbody []byte ) * RPCMsgIn {
378-
379- now := time .Now ()
380333
381- // assemble a message to send to inspector
382- tlsProtocol := ""
383- tlsCipher := ""
384- scheme := "http"
385334 if r .TLS != nil {
386335 // convert golang/spec integers into something human readable
387- scheme = "https"
388- tlsProtocol = tlstext .Version (r .TLS .Version )
389- tlsCipher = tlstext .CipherSuite (r .TLS .CipherSuite )
336+ msgIn .Scheme = "https"
337+ msgIn .TLSProtocol = tlstext .Version (r .TLS .Version )
338+ msgIn .TLSCipher = tlstext .CipherSuite (r .TLS .CipherSuite )
339+ } else {
340+ msgIn .Scheme = "http"
390341 }
391342
392- // golang removes Host header from req.Header map and
393- // promotes it to r.Host field. Add it back as the first header.
394- hin := convertHeaders (r .Header )
395- if len (r .Host ) > 0 {
396- hin = append ([][2 ]string {{"Host" , r .Host }}, hin ... )
343+ if hdrs := mcfg .RawHeaderExtractor (); hdrs != nil {
344+ msgIn .HeadersIn = hdrs (r )
397345 }
398-
399- return & RPCMsgIn {
400- ModuleVersion : mcfg .ModuleIdentifier (),
401- ServerVersion : mcfg .ServerIdentifier (),
402- ServerFlavor : mcfg .ServerFlavor (),
403- ServerName : r .Host ,
404- Timestamp : now .Unix (),
405- NowMillis : now .UnixNano () / 1e6 ,
406- RemoteAddr : stripPort (r .RemoteAddr ),
407- Method : r .Method ,
408- Scheme : scheme ,
409- URI : r .RequestURI ,
410- Protocol : r .Proto ,
411- TLSProtocol : tlsProtocol ,
412- TLSCipher : tlsCipher ,
413- ResponseCode : - 1 ,
414- ResponseMillis : 0 ,
415- ResponseSize : - 1 ,
416- PostBody : string (postbody ),
417- HeadersIn : hin ,
346+ if msgIn .HeadersIn == nil {
347+ msgIn .HeadersIn = requestHeader (r )
418348 }
349+ return & msgIn
419350}
420351
421352// stripPort removes any port from an address (e.g., the client port from the RemoteAddr)
@@ -505,6 +436,22 @@ func inspectableContentType(s string) bool {
505436 return false
506437}
507438
439+ // requestHeader returns request headers with host header
440+ func requestHeader (r * http.Request ) [][2 ]string {
441+ out := make ([][2 ]string , 0 , len (r .Header )+ 1 )
442+ // golang removes Host header from req.Header map and
443+ // promotes it to r.Host field. Add it back as the first header.
444+ if len (r .Host ) > 0 {
445+ out = append (out , [2 ]string {"Host" , r .Host })
446+ }
447+ for key , values := range r .Header {
448+ for _ , value := range values {
449+ out = append (out , [2 ]string {key , value })
450+ }
451+ }
452+ return out
453+ }
454+
508455// converts a http.Header map to a [][2]string
509456func convertHeaders (h http.Header ) [][2 ]string {
510457 // get headers
0 commit comments