2626import javax .ws .rs .client .ClientBuilder ;
2727import javax .ws .rs .client .ClientRequestContext ;
2828import javax .ws .rs .client .ClientRequestFilter ;
29+ import javax .ws .rs .client .ClientResponseContext ;
30+ import javax .ws .rs .client .ClientResponseFilter ;
31+ import javax .ws .rs .core .Application ;
2932import javax .ws .rs .core .GenericEntity ;
33+ import javax .ws .rs .core .Link ;
3034import javax .ws .rs .core .MediaType ;
3135import javax .ws .rs .core .MultivaluedMap ;
3236import javax .ws .rs .core .Response ;
37+ import javax .ws .rs .core .UriBuilder ;
38+ import javax .ws .rs .core .Variant ;
3339import javax .ws .rs .ext .MessageBodyWriter ;
40+ import javax .ws .rs .ext .ReaderInterceptor ;
41+ import javax .ws .rs .ext .ReaderInterceptorContext ;
42+ import javax .ws .rs .ext .RuntimeDelegate ;
3443import java .io .IOException ;
3544import java .io .OutputStream ;
3645import java .lang .annotation .Annotation ;
3948import java .nio .charset .StandardCharsets ;
4049import java .util .ArrayList ;
4150import java .util .Arrays ;
51+ import java .util .Collections ;
52+ import java .util .Iterator ;
4253import java .util .List ;
54+ import java .util .Map ;
55+ import java .util .concurrent .atomic .AtomicReference ;
4356
44- //import static java.nio.charset.StandardCharsets;
4557import static org .junit .jupiter .api .Assertions .assertEquals ;
4658
4759public class AbortTest {
@@ -52,6 +64,9 @@ public class AbortTest {
5264 Arrays .asList ("hello" , "goodbye" ),
5365 Arrays .asList ("salutations" , "farewell" )
5466 );
67+ private final String entity = "HI" ;
68+ private final String header = "CUSTOM_HEADER" ;
69+
5570
5671 @ Test
5772 void testAbortWithGenericEntity () {
@@ -103,8 +118,6 @@ public void writeTo(List<List<String>> csvList, Class<?> type, Type genericType,
103118
104119 @ Test
105120 void testAbortWithMBWWritingHeaders () {
106- final String entity = "HI" ;
107- final String header = "CUSTOM_HEADER" ;
108121 try (Response response = ClientBuilder .newClient ().register (new ClientRequestFilter () {
109122 @ Override
110123 public void filter (ClientRequestContext requestContext ) throws IOException {
@@ -130,4 +143,145 @@ public void writeTo(String s, Class<?> type, Type genericType, Annotation[] anno
130143 }
131144 }
132145
146+ @ Test
147+ void testInterceptorHeaderAdd () {
148+ final String header2 = "CUSTOM_HEADER_2" ;
149+
150+ try (Response response = ClientBuilder .newClient ().register (new ClientRequestFilter () {
151+ @ Override
152+ public void filter (ClientRequestContext requestContext ) throws IOException {
153+ requestContext .abortWith (Response .ok ().entity (entity ).build ());
154+ }
155+ }).register (new ReaderInterceptor () {
156+ @ Override
157+ public Object aroundReadFrom (ReaderInterceptorContext context ) throws IOException , WebApplicationException {
158+ MultivaluedMap <String , String > headers = context .getHeaders ();
159+ headers .put (header , Collections .singletonList (entity ));
160+ headers .add (header2 , entity );
161+ return context .proceed ();
162+ }
163+ })
164+ .target ("http://localhost:8080" ).request ().get ()) {
165+ Assertions .assertEquals (entity , response .readEntity (String .class ));
166+ Assertions .assertEquals (entity , response .getHeaderString (header ));
167+ Assertions .assertEquals (entity , response .getHeaderString (header2 ));
168+ }
169+ }
170+
171+ @ Test
172+ void testInterceptorHeaderIterate () {
173+ final AtomicReference <String > originalHeader = new AtomicReference <>();
174+
175+ try (Response response = ClientBuilder .newClient ().register (new ClientRequestFilter () {
176+ @ Override
177+ public void filter (ClientRequestContext requestContext ) throws IOException {
178+ requestContext .abortWith (Response .ok ().header (header , header ).entity (entity ).build ());
179+ }
180+ }).register (new ReaderInterceptor () {
181+ @ Override
182+ public Object aroundReadFrom (ReaderInterceptorContext context ) throws IOException , WebApplicationException {
183+ MultivaluedMap <String , String > headers = context .getHeaders ();
184+ Iterator <Map .Entry <String , List <String >>> it = headers .entrySet ().iterator ();
185+ while (it .hasNext ()) {
186+ Map .Entry <String , List <String >> next = it .next ();
187+ if (header .equals (next .getKey ())) {
188+ originalHeader .set (next .setValue (Collections .singletonList (entity )).get (0 ));
189+ }
190+ }
191+ return context .proceed ();
192+ }
193+ })
194+ .target ("http://localhost:8080" ).request ().get ()) {
195+ Assertions .assertEquals (entity , response .readEntity (String .class ));
196+ Assertions .assertEquals (entity , response .getHeaderString (header ));
197+ Assertions .assertEquals (header , originalHeader .get ());
198+ }
199+ }
200+
201+ @ Test
202+ void testNullHeader () {
203+ final AtomicReference <String > originalHeader = new AtomicReference <>();
204+ RuntimeDelegate .setInstance (new StringHeaderRuntimeDelegate (RuntimeDelegate .getInstance ()));
205+ try (Response response = ClientBuilder .newClient ().register (new ClientRequestFilter () {
206+ @ Override
207+ public void filter (ClientRequestContext requestContext ) throws IOException {
208+ requestContext .abortWith (Response .ok ()
209+ .header (header , new StringHeader ())
210+ .entity (entity ).build ());
211+ }
212+ }).register (new ClientResponseFilter () {
213+ @ Override
214+ public void filter (ClientRequestContext requestContext , ClientResponseContext responseContext )
215+ throws IOException {
216+ originalHeader .set (responseContext .getHeaderString (header ));
217+ }
218+ })
219+ .target ("http://localhost:8080" ).request ().get ()) {
220+ Assertions .assertEquals (entity , response .readEntity (String .class ));
221+ Assertions .assertEquals ("" , originalHeader .get ());
222+ }
223+ }
224+
225+ private static class StringHeader extends AtomicReference <String > {
226+
227+ }
228+
229+ private static class StringHeaderDelegate implements RuntimeDelegate .HeaderDelegate <StringHeader > {
230+ @ Override
231+ public StringHeader fromString (String value ) {
232+ StringHeader stringHeader = new StringHeader ();
233+ stringHeader .set (value );
234+ return stringHeader ;
235+ }
236+
237+ @ Override
238+ public String toString (StringHeader value ) {
239+ //on purpose
240+ return null ;
241+ }
242+ }
243+
244+ private static class StringHeaderRuntimeDelegate extends RuntimeDelegate {
245+ private final RuntimeDelegate original ;
246+
247+ private StringHeaderRuntimeDelegate (RuntimeDelegate original ) {
248+ this .original = original ;
249+ }
250+
251+ @ Override
252+ public UriBuilder createUriBuilder () {
253+ return original .createUriBuilder ();
254+ }
255+
256+ @ Override
257+ public Response .ResponseBuilder createResponseBuilder () {
258+ return original .createResponseBuilder ();
259+ }
260+
261+ @ Override
262+ public Variant .VariantListBuilder createVariantListBuilder () {
263+ return original .createVariantListBuilder ();
264+ }
265+
266+ @ Override
267+ public <T > T createEndpoint (Application application , Class <T > endpointType )
268+ throws IllegalArgumentException , UnsupportedOperationException {
269+ return original .createEndpoint (application , endpointType );
270+ }
271+
272+ @ Override
273+ @ SuppressWarnings ("unchecked" )
274+ public <T > HeaderDelegate <T > createHeaderDelegate (Class <T > type ) throws IllegalArgumentException {
275+ if (StringHeader .class .equals (type )) {
276+ return (HeaderDelegate <T >) new StringHeaderDelegate ();
277+ }
278+ return original .createHeaderDelegate (type );
279+ }
280+
281+ @ Override
282+ public Link .Builder createLinkBuilder () {
283+ return original .createLinkBuilder ();
284+ }
285+ }
286+
133287}
0 commit comments