3

I'm creating web-services in Java with Jersey2.0. Everything works as expected when I execute request from POSTMAN but when I execute request from the client application I'm not able to receive header parameter. My client application is on JavaScript. Also, I've added the CORS allows origin request parameters in ContainerResponseContext.

The following shows my ContainerResponseFilter class where I add the CORS.

@Provider
class CORSFilter : ContainerResponseFilter {

    override fun filter(requestContext: ContainerRequestContext?, responseContext: ContainerResponseContext?) {
        responseContext?.apply {
            headers.add("Access-Control-Allow-Origin", "*")
            headers.add("Access-Control-Allow-Headers", "origin, content-type, authorization, accept, privatekey")
            headers.add("Access-Control-Allow-Credentials", "true")
            headers.add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD")
        }
    }
}

The privatekey is my header name for the request. Now here's my code for ContainerRequestFilter.

@Priority(AUTHENTICATION)
@Provider
class JsTokenFilterNeeded : JsBaseFilter(this::class.java.simpleName) {

    override fun filter(request: ContainerRequestContext?) {
        val path = request?.uriInfo?.path       
        val privateKeyHeaderValue = request?.getHeaderString("privatekey")
        println("private key -> $privateKeyHeaderValue")
    }
}

I'm always getting the null value in privateKeyHeaderValue. Both the containers are successfully registered in ResourceConfig class.

As of now, I'm getting no 'Access-Control-Allow-Origin' header is present on the requested resource here's the log.

{host=[203.***.51.***:5555], connection=[keep-alive], access-control-request-method=[GET], origin=[http://localhost:38596], user-agent=[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36], access-control-request-headers=[privatekey], accept=[*/*], alexatoolbar-alx_ns_ph=[AlexaToolbar/alx-4.0.3], referer=[http://localhost:38596/], accept-encoding=[gzip, deflate], accept-language=[en-US,en;q=0.9]}

Edit 1 Here's my Js code for the client application.

$.ajax(
    {
        type: "GET",
        headers: {
            'privatekey': privateKey
        },
        url: "http://***.124.**.76:5555/dcu/energy/"+active_import,
        data: {
            'dcu_id': '99220445',
            'tariff': 0
        },
        error: function (result) {
            console.log(result);
        },
        success: function (result) {
            console.log(result);
        }
    });

Edit2 I'm using ResourceConfig in order to register my Providers. Here's my ResourceConfig class.

class MyResourceConfig : ResourceConfig() {

    init {
        register(CORSFilter())
        register(JsTokenFilterNeeded())
    }
}
Ahsan Saeed
  • 701
  • 10
  • 22
  • 1
    As you described, from postman everything works OK. Please share the client code in JS. In addition, I would recommend to print the entire request to log (or debug) and see what is missing. – Adi Ohana Apr 20 '19 at 11:56
  • I've already printed the log in the question at the end if you see and for Js code, I'll edit my question. – Ahsan Saeed Apr 20 '19 at 14:12
  • @AdiOhana added the JavaScript code. – Ahsan Saeed Apr 20 '19 at 14:18
  • check out https://stackoverflow.com/questions/28065963/how-to-handle-cors-using-jax-rs-with-jersey . are you using package scanning to discover providers and resources? If not, then you should explicitly register the CORSFilter – Adi Ohana Apr 20 '19 at 15:04
  • @AdiOhana I've already seen this link before posting my question and also I'm using the resource config in order to register my Providers. – Ahsan Saeed Apr 20 '19 at 15:21

1 Answers1

3

There is a preflight request that happened before the real request. The preflight request doesn't send any of the headers (the key header included). It only sends headers asking the server if the request is allowed. So when the preflight request reaches the filter, the token will not be there.

What you should do is make the CorsFilter implement both a ContainerRequestFilter and a ContainerResponseFilter. Make it a @PreMatching filter. That way it will be called before the token filter. In the request filter, check to see if it is a preflight request. If it is, then abort the request. This will cause the request to skip the rest of the request filters and go straight to the response filters. In the response filter side, you can add the CORS headers.

You should read the UPDATE in this post to get a better understanding of the flow of the CORS protocol and also see a better implementation of the CorsFilter that you can use that should work for your scenario.

Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720