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