Skip to content

[BUG] OPTIONS request for a httpmaid not configured for CORS should respond with 200 and no Access-Control-Request-* response header (aka deny by default) #82

@lestephane

Description

@lestephane

Describe the bug
Right now, an http maid where I did not configure CORS with CorsConfigurators will return an HTTP 500 for a path that is otherwise recognized (albeit for a different method)

To Reproduce

  @NotNull
  private static QuantumMaid serverInstance(int port) {
    QuantumMaid quantumMaid = quantumMaid()
        .withHttpMaid(anHttpMaid()
            .get("/*", dumpRequest())
            .post("/*", dumpRequest())
            .put("/*", dumpRequest())
            .delete("/*", dumpRequest()).build())
        .withLocalHostEndpointOnPort(port);
    return quantumMaid;
  }

client request:

$ curl -v localhost:8080 -XOPTIONS
* Rebuilt URL to: localhost:8080/
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> OPTIONS / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.47.0
> Accept: */*
> 
< HTTP/1.1 500 Internal Server Error
< Date: Mon, 01 Jun 2020 08:18:51 GMT
< Transfer-encoding: chunked
< 
* Connection #0 to host localhost left intact

server output:

11:19:49.485 [HTTP-Dispatcher] ERROR de.quantummaid.httpmaid.exceptions.DefaultExceptionMapper - Exception during request processing
PATH = Path(path=/)
QUERY_PARAMETERS = QueryParameters(queryParameters={})
RESPONSE_STATUS = 500
REQUEST_BODY_STRING = 
EXCEPTION = de.quantummaid.httpmaid.handler.PageNotFoundException: No handler found for path '/' and method 'OPTIONS'

PATH = Path(path=/)
QUERY_PARAMETERS = QueryParameters(queryParameters={})
RESPONSE_STATUS = 200
REQUEST_BODY_STRING = 
UNMARSHALLED_REQUEST_BODY = null
RAW_METHOD = OPTIONS
IS_HTTP_REQUEST = true
REQUEST_CONTENT_TYPE = ContentType(value=null)
RESPONSE_HEADERS = {}
REQUEST_BODY_STREAM = sun.net.httpserver.FixedLengthInputStream@2704bf89
RAW_PATH = /
RAW_REQUEST_QUERY_PARAMETERS = {}
METHOD = HttpRequestMethod(value=OPTIONS)
RAW_REQUEST_HEADERS = sun.net.httpserver.UnmodifiableHeaders@29740f87
REQUEST_HEADERS = Headers(headers={HeaderKey(value=user-agent)=HeaderValue(value=curl/7.47.0), HeaderKey(value=host)=HeaderValue(value=localhost:8080), HeaderKey(value=accept)=HeaderValue(value=*/*)})
UNMARSHALLED_REQUEST_BODY = null
RAW_METHOD = OPTIONS
IS_HTTP_REQUEST = true
REQUEST_CONTENT_TYPE = ContentType(value=null)
RESPONSE_HEADERS = {}
REQUEST_BODY_STREAM = sun.net.httpserver.FixedLengthInputStream@2704bf89
RAW_PATH = /
RAW_REQUEST_QUERY_PARAMETERS = {}
METHOD = HttpRequestMethod(value=OPTIONS)
RAW_REQUEST_HEADERS = sun.net.httpserver.UnmodifiableHeaders@29740f87
REQUEST_HEADERS = Headers(headers={HeaderKey(value=user-agent)=HeaderValue(value=curl/7.47.0), HeaderKey(value=host)=HeaderValue(value=localhost:8080), HeaderKey(value=accept)=HeaderValue(value=*/*)})
de.quantummaid.httpmaid.handler.PageNotFoundException: No handler found for path '/' and method 'OPTIONS'

PATH = Path(path=/)
QUERY_PARAMETERS = QueryParameters(queryParameters={})
RESPONSE_STATUS = 200
REQUEST_BODY_STRING = 
UNMARSHALLED_REQUEST_BODY = null
RAW_METHOD = OPTIONS
IS_HTTP_REQUEST = true
REQUEST_CONTENT_TYPE = ContentType(value=null)
RESPONSE_HEADERS = {}
REQUEST_BODY_STREAM = sun.net.httpserver.FixedLengthInputStream@2704bf89
RAW_PATH = /
RAW_REQUEST_QUERY_PARAMETERS = {}
METHOD = HttpRequestMethod(value=OPTIONS)
RAW_REQUEST_HEADERS = sun.net.httpserver.UnmodifiableHeaders@29740f87
REQUEST_HEADERS = Headers(headers={HeaderKey(value=user-agent)=HeaderValue(value=curl/7.47.0), HeaderKey(value=host)=HeaderValue(value=localhost:8080), HeaderKey(value=accept)=HeaderValue(value=*/*)})
	at de.quantummaid.httpmaid.handler.PageNotFoundException.pageNotFoundException(PageNotFoundException.java:41)
	at de.quantummaid.httpmaid.handler.InvokeHandlerProcessor.lambda$apply$0(InvokeHandlerProcessor.java:45)
	at java.base/java.util.Optional.orElseThrow(Optional.java:408)
	at de.quantummaid.httpmaid.handler.InvokeHandlerProcessor.apply(InvokeHandlerProcessor.java:45)
	at de.quantummaid.httpmaid.chains.Chain.lambda$accept$0(Chain.java:74)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
	at java.base/java.util.LinkedList$LLSpliterator.forEachRemaining(LinkedList.java:1239)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
	at de.quantummaid.httpmaid.chains.Chain.accept(Chain.java:74)
	at de.quantummaid.httpmaid.chains.ChainRegistry.accept(ChainRegistry.java:69)
	at de.quantummaid.httpmaid.chains.ChainRegistry.handleAction(ChainRegistry.java:78)
	at de.quantummaid.httpmaid.chains.ChainRegistry.accept(ChainRegistry.java:70)
	at de.quantummaid.httpmaid.chains.ChainRegistry.handleAction(ChainRegistry.java:78)
	at de.quantummaid.httpmaid.chains.ChainRegistry.accept(ChainRegistry.java:70)
	at de.quantummaid.httpmaid.chains.ChainRegistry.handleAction(ChainRegistry.java:78)
	at de.quantummaid.httpmaid.chains.ChainRegistry.accept(ChainRegistry.java:70)
	at de.quantummaid.httpmaid.chains.ChainRegistry.handleAction(ChainRegistry.java:78)
	at de.quantummaid.httpmaid.chains.ChainRegistry.accept(ChainRegistry.java:70)
	at de.quantummaid.httpmaid.chains.ChainRegistry.handleAction(ChainRegistry.java:78)
	at de.quantummaid.httpmaid.chains.ChainRegistry.accept(ChainRegistry.java:70)
	at de.quantummaid.httpmaid.chains.ChainRegistry.handleAction(ChainRegistry.java:78)
	at de.quantummaid.httpmaid.chains.ChainRegistry.accept(ChainRegistry.java:70)
	at de.quantummaid.httpmaid.chains.ChainRegistry.handleAction(ChainRegistry.java:78)
	at de.quantummaid.httpmaid.chains.ChainRegistry.accept(ChainRegistry.java:70)
	at de.quantummaid.httpmaid.chains.ChainRegistry.putIntoChain(ChainRegistry.java:63)
	at de.quantummaid.httpmaid.HttpMaid.handleRequest(HttpMaid.java:85)
	at de.quantummaid.httpmaid.endpoint.purejavaendpoint.PureJavaEndpointHandler.handle(PureJavaEndpointHandler.java:48)
	at jdk.httpserver/com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:77)
	at jdk.httpserver/sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:82)
	at jdk.httpserver/com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:80)
	at jdk.httpserver/sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:692)
	at jdk.httpserver/com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:77)
	at jdk.httpserver/sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:664)
	at jdk.httpserver/sun.net.httpserver.ServerImpl$DefaultExecutor.execute(ServerImpl.java:159)
	at jdk.httpserver/sun.net.httpserver.ServerImpl$Dispatcher.handle(ServerImpl.java:442)
	at jdk.httpserver/sun.net.httpserver.ServerImpl$Dispatcher.run(ServerImpl.java:408)
	at java.base/java.lang.Thread.run(Thread.java:834)

Expected behavior

If the path is known, and CORS is not configured, it should deny by default.

According to https://www.html5rocks.com/en/tutorials/cors/#toc-handling-a-not-so-simple-request, denial looks like this:

If the server wants to deny the CORS request, it can just return a generic response (like HTTP 200), without any CORS header. The server may want to deny the request if the HTTP method or headers requested in the preflight are not valid. Since there are no CORS-specific headers in the response, the browser assumes the request is invalid, and doesn’t make the actual request:

Note: Using regular expressions to express input classes

When Cors has not been configured

request:

OPTIONS / HTTP/1.1
Origin: (.*)
Access-Control-Request-Method: (.*)
Access-Control-Request-Headers: (.*)

response:

HTTP/1.1 200 OK
Content-Type: Content-Type: text/html; charset=utf-8
NO Access-Control-Allow-Origin
NO Access-Control-Allow-Methods
NO Access-Control-Allow-Headers
  • project version used: httpmaid 0.9.61 (bom 1.0.48)
  • Java version used: 11

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions