Quarkus: CORS with Ajax is not working well.

Created on 23 Jul 2019  路  28Comments  路  Source: quarkusio/quarkus

Calling REST resources using Ajax is not working fine
I am trying to call a service sides on my localhost:8080/person (POST) through VueJS app on my localhost:8084 but it is not working. I tried to enable CORS config. in application.properties with the below :

quarkus.http.cors=true
quarkus.http.cors.origins=http://localhost:8084
quarkus.http.cors.headers=accept, authorization, content-type, x-requested-with
quarkus.http.cors.methods=GET, PUT, POST

Expected behavior
It should work fine and be able to call my resource.

Actual behavior
Browser logs error :

Access to XMLHttpRequest at 'http://localhost:8080/person' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Even it is not reaching to my ContainerRequestFilter code.

To Reproduce
Steps to reproduce the behavior:

  1. Any REST resource. in my case I used POST method with application/json.
  2. Try to call it from different app (port) using Ajax library (jQuery or Axiom).

Configuration

> quarkus.http.cors=true
> quarkus.http.cors.origins=http://localhost:8084
> quarkus.http.cors.headers=accept, authorization, content-type, x-requested-with
> quarkus.http.cors.methods=GET, PUT, POST

Environment (please complete the following information):

  • Output of uname -a or ver: Darwin SDG0268LMAC 18.6.0 Darwin Kernel Version 18.6.0: Thu Apr 25 23:16:27 PDT 2019; root:xnu-4903.261.4~2/RELEASE_X86_64 x86_64
  • Output of java -version: OpenJDK Runtime Environment Corretto-8.202.08.2 (build 1.8.0_202-b08)
  • GraalVM version (if different from Java): graalvm-ce-19.0.2
  • Quarkus version or git rev: 0.18.0

Additional context
Event if CORS is disabled same issue is produced.

aresecurity kinbug

Most helpful comment

Dears,
I've generated the issue again with latest version. I've created two repositories for this. One for Quarkus as the backend APIs and the other one is the VueJS as front end.

Quarkus : https://github.com/iabughosh/microprofile-health
VueJS : https://github.com/iabughosh/VueJs

I will do some debugging from my end too.

Regards.

All 28 comments

Do you have to go the cors route? I'd just configure npm (vuejs) to proxy anything on localhost:8084/person to localhost:8080/person. In production on kubernetes this sort of thing is better done with an 2 ingresses sharing same dns.

Edit: if you staying with cors, try using your real ip, I've had trouble with localhost in the past

I took a look and it seems this is caused by the way how the CORS servlet filter and the RESTEasy servlet filter interact. I'll continue digging on Monday.

That makes sense now. Because request is not being reached to quarkus request filter so it must be stopped by some earlier stage. Thanks for the update.

Found two more strange scenarious:

  1. If I put * in quarkus.http.cors.origins - Quarkus block everything. Expected to allow all. Adding custom ContainerResponseFilter may fix it.
@Provider
public class CORSFilter implements ContainerResponseFilter {

    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
        MultivaluedMap<String, Object> headers = responseContext.getHeaders();
        headers.putSingle("Access-Control-Allow-Origin", "*");
        ...    
        headers.putSingle("Access-Control-Allow-Headers", "origin, content-type, accept, authorization");
    }

}
  1. PATCH HTTP method is not respected. Was not able to get it working even with explicit declaration in ContainerResponseFilter
headers.putSingle("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE, PATCH, HEAD");

For some reason PATCH requests are not catched by ContainerResponseFilter at all.

Ad 1., that's because the CORS servlet filter expects to find the value of the Origin header in the set of configured allowed origins. Supporting * is probably a good idea.

Ad 2., that's probably also because the CORSFilter and ResteasyFilter interact in a weird way. I didn't have time to look into it yet, but I should get to it this week.

Ad 1. again: the CORS filter already allows all origins, if quarkus.http.cors.origins is not set. Not sure if adding support for * is worth it.

Is this still a WIP? Just doing a check-in to see if there is something in motion (npm dev UI environment with quarkus dev backend environment). The scenario I have is a quarkus w/ undertow, resteasy, and smallrye-openapi and using Postman not getting any of the CORS-associated headers in the response for the rest/openapi endpoint (no Access-Control-Allow-Origin header entry).

Tested quarkus 0.20.0 and 0.23.1

application.properties

quarkus.smallrye-openapi.path=/openapi
quarkus.http.cors=true
#testing with and without, no difference
#quarkus.http.cors.origins=http://localhost:3000,http://localhost:8080
#testing with and without, no difference
#quarkus.http.cors.exposed-headers=Access-Control-Allow-Origin

I have tried the last version 0.23.1 but it doesn't work: Back-end still rejects requests from a different domain, respectively my react Front-end app still receive
Access to XMLHttpRequest at 'http://localhost:8080/' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Is this issue still not fixed? Is there is any suitable alternative?

I'm testing CORS using http://www.test-cors.org on Quarkus 0.23.2 and also the latest master branch, with this config file:

quarkus.http.cors=true
quarkus.http.cors.origins=http://www.test-cors.org
quarkus.http.cors.headers=accept,authorization,content-type,x-requested-with,x-foobar
quarkus.http.cors.methods=GET,POST,PUT

It seems to work just fine.

Just tested 0.23.2, hopefully I'm the minor but still not getting the Access-Control-Allow-Origin headers (tested both mvn quarkus:dev and a production build running the java -jar *-runner.jar).

application.properties

quarkus.smallrye-openapi.path=/openapi
quarkus.http.cors=true
#testing with and without, no difference
#quarkus.http.cors.origins=http://localhost:3000,http://localhost:8080
#tried this related to potential issue with localhost, no difference
#quarkus.http.cors.origins=http://127.0.0.1:3000
#testing with and without, no difference
#quarkus.http.cors.exposed-headers=Access-Control-Allow-Origin
#testing with and without, no difference
#quarkus.http.cors.headers=accept, origin, authorization, content-type, x-requested-with
#testing with and without, no difference
#quarkus.http.cors.methods=GET,PUT,POST,OPTIONS

@dhartford Can you please provide more details? For example, do you have a reproducer using curl (or HTTPie)?

Also, do you perhaps use some kind of a caching proxy or something similar? I've noticed that the Quarkus CORS handler should at the very least include Vary: Origin (and perhaps other values for the Vary header), but that didn't prevent it from working in the basic local usecase.

Using postman and curl for direct functional testing, and 'npm start' with a webapp with a fetch for applied testing (which states the no Access-Control-Allowed-Origin header problem), all localhost or 127.0.0.1 without any caching proxy.

curl -v http://localhost:8080/openapi/app

*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /openapi/app HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< **Content-Type: application/json**
< **Content-Length: 40**
< 
* Connection #0 to host localhost left intact
{ "APP_NAME": "Changed App Name Here so length may be different"}

Ah, so it's on the OpenAPI endpoint, I didn't try that. I'll check tomorrow, thanks for the info.

Dears,
I've generated the issue again with latest version. I've created two repositories for this. One for Quarkus as the backend APIs and the other one is the VueJS as front end.

Quarkus : https://github.com/iabughosh/microprofile-health
VueJS : https://github.com/iabughosh/VueJs

I will do some debugging from my end too.

Regards.

The same issue is still produced as @dhartford describe, even with the latest version 0.23.2
Hopefully, it will be fixed in the next release!

I have the same issue as well. When I use

quarkus.http.cors.origins=http://localhost:8081

is working fine. But when using *

quarkus.http.cors.origins="*"`

is not working no matter what I do.

Instead of *, just leave the quarkus.http.cors.origins property out.

One other thing I'd like to highlight, because I've seen it in the reports here (I already mentioned this in the other CORS issue): if the request doesn't have the Origin header, the response won't have CORS headers either.

This is perfectly fine per my understanding of CORS. (What's worse is that this doesn't necessarily play well with caching proxy servers. My understanding is that we should at least always include Vary: Origin if CORS is enabled. But that shouldn't be a problem in the investigations here.)

@Ladicek you are right. It is working now only with:

quarkus.http.cors=true

Dears,
Is still this considered as a bug ? because for me even if I disabled cors config, I am still facing the same issue !

Does anyone here have a reproducer with a ReactJS application accessing a Quarkus REST API to demonstrate this error to maintainers?

@iabughosh I think, this issue should be marked as solved.
for me now it's working correctly.
with the configuration as @Ladicek mentioned before.

quarkus.http.cors=true
quarkus.http.cors.origins=http://localhost:3000
quarkus.http.cors.headers=accept,origin,authorization,content-type,x-requested-with,x-foobar
quarkus.http.cors.methods=GET,POST,PUT,OPTIONS

Unfortunately, the main problem - which is disabling the cors still not working fine. I will try these configuration and report back.

Just Tried @Ladicek and it is working fine (which is great :) ); however, it is not working if I disabled CORS. I will close this bug as the main issue is resolved for me.

As I said, the only way to make it work on any domain is using only one single CORS property:

quarkus.http.cors=true

If I disable it, the problem still persists. I'm using Quarkus 0.25.0.
IMHO quarkus.http.cors.origins=* should also work, but for now, it isn't.

Currently, you can achieve "all origins" by simply omitting quarkus.http.cors.origins altogether. I wonder what should be the difference between "no quarkus.http.cors.origins at all" and "quarkus.http.cors.origins=*".

@Ladicek For the quarkus.http.cors.origins=* discussion item, I can at least share my experience which may not be related to the catalyst, but may support it. When working in certain regulatory fields, you often have to explicitly list all (security) relevant configuration values, often copying the default value, to show reviewers/auditors the intent as explicitly as possible.
HTH!

@dhartford In that case, it should be possible to just write quarkus.http.cors.origins=, but I'd expect that in highly regulated fields, allowing all origins wouldn't be what you want :-) Thanks for an interesting case though!

I have same issue..i have tried all above ways.but still not work.issue is still there of cors

Was this page helpful?
0 / 5 - 0 ratings