@@ -2,11 +2,9 @@ import { Ajv } from 'ajv';
2
2
import { createRequestAjv } from '../framework/ajv' ;
3
3
import {
4
4
ContentType ,
5
- validationError ,
6
5
ajvErrorsToValidatorError ,
7
6
augmentAjvErrors ,
8
7
} from './util' ;
9
- import ono from 'ono' ;
10
8
import { NextFunction , RequestHandler , Response } from 'express' ;
11
9
import {
12
10
ValidationSchema ,
@@ -15,6 +13,9 @@ import {
15
13
RequestValidatorOptions ,
16
14
ValidateRequestOpts ,
17
15
OpenApiRequestMetadata ,
16
+ NotFound ,
17
+ MethodNotAllowed ,
18
+ BadRequest ,
18
19
} from '../framework/types' ;
19
20
import { BodySchemaParser } from './parsers/body.parse' ;
20
21
import { ParametersSchemaParser } from './parsers/schema.parse' ;
@@ -59,12 +60,18 @@ export class RequestValidator {
59
60
const openapi = < OpenApiRequestMetadata > req . openapi ;
60
61
const path = openapi . expressRoute ;
61
62
if ( ! path ) {
62
- throw validationError ( 404 , req . path , 'not found' ) ;
63
+ throw new NotFound ( {
64
+ path : req . path ,
65
+ message : 'not found' ,
66
+ } ) ;
63
67
}
64
68
65
69
const reqSchema = openapi . schema ;
66
70
if ( ! reqSchema ) {
67
- throw validationError ( 405 , req . path , `${ req . method } method not allowed` ) ;
71
+ throw new MethodNotAllowed ( {
72
+ path : req . path ,
73
+ message : `${ req . method } method not allowed` ,
74
+ } ) ;
68
75
}
69
76
70
77
// cache middleware by combining method, path, and contentType
@@ -93,9 +100,13 @@ export class RequestValidator {
93
100
const body = bodySchemaParser . parse ( path , reqSchema , contentType ) ;
94
101
95
102
const isBodyBinary = body ?. [ 'format' ] === 'binary' ;
96
- const properties : ValidationSchema = { ...parameters , body : isBodyBinary ? { } : body } ;
103
+ const properties : ValidationSchema = {
104
+ ...parameters ,
105
+ body : isBodyBinary ? { } : body ,
106
+ } ;
97
107
// TODO throw 400 if missing a required binary body
98
- const required = ( < SchemaObject > body ) . required && ! isBodyBinary ? [ 'body' ] : [ ] ;
108
+ const required =
109
+ ( < SchemaObject > body ) . required && ! isBodyBinary ? [ 'body' ] : [ ] ;
99
110
// $schema: "http://json-schema.org/draft-04/schema#",
100
111
const schema = {
101
112
required : [ 'query' , 'headers' , 'params' ] . concat ( required ) ,
@@ -112,7 +123,12 @@ export class RequestValidator {
112
123
req . params = openapi . pathParams ?? req . params ;
113
124
}
114
125
115
- const mutator = new RequestParameterMutator ( this . ajv , apiDoc , path , properties ) ;
126
+ const mutator = new RequestParameterMutator (
127
+ this . ajv ,
128
+ apiDoc ,
129
+ path ,
130
+ properties ,
131
+ ) ;
116
132
117
133
mutator . modifyRequest ( req ) ;
118
134
@@ -138,33 +154,36 @@ export class RequestValidator {
138
154
const errors = augmentAjvErrors ( [ ...( validator . errors ?? [ ] ) ] ) ;
139
155
const err = ajvErrorsToValidatorError ( 400 , errors ) ;
140
156
const message = this . ajv . errorsText ( errors , { dataVar : 'request' } ) ;
141
- throw ono ( err , message ) ;
157
+ const error : BadRequest = new BadRequest ( {
158
+ path : req . path ,
159
+ message : message ,
160
+ } ) ;
161
+ error . errors = err . errors ;
162
+ throw error ;
142
163
}
143
164
} ;
144
165
}
145
166
146
167
private processQueryParam ( query , schema , whiteList : string [ ] = [ ] ) {
147
168
if ( ! schema . properties ) return ;
148
169
const knownQueryParams = new Set ( Object . keys ( schema . properties ) ) ;
149
- whiteList . forEach ( item => knownQueryParams . add ( item ) ) ;
170
+ whiteList . forEach ( ( item ) => knownQueryParams . add ( item ) ) ;
150
171
const queryParams = Object . keys ( query ) ;
151
172
const allowedEmpty = schema . allowEmptyValue ;
152
173
for ( const q of queryParams ) {
153
174
if (
154
175
! this . requestOpts . allowUnknownQueryParameters &&
155
176
! knownQueryParams . has ( q )
156
177
) {
157
- throw validationError (
158
- 400 ,
159
- `.query.${ q } ` ,
160
- `Unknown query parameter '${ q } '` ,
161
- ) ;
178
+ throw new BadRequest ( {
179
+ path : `.query.${ q } ` ,
180
+ message : `Unknown query parameter '${ q } '` ,
181
+ } ) ;
162
182
} else if ( ! allowedEmpty ?. has ( q ) && ( query [ q ] === '' || null ) ) {
163
- throw validationError (
164
- 400 ,
165
- `.query.${ q } ` ,
166
- `Empty value found for query parameter '${ q } '` ,
167
- ) ;
183
+ throw new BadRequest ( {
184
+ path : `.query.${ q } ` ,
185
+ message : `Empty value found for query parameter '${ q } '` ,
186
+ } ) ;
168
187
}
169
188
}
170
189
}
@@ -201,12 +220,12 @@ class Security {
201
220
) : string [ ] {
202
221
return usedSecuritySchema && securitySchema
203
222
? usedSecuritySchema
204
- . filter ( obj => Object . entries ( obj ) . length !== 0 )
205
- . map ( sec => {
223
+ . filter ( ( obj ) => Object . entries ( obj ) . length !== 0 )
224
+ . map ( ( sec ) => {
206
225
const securityKey = Object . keys ( sec ) [ 0 ] ;
207
226
return < SecuritySchemeObject > securitySchema [ securityKey ] ;
208
227
} )
209
- . filter ( sec => sec ?. type === 'apiKey' && sec ?. in == 'query' )
228
+ . filter ( ( sec ) => sec ?. type === 'apiKey' && sec ?. in == 'query' )
210
229
. map ( ( sec : ApiKeySecurityScheme ) => sec . name )
211
230
: [ ] ;
212
231
}
0 commit comments