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