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 final ProtocolVersion transportVersion = request.getVersion();
137 if (transportVersion != null && transportVersion.greaterEquals(HttpVersion.HTTP_2)) {
138 throw new UnsupportedHttpVersionException(transportVersion);
139 }
140 request.setScheme(this.scheme);
141 this.version = transportVersion;
142 onRequestReceived(request);
143 incrementRequestCount();
144 return request;
145 }
146
147 @Override
148 public void receiveRequestEntity(final ClassicHttpRequest request)
149 throws HttpException, IOException {
150 Args.notNull(request, "HTTP request");
151 final SocketHolder socketHolder = ensureOpen();
152
153 final long len = this.incomingContentStrategy.determineLength(request);
154 if (len == ContentLengthStrategy.UNDEFINED) {
155 return;
156 }
157 request.setEntity(createIncomingEntity(request, this.inBuffer, socketHolder.getInputStream(), len));
158 }
159
160 @Override
161 public void sendResponseHeader(final ClassicHttpResponse response)
162 throws HttpException, IOException {
163 Args.notNull(response, "HTTP response");
164 final SocketHolder socketHolder = ensureOpen();
165 this.responseWriter.write(response, this.outbuffer, socketHolder.getOutputStream());
166 onResponseSubmitted(response);
167 if (response.getCode() >= HttpStatus.SC_SUCCESS) {
168 incrementResponseCount();
169 }
170 }
171
172 @Override
173 public void sendResponseEntity(final ClassicHttpResponse response)
174 throws HttpException, IOException {
175 Args.notNull(response, "HTTP response");
176 final SocketHolder socketHolder = ensureOpen();
177 final HttpEntity entity = response.getEntity();
178 if (entity == null) {
179 return;
180 }
181 final long len = this.outgoingContentStrategy.determineLength(response);
182 try (final OutputStream outStream = createContentOutputStream(len, this.outbuffer, socketHolder.getOutputStream(), entity.getTrailers())) {
183 entity.writeTo(outStream);
184 }
185 }
186 }