1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.hc.client5.http.impl.io;
29
30 import java.io.IOException;
31 import java.net.Socket;
32 import java.nio.charset.Charset;
33 import java.nio.charset.CharsetDecoder;
34 import java.nio.charset.CharsetEncoder;
35 import java.nio.charset.CodingErrorAction;
36 import java.util.concurrent.atomic.AtomicLong;
37
38 import org.apache.hc.client5.http.io.ManagedHttpClientConnection;
39 import org.apache.hc.core5.annotation.Contract;
40 import org.apache.hc.core5.annotation.ThreadingBehavior;
41 import org.apache.hc.core5.http.ClassicHttpRequest;
42 import org.apache.hc.core5.http.ClassicHttpResponse;
43 import org.apache.hc.core5.http.ContentLengthStrategy;
44 import org.apache.hc.core5.http.config.CharCodingConfig;
45 import org.apache.hc.core5.http.config.Http1Config;
46 import org.apache.hc.core5.http.impl.DefaultContentLengthStrategy;
47 import org.apache.hc.core5.http.impl.io.DefaultHttpRequestWriterFactory;
48 import org.apache.hc.core5.http.impl.io.NoResponseOutOfOrderStrategy;
49 import org.apache.hc.core5.http.io.HttpConnectionFactory;
50 import org.apache.hc.core5.http.io.HttpMessageParserFactory;
51 import org.apache.hc.core5.http.io.HttpMessageWriterFactory;
52 import org.apache.hc.core5.http.io.ResponseOutOfOrderStrategy;
53
54
55
56
57
58 @Contract(threading = ThreadingBehavior.STATELESS)
59 public class ManagedHttpClientConnectionFactory implements HttpConnectionFactory<ManagedHttpClientConnection> {
60
61 private static final AtomicLong COUNTER = new AtomicLong();
62
63 public static final ManagedHttpClientConnectionFactory INSTANCE = new ManagedHttpClientConnectionFactory();
64
65 private final Http1Config h1Config;
66 private final CharCodingConfig charCodingConfig;
67 private final HttpMessageWriterFactory<ClassicHttpRequest> requestWriterFactory;
68 private final HttpMessageParserFactory<ClassicHttpResponse> responseParserFactory;
69 private final ContentLengthStrategy incomingContentStrategy;
70 private final ContentLengthStrategy outgoingContentStrategy;
71 private final ResponseOutOfOrderStrategy responseOutOfOrderStrategy;
72
73 private ManagedHttpClientConnectionFactory(
74 final Http1Config h1Config,
75 final CharCodingConfig charCodingConfig,
76 final HttpMessageWriterFactory<ClassicHttpRequest> requestWriterFactory,
77 final HttpMessageParserFactory<ClassicHttpResponse> responseParserFactory,
78 final ContentLengthStrategy incomingContentStrategy,
79 final ContentLengthStrategy outgoingContentStrategy,
80 final ResponseOutOfOrderStrategy responseOutOfOrderStrategy) {
81 this.h1Config = h1Config != null ? h1Config : Http1Config.DEFAULT;
82 this.charCodingConfig = charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT;
83 this.requestWriterFactory = requestWriterFactory != null ? requestWriterFactory :
84 new DefaultHttpRequestWriterFactory(this.h1Config);
85 this.responseParserFactory = responseParserFactory != null ? responseParserFactory :
86 new DefaultHttpResponseParserFactory(this.h1Config);
87 this.incomingContentStrategy = incomingContentStrategy != null ? incomingContentStrategy :
88 DefaultContentLengthStrategy.INSTANCE;
89 this.outgoingContentStrategy = outgoingContentStrategy != null ? outgoingContentStrategy :
90 DefaultContentLengthStrategy.INSTANCE;
91 this.responseOutOfOrderStrategy = responseOutOfOrderStrategy != null ? responseOutOfOrderStrategy :
92 NoResponseOutOfOrderStrategy.INSTANCE;
93 }
94
95 public ManagedHttpClientConnectionFactory(
96 final Http1Config h1Config,
97 final CharCodingConfig charCodingConfig,
98 final HttpMessageWriterFactory<ClassicHttpRequest> requestWriterFactory,
99 final HttpMessageParserFactory<ClassicHttpResponse> responseParserFactory,
100 final ContentLengthStrategy incomingContentStrategy,
101 final ContentLengthStrategy outgoingContentStrategy) {
102 this(
103 h1Config,
104 charCodingConfig,
105 requestWriterFactory,
106 responseParserFactory,
107 incomingContentStrategy,
108 outgoingContentStrategy,
109 null);
110 }
111
112 public ManagedHttpClientConnectionFactory(
113 final Http1Config h1Config,
114 final CharCodingConfig charCodingConfig,
115 final HttpMessageWriterFactory<ClassicHttpRequest> requestWriterFactory,
116 final HttpMessageParserFactory<ClassicHttpResponse> responseParserFactory) {
117 this(h1Config, charCodingConfig, requestWriterFactory, responseParserFactory, null, null);
118 }
119
120 public ManagedHttpClientConnectionFactory(
121 final Http1Config h1Config,
122 final CharCodingConfig charCodingConfig,
123 final HttpMessageParserFactory<ClassicHttpResponse> responseParserFactory) {
124 this(h1Config, charCodingConfig, null, responseParserFactory);
125 }
126
127 public ManagedHttpClientConnectionFactory() {
128 this(null, null, null);
129 }
130
131 @Override
132 public ManagedHttpClientConnection createConnection(final Socket socket) throws IOException {
133 CharsetDecoder charDecoder = null;
134 CharsetEncoder charEncoder = null;
135 final Charset charset = this.charCodingConfig.getCharset();
136 final CodingErrorAction malformedInputAction = this.charCodingConfig.getMalformedInputAction() != null ?
137 this.charCodingConfig.getMalformedInputAction() : CodingErrorAction.REPORT;
138 final CodingErrorAction unmappableInputAction = this.charCodingConfig.getUnmappableInputAction() != null ?
139 this.charCodingConfig.getUnmappableInputAction() : CodingErrorAction.REPORT;
140 if (charset != null) {
141 charDecoder = charset.newDecoder();
142 charDecoder.onMalformedInput(malformedInputAction);
143 charDecoder.onUnmappableCharacter(unmappableInputAction);
144 charEncoder = charset.newEncoder();
145 charEncoder.onMalformedInput(malformedInputAction);
146 charEncoder.onUnmappableCharacter(unmappableInputAction);
147 }
148 final String id = "http-outgoing-" + COUNTER.getAndIncrement();
149 final DefaultManagedHttpClientConnection conn = new DefaultManagedHttpClientConnection(
150 id,
151 charDecoder,
152 charEncoder,
153 h1Config,
154 incomingContentStrategy,
155 outgoingContentStrategy,
156 responseOutOfOrderStrategy,
157 requestWriterFactory,
158 responseParserFactory);
159 if (socket != null) {
160 conn.bind(socket);
161 }
162 return conn;
163 }
164
165
166
167
168
169
170 public static Builder builder() {
171 return new Builder();
172 }
173
174
175
176
177
178
179 public static final class Builder {
180
181 private Http1Config http1Config;
182 private CharCodingConfig charCodingConfig;
183 private ContentLengthStrategy incomingContentLengthStrategy;
184 private ContentLengthStrategy outgoingContentLengthStrategy;
185 private ResponseOutOfOrderStrategy responseOutOfOrderStrategy;
186 private HttpMessageWriterFactory<ClassicHttpRequest> requestWriterFactory;
187 private HttpMessageParserFactory<ClassicHttpResponse> responseParserFactory;
188
189 private Builder() {}
190
191 public Builder http1Config(final Http1Config http1Config) {
192 this.http1Config = http1Config;
193 return this;
194 }
195
196 public Builder charCodingConfig(final CharCodingConfig charCodingConfig) {
197 this.charCodingConfig = charCodingConfig;
198 return this;
199 }
200
201 public Builder incomingContentLengthStrategy(final ContentLengthStrategy incomingContentLengthStrategy) {
202 this.incomingContentLengthStrategy = incomingContentLengthStrategy;
203 return this;
204 }
205
206 public Builder outgoingContentLengthStrategy(final ContentLengthStrategy outgoingContentLengthStrategy) {
207 this.outgoingContentLengthStrategy = outgoingContentLengthStrategy;
208 return this;
209 }
210
211 public Builder responseOutOfOrderStrategy(final ResponseOutOfOrderStrategy responseOutOfOrderStrategy) {
212 this.responseOutOfOrderStrategy = responseOutOfOrderStrategy;
213 return this;
214 }
215
216 public Builder requestWriterFactory(
217 final HttpMessageWriterFactory<ClassicHttpRequest> requestWriterFactory) {
218 this.requestWriterFactory = requestWriterFactory;
219 return this;
220 }
221
222 public Builder responseParserFactory(
223 final HttpMessageParserFactory<ClassicHttpResponse> responseParserFactory) {
224 this.responseParserFactory = responseParserFactory;
225 return this;
226 }
227
228 public ManagedHttpClientConnectionFactory build() {
229 return new ManagedHttpClientConnectionFactory(
230 http1Config,
231 charCodingConfig,
232 requestWriterFactory,
233 responseParserFactory,
234 incomingContentLengthStrategy,
235 outgoingContentLengthStrategy,
236 responseOutOfOrderStrategy);
237 }
238 }
239 }