@Override public ClientResponse apply(final ClientRequest jerseyRequest) throws ProcessingException { final Request jettyRequest = translateRequest(jerseyRequest); final Map<String, String> clientHeadersSnapshot = writeOutBoundHeaders(jerseyRequest.getHeaders(), jettyRequest); final ContentProvider entity = getBytesProvider(jerseyRequest); if (entity != null) { jettyRequest.content(entity); } try { final ContentResponse jettyResponse = jettyRequest.send(); HeaderUtils.checkHeaderChanges( clientHeadersSnapshot, jerseyRequest.getHeaders(), JettyConnector.this.getClass().getName()); final javax.ws.rs.core.Response.StatusType status = jettyResponse.getReason() == null ? Statuses.from(jettyResponse.getStatus()) : Statuses.from(jettyResponse.getStatus(), jettyResponse.getReason()); final ClientResponse jerseyResponse = new ClientResponse(status, jerseyRequest); processResponseHeaders(jettyResponse.getHeaders(), jerseyResponse); try { jerseyResponse.setEntityStream(new HttpClientResponseInputStream(jettyResponse)); } catch (final IOException e) { LOGGER.log(Level.SEVERE, null, e); } return jerseyResponse; } catch (final Exception e) { throw new ProcessingException(e); } }
@Test public void multiple_headers_with_the_same_name_are_processed_successfully() throws Exception { final CloseableHttpClient client = mock(CloseableHttpClient.class); final DropwizardApacheConnector dropwizardApacheConnector = new DropwizardApacheConnector(client, null, false); final Header[] apacheHeaders = { new BasicHeader("Set-Cookie", "test1"), new BasicHeader("Set-Cookie", "test2") }; final CloseableHttpResponse apacheResponse = mock(CloseableHttpResponse.class); when(apacheResponse.getStatusLine()) .thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK")); when(apacheResponse.getAllHeaders()).thenReturn(apacheHeaders); when(client.execute(Matchers.any())).thenReturn(apacheResponse); final ClientRequest jerseyRequest = mock(ClientRequest.class); when(jerseyRequest.getUri()).thenReturn(URI.create("http://localhost")); when(jerseyRequest.getMethod()).thenReturn("GET"); when(jerseyRequest.getHeaders()).thenReturn(new MultivaluedHashMap<>()); final ClientResponse jerseyResponse = dropwizardApacheConnector.apply(jerseyRequest); assertThat(jerseyResponse.getStatus()) .isEqualTo(apacheResponse.getStatusLine().getStatusCode()); }
/** * Build a new Apache's {@link org.apache.http.client.methods.HttpUriRequest} from Jersey's {@link * org.glassfish.jersey.client.ClientRequest} * * <p>Convert a method, URI, body, headers and override a user-agent if necessary * * @param jerseyRequest representation of an HTTP request in Jersey * @return a new {@link org.apache.http.client.methods.HttpUriRequest} */ private HttpUriRequest buildApacheRequest(ClientRequest jerseyRequest) { final RequestBuilder builder = RequestBuilder.create(jerseyRequest.getMethod()) .setUri(jerseyRequest.getUri()) .setEntity(getHttpEntity(jerseyRequest)); for (String headerName : jerseyRequest.getHeaders().keySet()) { builder.addHeader(headerName, jerseyRequest.getHeaderString(headerName)); } final Optional<RequestConfig> requestConfig = addJerseyRequestConfig(jerseyRequest); requestConfig.ifPresent(builder::setConfig); return builder.build(); }
@Override public Future<?> apply(final ClientRequest jerseyRequest, final AsyncConnectorCallback callback) { final Request jettyRequest = translateRequest(jerseyRequest); final Map<String, String> clientHeadersSnapshot = writeOutBoundHeaders(jerseyRequest.getHeaders(), jettyRequest); final ContentProvider entity = getStreamProvider(jerseyRequest); if (entity != null) { jettyRequest.content(entity); } final AtomicBoolean callbackInvoked = new AtomicBoolean(false); final Throwable failure; try { final SettableFuture<ClientResponse> responseFuture = SettableFuture.create(); Futures.addCallback( responseFuture, new FutureCallback<ClientResponse>() { @Override public void onSuccess(final ClientResponse result) {} @Override public void onFailure(final Throwable t) { if (t instanceof CancellationException) { // take care of future cancellation jettyRequest.abort(t); } } }); final AtomicReference<ClientResponse> jerseyResponse = new AtomicReference<ClientResponse>(); final ByteBufferInputStream entityStream = new ByteBufferInputStream(); jettyRequest.send( new Response.Listener.Adapter() { @Override public void onHeaders(final Response jettyResponse) { HeaderUtils.checkHeaderChanges( clientHeadersSnapshot, jerseyRequest.getHeaders(), JettyConnector.this.getClass().getName()); if (responseFuture.isDone()) if (!callbackInvoked.compareAndSet(false, true)) { return; } final ClientResponse response = translateResponse(jerseyRequest, jettyResponse, entityStream); jerseyResponse.set(response); callback.response(response); } @Override public void onContent(final Response jettyResponse, final ByteBuffer content) { try { entityStream.put(content); } catch (final InterruptedException ex) { final ProcessingException pe = new ProcessingException(ex); entityStream.closeQueue(pe); // try to complete the future with an exception responseFuture.setException(pe); Thread.currentThread().interrupt(); } } @Override public void onComplete(final Result result) { entityStream.closeQueue(); // try to complete the future with the response only once truly done responseFuture.set(jerseyResponse.get()); } @Override public void onFailure(final Response response, final Throwable t) { entityStream.closeQueue(t); // try to complete the future with an exception responseFuture.setException(t); if (callbackInvoked.compareAndSet(false, true)) { callback.failure(t); } } }); return responseFuture; } catch (final Throwable t) { failure = t; } if (callbackInvoked.compareAndSet(false, true)) { callback.failure(failure); } return Futures.immediateFailedFuture(failure); }