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.core5.http.impl.io;
29
30 import java.io.IOException;
31 import java.io.OutputStream;
32 import java.net.Socket;
33 import java.nio.charset.CharsetDecoder;
34 import java.nio.charset.CharsetEncoder;
35
36 import org.apache.hc.core5.http.ClassicHttpRequest;
37 import org.apache.hc.core5.http.ClassicHttpResponse;
38 import org.apache.hc.core5.http.ContentLengthStrategy;
39 import org.apache.hc.core5.http.HttpEntity;
40 import org.apache.hc.core5.http.HttpException;
41 import org.apache.hc.core5.http.HttpStatus;
42 import org.apache.hc.core5.http.HttpVersion;
43 import org.apache.hc.core5.http.ProtocolVersion;
44 import org.apache.hc.core5.http.UnsupportedHttpVersionException;
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.io.HttpMessageParser;
48 import org.apache.hc.core5.http.io.HttpMessageParserFactory;
49 import org.apache.hc.core5.http.io.HttpMessageWriter;
50 import org.apache.hc.core5.http.io.HttpMessageWriterFactory;
51 import org.apache.hc.core5.http.io.HttpServerConnection;
52 import org.apache.hc.core5.util.Args;
53
54
55
56
57
58
59 public class DefaultBHttpServerConnection extends BHttpConnectionBase implements HttpServerConnection {
60
61 private final String scheme;
62 private final ContentLengthStrategy incomingContentStrategy;
63 private final ContentLengthStrategy outgoingContentStrategy;
64 private final HttpMessageParser<ClassicHttpRequest> requestParser;
65 private final HttpMessageWriter<ClassicHttpResponse> responseWriter;
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86 public DefaultBHttpServerConnection(
87 final String scheme,
88 final Http1Config http1Config,
89 final CharsetDecoder charDecoder,
90 final CharsetEncoder charEncoder,
91 final ContentLengthStrategy incomingContentStrategy,
92 final ContentLengthStrategy outgoingContentStrategy,
93 final HttpMessageParserFactory<ClassicHttpRequest> requestParserFactory,
94 final HttpMessageWriterFactory<ClassicHttpResponse> responseWriterFactory) {
95 super(http1Config, charDecoder, charEncoder);
96 this.scheme = scheme;
97 this.requestParser = (requestParserFactory != null ? requestParserFactory :
98 DefaultHttpRequestParserFactory.INSTANCE).create(http1Config);
99 this.responseWriter = (responseWriterFactory != null ? responseWriterFactory :
100 DefaultHttpResponseWriterFactory.INSTANCE).create();
101 this.incomingContentStrategy = incomingContentStrategy != null ? incomingContentStrategy :
102 DefaultContentLengthStrategy.INSTANCE;
103 this.outgoingContentStrategy = outgoingContentStrategy != null ? outgoingContentStrategy :
104 DefaultContentLengthStrategy.INSTANCE;
105 }
106
107 public DefaultBHttpServerConnection(
108 final String scheme,
109 final Http1Config http1Config,
110 final CharsetDecoder charDecoder,
111 final CharsetEncoder charEncoder) {
112 this(scheme, http1Config, charDecoder, charEncoder, null, null, null, null);
113 }
114
115 public DefaultBHttpServerConnection(
116 final String scheme,
117 final Http1Config http1Config) {
118 this(scheme, http1Config, null, null);
119 }
120
121 protected void onRequestReceived(final ClassicHttpRequest request) {
122 }
123
124 protected void onResponseSubmitted(final ClassicHttpResponse response) {
125 }
126
127 @Override
128 public void bind(final Socket socket) throws IOException {
129 super.bind(socket);
130 }
131
132 @Override
133 public ClassicHttpRequest receiveRequestHeader() throws HttpException, IOException {
134 final SocketHolder socketHolder = ensureOpen();
135 final ClassicHttpRequest request = this.requestParser.parse(this.inBuffer, socketHolder.getInputStream());
136 if (request == null) {
137 return null;
138 }
139 final ProtocolVersion transportVersion = request.getVersion();
140 if (transportVersion != null && transportVersion.greaterEquals(HttpVersion.HTTP_2)) {
141 throw new UnsupportedHttpVersionException(transportVersion);
142 }
143 request.setScheme(this.scheme);
144 this.version = transportVersion;
145 onRequestReceived(request);
146 incrementRequestCount();
147 return request;
148 }
149
150 @Override
151 public void receiveRequestEntity(final ClassicHttpRequest request)
152 throws HttpException, IOException {
153 Args.notNull(request, "HTTP request");
154 final SocketHolder socketHolder = ensureOpen();
155
156 final long len = this.incomingContentStrategy.determineLength(request);
157 if (len == ContentLengthStrategy.UNDEFINED) {
158 return;
159 }
160 request.setEntity(createIncomingEntity(request, this.inBuffer, socketHolder.getInputStream(), len));
161 }
162
163 @Override
164 public void sendResponseHeader(final ClassicHttpResponse response)
165 throws HttpException, IOException {
166 Args.notNull(response, "HTTP response");
167 final SocketHolder socketHolder = ensureOpen();
168 this.responseWriter.write(response, this.outbuffer, socketHolder.getOutputStream());
169 onResponseSubmitted(response);
170 if (response.getCode() >= HttpStatus.SC_SUCCESS) {
171 incrementResponseCount();
172 }
173 }
174
175 @Override
176 public void sendResponseEntity(final ClassicHttpResponse response)
177 throws HttpException, IOException {
178 Args.notNull(response, "HTTP response");
179 final SocketHolder socketHolder = ensureOpen();
180 final HttpEntity entity = response.getEntity();
181 if (entity == null) {
182 return;
183 }
184 final long len = this.outgoingContentStrategy.determineLength(response);
185 try (final OutputStream outStream = createContentOutputStream(len, this.outbuffer, socketHolder.getOutputStream(), entity.getTrailers())) {
186 entity.writeTo(outStream);
187 }
188 }
189 }