55namespace WebProject \PhpOpenApiMockServer \Middleware \MockMiddleware \Request ;
66
77use cebe \openapi \spec \OpenApi ;
8- use WebProject \PhpOpenApiMockServer \Middleware \MockMiddleware \Exception \RoutingException ;
9- use WebProject \PhpOpenApiMockServer \Middleware \MockMiddleware \Exception \SecurityException ;
10- use WebProject \PhpOpenApiMockServer \Middleware \MockMiddleware \Exception \ValidationException ;
11- use WebProject \PhpOpenApiMockServer \Middleware \MockMiddleware \Response \ResponseFaker ;
12- use Exception ;
13- use InvalidArgumentException ;
148use League \OpenAPIValidation \PSR7 \Exception \NoOperation ;
159use League \OpenAPIValidation \PSR7 \Exception \NoPath ;
1610use League \OpenAPIValidation \PSR7 \Exception \NoResponseCode ;
1711use League \OpenAPIValidation \PSR7 \Exception \Validation \InvalidSecurity ;
1812use League \OpenAPIValidation \PSR7 \Exception \ValidationFailed ;
1913use League \OpenAPIValidation \PSR7 \OperationAddress ;
14+ use League \OpenAPIValidation \PSR7 \SpecFinder ;
2015use Psr \Http \Message \ResponseInterface ;
2116use Throwable ;
17+ use WebProject \PhpOpenApiMockServer \Middleware \MockMiddleware \Exception \RoutingException ;
18+ use WebProject \PhpOpenApiMockServer \Middleware \MockMiddleware \Exception \SecurityException ;
19+ use WebProject \PhpOpenApiMockServer \Middleware \MockMiddleware \Exception \ValidationException ;
2220use WebProject \PhpOpenApiMockServer \Middleware \MockMiddleware \Faker \Exception \NoPath as FakerNoPath ;
21+ use WebProject \PhpOpenApiMockServer \Middleware \MockMiddleware \Response \ResponseFaker ;
22+
23+ use function array_keys ;
24+ use function preg_match ;
25+ use function sort ;
26+
27+ use InvalidArgumentException ;
2328
2429class RequestHandler
2530{
@@ -39,7 +44,13 @@ public function handleValidRequest(
3944 ?string $ statusCode = null ,
4045 ?string $ exampleName = null
4146 ): ResponseInterface {
42- return $ this ->responseFaker ->mock ($ openApi , $ operationAddress , $ statusCode ?? ['200 ' , '201 ' ], $ acceptedContentTypes , $ exampleName );
47+ return $ this ->responseFaker ->mock (
48+ $ openApi ,
49+ $ operationAddress ,
50+ $ statusCode ?? $ this ->getSuccessStatusCodes ($ openApi , $ operationAddress ),
51+ $ acceptedContentTypes ,
52+ $ exampleName
53+ );
4354 }
4455
4556 /**
@@ -133,4 +144,45 @@ public function handleValidationFailedRequest(
133144 return $ this ->responseFaker ->handleException (ValidationException::forUnprocessableEntity ($ throwable ), $ acceptedContentTypes [0 ] ?? 'application/json ' );
134145 }
135146 }
147+
148+ /**
149+ * Extract all 2xx status codes defined in the spec for the given operation,
150+ * sorted ascending. Falls back to ['200', '201'] if none are found.
151+ *
152+ * @return list<string>
153+ */
154+ private function getSuccessStatusCodes (OpenApi $ openApi , OperationAddress $ operationAddress ): array
155+ {
156+ try {
157+ $ operation = (new SpecFinder ($ openApi ))
158+ ->findOperationSpec ($ operationAddress );
159+ } catch (Throwable ) {
160+ return ['200 ' , '201 ' ];
161+ }
162+
163+ if ($ operation ->responses === null ) {
164+ return ['200 ' , '201 ' ];
165+ }
166+
167+ $ codes = [];
168+ foreach (array_keys ($ operation ->responses ->getResponses ()) as $ code ) {
169+ $ code = (string ) $ code ;
170+ if (preg_match ('/^2\d{2}$/ ' , $ code ) === 1 ) {
171+ $ codes [] = $ code ;
172+ }
173+ }
174+
175+ sort ($ codes );
176+
177+ if ($ codes === []) {
178+ // No 2xx codes defined, check for 'default' response
179+ if ($ operation ->responses ->hasResponse ('default ' )) {
180+ return ['default ' ];
181+ }
182+
183+ return ['200 ' , '201 ' ];
184+ }
185+
186+ return $ codes ;
187+ }
136188}
0 commit comments