Skip to content

Commit f4786f3

Browse files
committed
Drop HttpResponseHeaders and add a default method to notify trailing headers, close #1397
Motivation: HttpResponseHeaders brings an extra allocation and complexity for the sheer sake of holding the information that those headers are trailing ones. Trailing headers are actually a rare thing, we could just add an extra method on AsyncHandler with a default implementation that would noop. Modifications: * drop HttpResponseHeaders * pass Netty’s HttpHeaders * introduce AsyncHandler#onTrailingHeadersReceived Result: More simple API (no need to unwrap), less allocations
1 parent 18150e4 commit f4786f3

37 files changed

+198
-224
lines changed

client/src/main/java/org/asynchttpclient/AsyncCompletionHandler.java

+24-25
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@
1616
*/
1717
package org.asynchttpclient;
1818

19+
import io.netty.handler.codec.http.HttpHeaders;
20+
1921
import org.asynchttpclient.handler.ProgressAsyncHandler;
2022
import org.slf4j.Logger;
2123
import org.slf4j.LoggerFactory;
2224

2325
/**
24-
* An {@link AsyncHandler} augmented with an {@link #onCompleted(Response)} convenience method which gets called
25-
* when the {@link Response} processing is finished. This class also implement the {@link ProgressAsyncHandler} callback,
26-
* all doing nothing except returning {@link org.asynchttpclient.AsyncHandler.State#CONTINUE}
26+
* An {@link AsyncHandler} augmented with an {@link #onCompleted(Response)} convenience method which gets called when the {@link Response} processing is finished. This class also
27+
* implement the {@link ProgressAsyncHandler} callback, all doing nothing except returning {@link org.asynchttpclient.AsyncHandler.State#CONTINUE}
2728
*
2829
* @param <T> Type of the value that will be returned by the associated {@link java.util.concurrent.Future}
2930
*/
@@ -32,41 +33,37 @@ public abstract class AsyncCompletionHandler<T> implements AsyncHandler<T>, Prog
3233
private static final Logger LOGGER = LoggerFactory.getLogger(AsyncCompletionHandler.class);
3334
private final Response.ResponseBuilder builder = new Response.ResponseBuilder();
3435

