Skip to content

Commit 309e8c3

Browse files
committed
Working
1 parent c709bbb commit 309e8c3

File tree

2 files changed

+41
-16
lines changed

2 files changed

+41
-16
lines changed

src/main/java/io/fusionauth/http/server/internal/HTTPWorker.java

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import io.fusionauth.http.HTTPValues;
2626
import io.fusionauth.http.HTTPValues.Connections;
2727
import io.fusionauth.http.HTTPValues.Headers;
28+
import io.fusionauth.http.HTTPValues.Protocols;
2829
import io.fusionauth.http.ParseException;
2930
import io.fusionauth.http.log.Logger;
3031
import io.fusionauth.http.server.HTTPHandler;
@@ -130,7 +131,7 @@ public void run() {
130131

131132
// If the "expect" wasn't accepted, close the socket and exit
132133
if (!expectContinue(request)) {
133-
close(Status.OK, response);
134+
closeSocketOnly();
134135
return;
135136
}
136137

@@ -148,7 +149,7 @@ public void run() {
148149
// Since the Handler can change the Keep-Alive state, we use the response here
149150
if (!keepAlive) {
150151
logger.debug("[{}] Close socket. No Keep-Alive", Thread.currentThread().threadId());
151-
close(Status.OK, response);
152+
closeSocketOnly();
152153
break;
153154
}
154155

@@ -211,7 +212,7 @@ public State state() {
211212
}
212213

213214
private void close(int status, HTTPResponse response) {
214-
boolean error = status != 200;
215+
boolean error = status > 299;
215216
if (error && instrumenter != null) {
216217
instrumenter.connectionClosed();
217218
}
@@ -235,18 +236,36 @@ private void close(int status, HTTPResponse response) {
235236
}
236237
}
237238

239+
private void closeSocketOnly() {
240+
try {
241+
socket.close();
242+
} catch (IOException e) {
243+
logger.debug(String.format("[%s] Could not close the connection because the socket threw an exception.", Thread.currentThread().threadId()), e);
244+
}
245+
}
246+
238247
private boolean expectContinue(HTTPRequest request) throws IOException {
239248
var expectResponse = new HTTPResponse();
249+
// Default to 100, the validator is optional. The HTTP response will default to 200.
250+
expectResponse.setStatus(100);
251+
252+
// Invoke the optional validator
240253
var validator = configuration.getExpectValidator();
241254
if (validator != null) {
242255
validator.validate(request, expectResponse);
243256
}
244257

258+
// Ignore the status message if set by the validator. A status code of 100 should always have a message of Continue.
259+
if (expectResponse.getStatus() == 100) {
260+
expectResponse.setStatusMessage("Continue");
261+
}
262+
245263
// Write directly to the socket because the HTTPOutputStream does a lot of extra work that we don't want
246264
OutputStream out = socket.getOutputStream();
247265
HTTPTools.writeResponsePreamble(expectResponse, out);
248266
out.flush();
249267

268+
// A status code of 100 means go for it.
250269
return expectResponse.getStatus() == 100;
251270
}
252271

@@ -262,14 +281,14 @@ private Integer validatePreamble(HTTPRequest request) {
262281

263282
if (!protocol.startsWith("HTTP/")) {
264283
if (logger.isTraceEnabled()) {
265-
logger.trace("Invalid request. Invalid protocol [{}]. Supported versions [HTTP/1.1].", protocol);
284+
logger.trace("Invalid request. Invalid protocol [{}]. Supported versions [{}].", protocol, Protocols.HTTTP1_1);
266285
}
267286
return Status.BadRequest;
268287
}
269288

270-
if (!"HTTP/1.1".equals(protocol)) {
289+
if (!Protocols.HTTTP1_1.equals(protocol)) {
271290
if (logger.isTraceEnabled()) {
272-
logger.trace("Invalid request. Unsupported HTTP version [{}]. Supported versions [HTTP/1.1].", protocol);
291+
logger.trace("Invalid request. Unsupported HTTP version [{}]. Supported versions [{}].", protocol, Protocols.HTTTP1_1);
273292
}
274293
return Status.HTTPVersionNotSupported;
275294
}

src/test/java/io/fusionauth/http/ExpectTest.java

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -83,17 +83,23 @@ public void expect(String scheme) throws Exception {
8383
res.setStatusMessage("Continue");
8484
};
8585

86+
// Test w/ and w/out a custom expect validator. The default behavior should be to approve the payload.
8687
CountingInstrumenter instrumenter = new CountingInstrumenter();
87-
try (HTTPServer ignore = makeServer(scheme, handler, instrumenter, validator).start(); var client = makeClient(scheme, null)) {
88-
URI uri = makeURI(scheme, "");
89-
var response = client.send(
90-
HttpRequest.newBuilder().uri(uri).header(Headers.ContentType, "application/json").expectContinue(true).POST(BodyPublishers.ofString(RequestBody)).build(),
91-
r -> BodySubscribers.ofString(StandardCharsets.UTF_8)
92-
);
88+
boolean[] validationOptions = {true, false};
89+
for (boolean validation : validationOptions) {
90+
ExpectValidator expectValidator = validation ? validator : null;
9391

94-
assertEquals(response.statusCode(), 200);
95-
assertEquals(response.body(), ExpectedResponse);
96-
assertTrue(validated.get());
92+
try (HTTPServer ignore = makeServer(scheme, handler, instrumenter, expectValidator).start(); var client = makeClient(scheme, null)) {
93+
URI uri = makeURI(scheme, "");
94+
var response = client.send(
95+
HttpRequest.newBuilder().uri(uri).header(Headers.ContentType, "application/json").expectContinue(true).POST(BodyPublishers.ofString(RequestBody)).build(),
96+
r -> BodySubscribers.ofString(StandardCharsets.UTF_8)
97+
);
98+
99+
assertEquals(response.statusCode(), 200);
100+
assertEquals(response.body(), ExpectedResponse);
101+
assertTrue(validated.get());
102+
}
97103
}
98104
}
99105

@@ -120,4 +126,4 @@ public void expectReject(String scheme) throws Exception {
120126
assertEquals(response.body(), "");
121127
}
122128
}
123-
}
129+
}

0 commit comments

Comments
 (0)