11package com .retailsvc .http .internal ;
22
3+ import com .retailsvc .http .AfterResponseHook ;
4+ import com .retailsvc .http .ExceptionHandler ;
35import com .retailsvc .http .MethodNotAllowedException ;
46import com .retailsvc .http .NotFoundException ;
57import com .retailsvc .http .Request ;
8+ import com .retailsvc .http .Response ;
69import com .retailsvc .http .TypeMapper ;
710import com .retailsvc .http .ValidationException ;
811import com .retailsvc .http .spec .HttpMethod ;
1720import com .sun .net .httpserver .HttpExchange ;
1821import java .io .IOException ;
1922import java .util .HashMap ;
23+ import java .util .List ;
2024import java .util .Locale ;
2125import java .util .Map ;
2226import java .util .Optional ;
27+ import org .slf4j .Logger ;
28+ import org .slf4j .LoggerFactory ;
2329
2430public final class RequestPreparationFilter extends Filter {
2531
32+ private static final Logger LOG = LoggerFactory .getLogger (RequestPreparationFilter .class );
2633 private static final String BODY_POINTER = "/body" ;
2734
2835 private final Spec spec ;
2936 private final Router router ;
3037 private final Validator validator ;
3138 private final Map <String , TypeMapper > bodyMappers ;
39+ private final ExceptionHandler exceptionHandler ;
40+ private final ResponseRenderer renderer ;
41+ private final List <AfterResponseHook > afterHooks ;
3242
43+ @ SuppressWarnings ("java:S107" )
3344 public RequestPreparationFilter (
34- Spec spec , Router router , Validator validator , Map <String , TypeMapper > bodyMappers ) {
45+ Spec spec ,
46+ Router router ,
47+ Validator validator ,
48+ Map <String , TypeMapper > bodyMappers ,
49+ ExceptionHandler exceptionHandler ,
50+ ResponseRenderer renderer ,
51+ List <AfterResponseHook > afterHooks ) {
3552 this .spec = spec ;
3653 this .router = router ;
3754 this .validator = validator ;
3855 this .bodyMappers = Map .copyOf (bodyMappers );
56+ this .exceptionHandler = exceptionHandler ;
57+ this .renderer = renderer ;
58+ this .afterHooks = List .copyOf (afterHooks );
3959 }
4060
4161 @ Override
@@ -45,6 +65,31 @@ public String description() {
4565
4666 @ Override
4767 public void doFilter (HttpExchange exchange , Chain chain ) throws IOException {
68+ Request request ;
69+ try {
70+ request = buildRequest (exchange );
71+ } catch (RuntimeException | IOException t ) {
72+ Response response = exceptionHandler .handle (t );
73+ renderer .render (exchange , response );
74+ return ;
75+ }
76+
77+ try {
78+ ScopedValue .where (DispatchHandler .CURRENT , request )
79+ .call (
80+ () -> {
81+ runInnerChain (exchange , chain );
82+ fireAfterHooks (exchange , request );
83+ return null ;
84+ });
85+ } catch (IOException | RuntimeException e ) {
86+ throw e ;
87+ } catch (Exception e ) {
88+ throw new IOException (e );
89+ }
90+ }
91+
92+ private Request buildRequest (HttpExchange exchange ) throws IOException {
4893 byte [] body = exchange .getRequestBody ().readAllBytes ();
4994
5095 HttpMethod method = HttpMethod .parse (exchange .getRequestMethod ());
@@ -65,32 +110,31 @@ public void doFilter(HttpExchange exchange, Chain chain) throws IOException {
65110 ParsedBody parsedBody = validateAndParseBody (exchange , op , body );
66111
67112 var headers = exchange .getRequestHeaders ();
68- Request request =
69- new Request (
70- body ,
71- parsedBody .value (),
72- parsedBody . mapper (),
73- op . operationId (),
74- match . pathParameters (),
75- exchange . getRequestURI (). getRawQuery () ,
76- headers :: getFirst ,
77- Map . of (),
78- method );
113+ return new Request (
114+ body ,
115+ parsedBody . value () ,
116+ parsedBody .mapper (),
117+ op . operationId (),
118+ match . pathParameters (),
119+ exchange . getRequestURI (). getRawQuery (),
120+ headers :: getFirst ,
121+ Map . of () ,
122+ method );
123+ }
79124
125+ private void runInnerChain (HttpExchange exchange , Chain chain ) throws IOException {
80126 try {
81- ScopedValue .where (DispatchHandler .CURRENT , request )
82- .call (
83- () -> {
84- chain .doFilter (exchange );
85- return null ;
86- });
87- } catch (IOException | RuntimeException e ) {
88- throw e ;
89- } catch (Exception e ) {
90- throw new IOException (e );
127+ chain .doFilter (exchange );
128+ } catch (RuntimeException | IOException t ) {
129+ Response response = exceptionHandler .handle (t );
130+ renderer .render (exchange , response );
91131 }
92132 }
93133
134+ private void fireAfterHooks (HttpExchange exchange , Request request ) {
135+ // implemented in Task 5
136+ }
137+
94138 private String stripBasePath (String path ) {
95139 String base = spec .basePath ();
96140 if (base == null || base .isEmpty () || base .equals ("/" )) {
0 commit comments