@@ -47,10 +47,19 @@ router.post(
47
47
const validEvents : any [ ] = [ ]
48
48
const validationErrors : any [ ] = [ ]
49
49
50
+ // We use a LRU cache & a hash of the request IP + error message
51
+ // to prevent sending multiple validation errors per user that can spam requests to Hydro
52
+ const getValidationErrorHash = ( validateErrors : ErrorObject [ ] ) =>
53
+ `${ req . ip } :${ ( validateErrors || [ ] )
54
+ . map (
55
+ ( error : ErrorObject ) => error . message + error . instancePath + JSON . stringify ( error . params ) ,
56
+ )
57
+ . join ( ':' ) } `
58
+
50
59
for ( const eventBody of eventsToProcess ) {
51
60
try {
61
+ // Skip event if it doesn't have a type or if the type is not in the allowed types
52
62
if ( ! eventBody . type || ! allowedTypes . has ( eventBody . type ) ) {
53
- validationErrors . push ( { event : eventBody , error : 'Invalid type' } )
54
63
continue
55
64
}
56
65
const type : EventType = eventBody . type
@@ -71,18 +80,7 @@ router.post(
71
80
}
72
81
const validate = validators [ type ]
73
82
if ( ! validate ( body ) ) {
74
- validationErrors . push ( {
75
- event : body ,
76
- error : validate . errors || [ ] ,
77
- } )
78
- // This protects so we don't bother sending the same validation
79
- // error, per user, more than once (per time interval).
80
- // This helps if we're bombarded with junk bot traffic. So it
81
- // protects our Hydro instance from being overloaded with things
82
- // that aren't helping anybody.
83
- const hash = `${ req . ip } :${ ( validate . errors || [ ] )
84
- . map ( ( error : ErrorObject ) => error . message + error . instancePath )
85
- . join ( ':' ) } `
83
+ const hash = getValidationErrorHash ( validate . errors || [ ] )
86
84
if ( ! sentValidationErrors . has ( hash ) ) {
87
85
sentValidationErrors . set ( hash , true )
88
86
formatErrors ( validate . errors || [ ] , body ) . map ( ( error ) => {
0 commit comments