2525import io .fusionauth .http .HTTPValues ;
2626import io .fusionauth .http .HTTPValues .Connections ;
2727import io .fusionauth .http .HTTPValues .Headers ;
28+ import io .fusionauth .http .HTTPValues .Protocols ;
2829import io .fusionauth .http .ParseException ;
2930import io .fusionauth .http .log .Logger ;
3031import 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 }
0 commit comments