Jooby CORS and conf

80 views
Skip to first unread message

Francesco Costa

unread,
Jan 20, 2019, 2:51:07 PM1/20/19
to jooby-project
Hi all,
I am trying to send request from my local web app to my local dev Jooby server, I got some failures due to CORS policy disallowing the requests.
I managed to make it work reading the doc https://jooby.org/doc/#misc-cors though I don't fully understand how Jooby works on this.

I tried to send requests both with axios.js or native fetch: if a preflight OPTIONS is send to the server my request will always fail saying the method is disallowed, if I only send a GET it works.

I'm running Jooby with 
{
  use("*", new CorsHandler());
}

I looked a little bit at the impl and it's essentially a Route filter, I didn't spent too much time on how the config is merged and that's why I have these 2 questions:

1.  I tried to add OPTIONS to my dev config, but that didn't fix the preflighted requests case
  # Allowed methods: Set the Access-Control-Allow-Methods header 
  allowedMethods: [GET, POST]
Does Jooby uses either the .conf options or the CorsHandler ones? Basically I don't understand if the handler is always required to enable CORS or if you could simply enable CORS support from the config.
Also if the handler uses the config, why is not liking my OPTIONS preflight request?

2. Is there a way to see all the currently used config values in the server through some debug handler or should I just print them out in some module?
I see on startup that the correct config is picked up from the config tree print, but I want to make sure that OPTIONS is being picked up
Thanks,

This is the code, in the failing version I set custom headers and that cause the library to do a preflight in the ok version has no custom headers
fetch('http://localhost:8080/test?key=' + idToken, {
credentials: 'omit',
/*
headers: {
accept: 'text/plain',
'accept-language': 'en-US,en;q=0.9,it;q=0.8',
'cache-control': 'max-age=0',
'upgrade-insecure-requests': '1'
},

*/
referrerPolicy: 'no-referrer-when-downgrade',
body: null,
method: 'GET',
mode: 'cors'
})

This is the one that fails 

curl 'http://localhost:8080/test?key=eyJhbGciOiJSUzI1NiI.....o710KVcQ' -X OPTIONS -H 'Access-Control-Request-Method: GET' -H 'Origin: http://localhost:3000' -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Language: en-US,en;q=0.9,it;q=0.8' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36' -H 'Accept: */*' -H 'Referer: http://localhost:3000/toy' -H 'Connection: keep-alive' -H 'Access-Control-Request-Headers: cache-control,upgrade-insecure-requests' --compressed

And response headers 
HTTP/1.1 405 Method Not Allowed Cache-Control: must-revalidate,no-cache,no-store Content-Type: text/html;charset=UTF-8 content-length: 2923 connection: keep-alive

This is the one that works

curl 'http://localhost:8080/test?key=eyJhbGciOiJSU......mb9MtjjP4yTjw' -H 'Origin: http://localhost:3000' -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Language: en-US,en;q=0.9,it;q=0.8' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36' -H 'Accept: */*' -H 'Referer: http://localhost:3000/toy' -H 'Connection: keep-alive' --compressed

Response headers
HTTP/1.1 200 OK Access-Control-Allow-Origin: http://localhost:3000 Access-Control-Allow-Credentials: true Content-Type: text/html;charset=UTF-8 content-length: 45 connection: keep-alive

Francesco Costa

unread,
Jan 20, 2019, 4:17:58 PM1/20/19
to jooby-project
Partially figured out the failure, the preflght call needs to be manually handled with an options() route, I thought Jooby was doing it for some reason.
I get past that, returned empty response with 200, don't see a follow up GET coming from the client after that, but I guess that's for me to go an brush up on how preflight works in HTTP/2

Edgar Espina

unread,
Jan 20, 2019, 7:49:46 PM1/20/19
to jooby-project
I used corshandler in a couple of project without issue. It works, something else is going on.

1. you need to install/use the corshandler (set the correct headers)

2. .conf file is for setting properties on corshandler without doing it by code. for example you could turn on/off per environment.. etc

3. there is nothing to print out all conf property values, you need to do it manually.

4. what you see in the docs are the default values:

cors {
 
# Configures the Access-Control-Allow-Origin CORS header. Possibly values: *, domain, regex or a list of previous values.
 
# Example:
 
# "*"
 
# ["http://foo.com"]
 
# ["http://*.com"]
 
# ["http://foo.com", "http://bar.com"]
 
origin: "*"

 
# If true, set the Access-Control-Allow-Credentials header
 
credentials: true


 
# Allowed methods: Set the Access-Control-Allow-Methods header
 
allowedMethods: [GET, POST]


 
# Allowed headers: set the Access-Control-Allow-Headers header. Possibly values: *, header name or a list of previous values.
 
# Examples
 
# "*"
 
# Custom-Header
 
# [Header-1, Header-2]
 
allowedHeaders: [X-Requested-With, Content-Type, Accept, Origin]

 
# Preflight max age: number of seconds that preflight requests can be cached by the client
 
maxAge: 30m

 
# Set the Access-Control-Expose-Headers header
 
# exposedHeaders: []
}


you can override one or more from your application.conf like:

cors.allowedMethods:[GET, POST, PUT, etc]

Francesco Costa

unread,
Jan 21, 2019, 1:24:16 PM1/21/19
to jooby-project
The CORS handler deals with preflight as you mentioned, I basically was failing one of the allowed header checks, I had a little bit of time to read the code and step-by-step debug and I figured out what was going on.

One last question: did you define cors.enabled somewhere else for us? Cause I did not see that in the doc defaults, but it's definitely enabled as it's working

Thanks for your time as usual

Cors.java
@Inject
public Cors(@Named("cors") final Config config) {
requireNonNull(config, "Config is required.");
this.enabled = config.hasPath("enabled") ? config.getBoolean("enabled") : true;
withOrigin(list(config.getAnyRef("origin")));
this.credentials = config.getBoolean("credentials");
withMethods(list(config.getAnyRef("allowedMethods")));
withHeaders(list(config.getAnyRef("allowedHeaders")));
withMaxAge((int) config.getDuration("maxAge", TimeUnit.SECONDS));
withExposedHeaders(config.hasPath("exposedHeaders")
? list(config.getAnyRef("exposedHeaders"))
: Collections.emptyList());
}

Edgar Espina

unread,
Jan 21, 2019, 1:40:55 PM1/21/19
to Francesco Costa, jooby-project
Glad it works. `cors.enabled` is an optional conf property. If not present (default), it is set to `true`. Just another option/way of turning everything on/off per environment.

Thanks

--
You received this message because you are subscribed to the Google Groups "jooby-project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jooby-projec...@googlegroups.com.
To post to this group, send email to jooby-...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jooby-project/17146e72-1c19-4dd4-aded-ee0b229963d3%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


--
edgar
Reply all
Reply to author
Forward
0 new messages