1818
1919import static org .assertj .core .api .Assertions .assertThat ;
2020
21- import java .util .stream .Stream ;
22-
23- import org .junit .jupiter .api .extension .ExtensionContext ;
2421import org .junit .jupiter .api .extension .RegisterExtension ;
2522import org .junit .jupiter .params .ParameterizedTest ;
26- import org .junit .jupiter .params .provider .Arguments ;
27- import org .junit .jupiter .params .provider .ArgumentsProvider ;
28- import org .junit .jupiter .params .provider .ArgumentsSource ;
23+ import org .junit .jupiter .params .provider .ValueSource ;
2924
30- import com .linecorp .armeria .client .BlockingWebClient ;
3125import com .linecorp .armeria .common .AggregatedHttpResponse ;
3226import com .linecorp .armeria .common .HttpResponse ;
3327import com .linecorp .armeria .common .HttpStatus ;
3428import com .linecorp .armeria .common .RequestContext ;
3529import com .linecorp .armeria .common .logging .RequestLog ;
3630import com .linecorp .armeria .server .HttpStatusException ;
3731import com .linecorp .armeria .server .ServerBuilder ;
32+ import com .linecorp .armeria .server .ServiceErrorHandler ;
3833import com .linecorp .armeria .server .annotation .ExceptionHandlerFunction ;
3934import com .linecorp .armeria .server .annotation .Get ;
4035import com .linecorp .armeria .server .annotation .ProducesText ;
4338class ContentPreviewingErrorResponseTest {
4439
4540 @ RegisterExtension
46- static final ServerExtension server = new ServerExtension () {
41+ static final ServerExtension serverWithErrorHandler = new ServerExtension () {
4742 @ Override
4843 protected void configure (ServerBuilder sb ) {
44+ configureServer (sb , true );
45+ }
46+ };
47+
48+ @ RegisterExtension
49+ static final ServerExtension serverWithoutServerErrorHandler = new ServerExtension () {
50+ @ Override
51+ protected void configure (ServerBuilder sb ) {
52+ configureServer (sb , false );
53+ }
54+ };
55+
56+ private static void configureServer (ServerBuilder sb , boolean errorHandler ) {
57+ if (errorHandler ) {
4958 sb .errorHandler ((ctx , cause ) -> {
5059 return HttpResponse .of ("errorHandler: " + cause .getMessage ());
5160 });
61+ }
5262
53- sb .service ("/aborted/http-status-exception" , (ctx , req ) ->
54- HttpResponse .ofFailure (HttpStatusException .of (HttpStatus .INTERNAL_SERVER_ERROR )));
55- sb .service ("/aborted/unexpected-exception" , (ctx , req ) ->
56- HttpResponse .ofFailure (new IllegalStateException ("Oops!" )));
63+ sb .service ("/aborted/http-status-exception" , (ctx , req ) ->
64+ HttpResponse .ofFailure (HttpStatusException .of (HttpStatus .INTERNAL_SERVER_ERROR )));
65+ sb .service ("/aborted/unexpected-exception" , (ctx , req ) ->
66+ HttpResponse .ofFailure (new IllegalStateException ("Oops!" )));
5767
58- sb .service ("/throw/http-status-exception" , (ctx , req ) -> {
59- throw HttpStatusException .of (HttpStatus .INTERNAL_SERVER_ERROR );
60- });
61- sb .service ("/throw/unexpected-exception" , (ctx , req ) -> {
62- throw new IllegalStateException ("Oops!" );
63- });
68+ sb .service ("/throw/http-status-exception" , (ctx , req ) -> {
69+ throw HttpStatusException .of (HttpStatus .INTERNAL_SERVER_ERROR );
70+ });
71+ sb .service ("/throw/unexpected-exception" , (ctx , req ) -> {
72+ throw new IllegalStateException ("Oops!" );
73+ });
6474
65- sb .annotatedService ("/annotated" , new ContentPreviewingAnnotatedService ());
75+ sb .annotatedService ("/annotated" , new ContentPreviewingAnnotatedService ());
76+ if (errorHandler ) {
6677 sb .annotatedService ("/annotatedExceptionHandler" ,
6778 new ContentPreviewingAnnotatedService (),
6879 (ExceptionHandlerFunction ) (ctx , req , cause ) -> {
6980 return HttpResponse .of ("exceptionHandler: " + cause .getMessage ());
7081 });
71-
72- sb .decorator (LoggingService .newDecorator ());
73- sb .decorator (ContentPreviewingService .newDecorator (Integer .MAX_VALUE ));
7482 }
75- };
83+
84+ final ServiceErrorHandler serviceErrorHandler = (ctx , cause ) -> {
85+ return HttpResponse .of ("serviceErrorHandler: " + cause .getMessage ());
86+ };
87+ sb .withRoute (bindingBuilder -> {
88+ if (errorHandler ) {
89+ bindingBuilder .errorHandler (serviceErrorHandler );
90+ }
91+ bindingBuilder .path ("/binding/aborted/http-status-exception" )
92+ .build ((ctx , req ) -> {
93+ return HttpResponse .ofFailure (
94+ HttpStatusException .of (HttpStatus .INTERNAL_SERVER_ERROR ));
95+ });
96+ });
97+ sb .withRoute (bindingBuilder -> {
98+ if (errorHandler ) {
99+ bindingBuilder .errorHandler (serviceErrorHandler );
100+ }
101+ bindingBuilder .path ("/binding/aborted/unexpected-exception" )
102+ .build ((ctx , req ) -> {
103+ return HttpResponse .ofFailure (new IllegalStateException ("Oops!" ));
104+ });
105+ });
106+ sb .withRoute (bindingBuilder -> {
107+ if (errorHandler ) {
108+ bindingBuilder .errorHandler (serviceErrorHandler );
109+ }
110+ bindingBuilder .path ("/binding/throw/http-status-exception" )
111+ .build ((ctx , req ) -> {
112+ throw HttpStatusException .of (HttpStatus .INTERNAL_SERVER_ERROR );
113+ });
114+ });
115+ sb .withRoute (bindingBuilder -> {
116+ if (errorHandler ) {
117+ bindingBuilder .errorHandler (serviceErrorHandler );
118+ }
119+ bindingBuilder .path ("/binding/throw/unexpected-exception" )
120+ .build ((ctx , req ) -> {
121+ throw new IllegalStateException ("Oops!" );
122+ });
123+ });
124+
125+ sb .decorator (LoggingService .newDecorator ());
126+ sb .decorator (ContentPreviewingService .newDecorator (Integer .MAX_VALUE ));
127+ }
128+
129+ @ ParameterizedTest
130+ @ ValueSource (strings = {
131+ "/aborted/http-status-exception" ,
132+ "/aborted/unexpected-exception" ,
133+ "/throw/http-status-exception" ,
134+ "/throw/unexpected-exception" ,
135+ "/annotated/aborted/http-status-exception" ,
136+ "/annotated/aborted/unexpected-exception" ,
137+ "/annotated/throw/http-status-exception" ,
138+ "/annotated/throw/unexpected-exception" ,
139+ "/binding/aborted/http-status-exception" ,
140+ "/binding/aborted/unexpected-exception" ,
141+ "/binding/throw/http-status-exception" ,
142+ "/binding/throw/unexpected-exception" ,
143+ })
144+ void shouldSetNullContentPreviewWhenAnExceptionIsRaisedAndErrorHandlerSet (String path ) throws Exception {
145+ serverWithErrorHandler .blockingWebClient ().get (path );
146+
147+ final RequestContext ctx = serverWithErrorHandler .requestContextCaptor ().poll ();
148+ final RequestLog log = ctx .log ().whenComplete ().join ();
149+
150+ assertThat (log .responseContentPreview ()).isNull ();
151+ }
76152
77153 @ ParameterizedTest
78- @ ArgumentsSource (ShouldRecordErrorResponseContentPreviewingArgumentsProvider .class )
79- void shouldRecordErrorResponseContentPreviewing (String path , String responseContent ) throws Exception {
80- final BlockingWebClient client = server .blockingWebClient ();
81- final AggregatedHttpResponse res = client .get (path );
82- assertThat (res .contentUtf8 ()).isEqualTo (responseContent );
154+ @ ValueSource (strings = {
155+ "/aborted/http-status-exception" ,
156+ "/aborted/unexpected-exception" ,
157+ "/throw/http-status-exception" ,
158+ "/throw/unexpected-exception" ,
159+ "/annotated/aborted/http-status-exception" ,
160+ "/annotated/aborted/unexpected-exception" ,
161+ "/annotated/throw/http-status-exception" ,
162+ "/annotated/throw/unexpected-exception" ,
163+ "/binding/aborted/http-status-exception" ,
164+ "/binding/aborted/unexpected-exception" ,
165+ "/binding/throw/http-status-exception" ,
166+ "/binding/throw/unexpected-exception" ,
167+ })
168+ void shouldSetNullContentPreviewWhenAnExceptionIsRaisedAndNoErrorHandlerSet (String path ) throws Exception {
169+ serverWithoutServerErrorHandler .blockingWebClient ().get (path );
170+
171+ final RequestContext ctx = serverWithoutServerErrorHandler .requestContextCaptor ().poll ();
172+ final RequestLog log = ctx .log ().whenComplete ().join ();
83173
84- final RequestContext ctx = server .requestContextCaptor ().poll ();
174+ assertThat (log .responseContentPreview ()).isNull ();
175+ }
176+
177+ @ ParameterizedTest
178+ @ ValueSource (strings = {
179+ "/annotatedExceptionHandler/aborted/http-status-exception" ,
180+ "/annotatedExceptionHandler/aborted/unexpected-exception" ,
181+ "/annotatedExceptionHandler/throw/http-status-exception" ,
182+ "/annotatedExceptionHandler/throw/unexpected-exception" ,
183+ })
184+ void annotatedServiceExceptionHandlerAlwaysRecordContentPreview (String path ) throws Exception {
185+ final AggregatedHttpResponse res = serverWithErrorHandler .blockingWebClient ().get (path );
186+ final String content = res .contentUtf8 ();
187+
188+ final RequestContext ctx = serverWithErrorHandler .requestContextCaptor ().poll ();
85189 final RequestLog log = ctx .log ().whenComplete ().join ();
86190
87- assertThat (log .responseContentPreview ()).isEqualTo (responseContent );
191+ assertThat (log .responseContentPreview ()).isEqualTo (content );
88192 }
89193
90194 @ ProducesText
@@ -96,7 +200,7 @@ public HttpResponse abortedHttpStatusException() {
96200
97201 @ Get ("/aborted/unexpected-exception" )
98202 public HttpResponse abortedUnexpectedException () {
99- return HttpResponse .ofFailure (new IllegalStateException ("Oops!" ));
203+ return HttpResponse .ofFailure (new IllegalArgumentException ("Oops!" ));
100204 }
101205
102206 @ Get ("/throw/http-status-exception" )
@@ -106,38 +210,7 @@ public HttpResponse throwHttpStatusException() {
106210
107211 @ Get ("/throw/unexpected-exception" )
108212 public HttpResponse throwUnexpectedException () {
109- throw new IllegalStateException ("Oops!" );
110- }
111- }
112-
113- private static final class ShouldRecordErrorResponseContentPreviewingArgumentsProvider
114- implements ArgumentsProvider {
115- @ Override
116- public Stream <? extends Arguments > provideArguments (ExtensionContext context ) {
117- return Stream .of (Arguments .of ("/aborted/http-status-exception" ,
118- "errorHandler: 500 Internal Server Error" ),
119- Arguments .of ("/aborted/unexpected-exception" ,
120- "errorHandler: Oops!" ),
121- Arguments .of ("/throw/http-status-exception" ,
122- "errorHandler: 500 Internal Server Error" ),
123- Arguments .of ("/throw/unexpected-exception" ,
124- "errorHandler: Oops!" ),
125- Arguments .of ("/annotated/aborted/http-status-exception" ,
126- "errorHandler: 500 Internal Server Error" ),
127- Arguments .of ("/annotated/aborted/unexpected-exception" ,
128- "errorHandler: Oops!" ),
129- Arguments .of ("/annotated/throw/http-status-exception" ,
130- "errorHandler: 500 Internal Server Error" ),
131- Arguments .of ("/annotated/throw/unexpected-exception" ,
132- "errorHandler: Oops!" ),
133- Arguments .of ("/annotatedExceptionHandler/aborted/http-status-exception" ,
134- "exceptionHandler: 500 Internal Server Error" ),
135- Arguments .of ("/annotatedExceptionHandler/aborted/unexpected-exception" ,
136- "exceptionHandler: Oops!" ),
137- Arguments .of ("/annotatedExceptionHandler/throw/http-status-exception" ,
138- "exceptionHandler: 500 Internal Server Error" ),
139- Arguments .of ("/annotatedExceptionHandler/throw/unexpected-exception" ,
140- "exceptionHandler: Oops!" ));
213+ throw new IllegalArgumentException ("Oops!" );
141214 }
142215 }
143216}
0 commit comments