35-
/**
36-
* {@inheritDoc}
37-
*/
38-
public State onBodyPartReceived(final HttpResponseBodyPart content) throws Exception {
36+
@Override
37+
public State onBodyPartReceived(HttpResponseBodyPart content) throws Exception {
3938
builder.accumulate(content);
4039
return State.CONTINUE;
4140
}
4241

43-
/**
44-
* {@inheritDoc}
45-
*/
46-
public State onStatusReceived(final HttpResponseStatus status) throws Exception {
42+
@Override
43+
public State onStatusReceived(HttpResponseStatus status) throws Exception {
4744
builder.reset();
4845
builder.accumulate(status);
4946
return State.CONTINUE;
5047
}
5148

52-
/**
53-
* {@inheritDoc}
54-
*/
55-
public State onHeadersReceived(final HttpResponseHeaders headers) throws Exception {
49+
@Override
50+
public State onHeadersReceived(HttpHeaders headers) throws Exception {
5651
builder.accumulate(headers);
5752
return State.CONTINUE;
5853
}
5954

60-
/**
61-
* {@inheritDoc}
62-
*/
55+
@Override
56+
public State onTrailingHeadersReceived(HttpHeaders headers) throws Exception {
57+
builder.accumulate(headers);
58+
return State.CONTINUE;
59+
}
60+
61+
@Override
6362
public final T onCompleted() throws Exception {
6463
return onCompleted(builder.build());
6564
}
6665

67-
/**
68-
* {@inheritDoc}
69-
*/
66+
@Override
7067
public void onThrowable(Throwable t) {
7168
LOGGER.debug(t.getMessage(), t);
7269
}
@@ -85,28 +82,30 @@ public void onThrowable(Throwable t) {
8582
*
8683
* @return a {@link org.asynchttpclient.AsyncHandler.State} telling to CONTINUE or ABORT the current processing.
8784
*/
85+
@Override
8886
public State onHeadersWritten() {
8987
return State.CONTINUE;
9088
}
9189

9290
/**
93-
* Invoked when the content (a {@link java.io.File}, {@link String} or {@link java.io.InputStream} has been fully
94-
* written on the I/O socket.
91+
* Invoked when the content (a {@link java.io.File}, {@link String} or {@link java.io.InputStream} has been fully written on the I/O socket.
9592
*
9693
* @return a {@link org.asynchttpclient.AsyncHandler.State} telling to CONTINUE or ABORT the current processing.
9794
*/
95+
@Override
9896
public State onContentWritten() {
9997
return State.CONTINUE;
10098
}
10199

102100
/**
103101
* Invoked when the I/O operation associated with the {@link Request} body as been progressed.
104102
*
105-
* @param amount The amount of bytes to transfer
103+
* @param amount The amount of bytes to transfer
106104
* @param current The amount of bytes transferred
107-
* @param total The total number of bytes transferred
105+
* @param total The total number of bytes transferred
108106
* @return a {@link org.asynchttpclient.AsyncHandler.State} telling to CONTINUE or ABORT the current processing.
109107
*/
108+
@Override
110109
public State onContentWriteProgress(long amount, long current, long total) {
111110
return State.CONTINUE;
112111
}

client/src/main/java/org/asynchttpclient/AsyncHandler.java

+14-3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package org.asynchttpclient;
1717

18+
import io.netty.handler.codec.http.HttpHeaders;
19+
1820

1921
/**
2022
* An asynchronous handler or callback which gets invoked as soon as some data is available when
@@ -89,14 +91,23 @@ enum State {
8991
State onStatusReceived(HttpResponseStatus responseStatus) throws Exception;
9092

9193
/**
92-
* Invoked as soon as the HTTP headers has been received. Can potentially be invoked more than once if a broken server
93-
* sent trailing headers.
94+
* Invoked as soon as the HTTP headers have been received.
9495
*
9596
* @param headers the HTTP headers.
9697
* @return a {@link State} telling to CONTINUE or ABORT the current processing.
9798
* @throws Exception if something wrong happens
9899
*/
99-
State onHeadersReceived(HttpResponseHeaders headers) throws Exception;
100+
State onHeadersReceived(HttpHeaders headers) throws Exception;
101+
102+
/**
103+
* Invoked when trailing headers have been received.
104+
* @param headers
105+
* @return
106+
* @throws Exception
107+
*/
108+
default State onTrailingHeadersReceived(HttpHeaders headers) throws Exception {
109+
return State.CONTINUE;
110+
}
100111

101112
/**
102113
* Invoked once the HTTP response processing is finished.

client/src/main/java/org/asynchttpclient/HttpResponseHeaders.java

-44
This file was deleted.

client/src/main/java/org/asynchttpclient/Response.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -172,15 +172,15 @@ public interface Response {
172172
class ResponseBuilder {
173173
private final List<HttpResponseBodyPart> bodyParts = new ArrayList<>(1);
174174
private HttpResponseStatus status;
175-
private HttpResponseHeaders headers;
175+
private HttpHeaders headers;
176176

177177
public ResponseBuilder accumulate(HttpResponseStatus status) {
178178
this.status = status;
179179
return this;
180180
}
181181

182-
public ResponseBuilder accumulate(HttpResponseHeaders headers) {
183-
this.headers = this.headers == null ? headers : new HttpResponseHeaders(this.headers.getHeaders().add(headers.getHeaders()), true);
182+
public ResponseBuilder accumulate(HttpHeaders headers) {
183+
this.headers = this.headers == null ? headers : this.headers.add(headers);
184184
return this;
185185
}
186186

client/src/main/java/org/asynchttpclient/filter/FilterContext.java

+8-7
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@
1212
*/
1313
package org.asynchttpclient.filter;
1414

15+
import io.netty.handler.codec.http.HttpHeaders;
16+
17+
import java.io.IOException;
18+
1519
import org.asynchttpclient.AsyncHandler;
16-
import org.asynchttpclient.HttpResponseHeaders;
1720
import org.asynchttpclient.HttpResponseStatus;
1821
import org.asynchttpclient.Request;
1922

20-
import java.io.IOException;
21-
2223
/**
2324
* A {@link FilterContext} can be used to decorate {@link Request} and {@link AsyncHandler} from a list of {@link RequestFilter}.
2425
* {@link RequestFilter} gets executed before the HTTP request is made to the remote server. Once the response bytes are
@@ -68,9 +69,9 @@ public HttpResponseStatus getResponseStatus() {
6869
}
6970

7071
/**
71-
* @return the response {@link HttpResponseHeaders}
72+
* @return the response {@link HttpHeaders}
7273
*/
73-
public HttpResponseHeaders getResponseHeaders() {
74+
public HttpHeaders getResponseHeaders() {
7475
return b.headers;
7576
}
7677

@@ -94,7 +95,7 @@ public static class FilterContextBuilder<T> {
9495
private HttpResponseStatus responseStatus = null;
9596
private boolean replayRequest = false;
9697
private IOException ioException = null;
97-
private HttpResponseHeaders headers;
98+
private HttpHeaders headers;
9899

99100
public FilterContextBuilder() {
100101
}
@@ -130,7 +131,7 @@ public FilterContextBuilder<T> responseStatus(HttpResponseStatus responseStatus)
130131
return this;
131132
}
132133

133-
public FilterContextBuilder<T> responseHeaders(HttpResponseHeaders headers) {
134+
public FilterContextBuilder<T> responseHeaders(HttpHeaders headers) {
134135
this.headers = headers;
135136
return this;
136137
}

client/src/main/java/org/asynchttpclient/handler/BodyDeferringAsyncHandler.java

+15-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
*/
1313
package org.asynchttpclient.handler;
1414

15+
import io.netty.handler.codec.http.HttpHeaders;
16+
1517
import java.io.FilterInputStream;
1618
import java.io.IOException;
1719
import java.io.InputStream;
@@ -23,7 +25,6 @@
2325

2426
import org.asynchttpclient.AsyncHandler;
2527
import org.asynchttpclient.HttpResponseBodyPart;
26-
import org.asynchttpclient.HttpResponseHeaders;
2728
import org.asynchttpclient.HttpResponseStatus;
2829
import org.asynchttpclient.Response;
2930

@@ -98,6 +99,7 @@ public BodyDeferringAsyncHandler(final OutputStream os) {
9899
this.responseSet = false;
99100
}
100101

102+
@Override
101103
public void onThrowable(Throwable t) {
102104
this.throwable = t;
103105
// Counting down to handle error cases too.
@@ -121,17 +123,26 @@ public void onThrowable(Throwable t) {
121123
}
122124
}
123125

126+
@Override
124127
public State onStatusReceived(HttpResponseStatus responseStatus) throws Exception {
125128
responseBuilder.reset();
126129
responseBuilder.accumulate(responseStatus);
127130
return State.CONTINUE;
128131
}
129132

130-
public State onHeadersReceived(HttpResponseHeaders headers) throws Exception {
133+
@Override
134+
public State onHeadersReceived(HttpHeaders headers) throws Exception {
135+
responseBuilder.accumulate(headers);
136+
return State.CONTINUE;
137+
}
138+
139+
@Override
140+
public State onTrailingHeadersReceived(HttpHeaders headers) throws Exception {
131141
responseBuilder.accumulate(headers);
132142
return State.CONTINUE;
133143
}
134144

145+
@Override
135146
public State onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception {
136147
// body arrived, flush headers
137148
if (!responseSet) {
@@ -152,6 +163,7 @@ protected void closeOut() throws IOException {
152163
}
153164
}
154165

166+
@Override
155167
public Response onCompleted() throws IOException {
156168

157169
if (!responseSet) {
@@ -242,6 +254,7 @@ public BodyDeferringInputStream(final Future<Response> future, final BodyDeferri
242254
* Closes the input stream, and "joins" (wait for complete execution
243255
* together with potential exception thrown) of the async request.
244256
*/
257+
@Override
245258
public void close() throws IOException {
246259
// close
247260
super.close();

client/src/main/java/org/asynchttpclient/handler/TransferCompletionHandler.java

+8-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
import org.asynchttpclient.AsyncCompletionHandlerBase;
2020
import org.asynchttpclient.HttpResponseBodyPart;
21-
import org.asynchttpclient.HttpResponseHeaders;
2221
import org.asynchttpclient.Response;
2322
import org.slf4j.Logger;
2423
import org.slf4j.LoggerFactory;
@@ -97,8 +96,14 @@ public void headers(HttpHeaders headers) {
9796
}
9897

9998
@Override
100-
public State onHeadersReceived(final HttpResponseHeaders headers) throws Exception {
101-
fireOnHeaderReceived(headers.getHeaders());
99+
public State onHeadersReceived(final HttpHeaders headers) throws Exception {
100+
fireOnHeaderReceived(headers);
101+
return super.onHeadersReceived(headers);
102+
}
103+
104+
@Override
105+
public State onTrailingHeadersReceived(HttpHeaders headers) throws Exception {
106+
fireOnHeaderReceived(headers);
102107
return super.onHeadersReceived(headers);
103108
}
104109

0 commit comments

Comments
 (0)