question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Problem with 'Access-Control-Allow-Origin'

See original GitHub issue

Hi, i try to use your library and get ‘Access-Control-Allow-Origin’ error.

Assume, we have a plain version of backend, that just allow us to handle a POST request:

package com.daniel

import scala.concurrent.duration._
import akka.actor._
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.HttpResponse
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server._
import akka.stream.ActorMaterializer
import akka.util.Timeout
import ch.megard.akka.http.cors.CorsDirectives._
import ch.megard.akka.http.cors.CorsSettings

object Main extends App with UserResources{
  implicit val system = ActorSystem("test-service")
  implicit val materializer = ActorMaterializer()

  implicit val executionContext = system.dispatcher
  implicit val timeout = Timeout(10 seconds)

  val api = routes

  Http().bindAndHandle(handler = api, interface = "0.0.0.0", port = 5000) map { binding =>
    println(s"REST interface bound to ${binding.localAddress}")
  }
}

trait UserResources {
  val settings = CorsSettings.defaultSettings.copy(allowCredentials = false)

  val routes: Route = cors(settings) {
    path("cors-issue") {
      post {
          complete(HttpResponse(200))
      }
    }
  }
}

Our build.sbt:

enablePlugins(JavaServerAppPackaging)

name := "cors-issue"
version := "0.1"
organization := "com.daniel"
scalaVersion := "2.11.8"
scalacOptions := Seq("-unchecked", "-deprecation", "-encoding", "utf8")

libraryDependencies ++= {
  val AkkaVersion       = "2.4.6"
  val AkkaHttpVersion   = "2.4.3"
  Seq(
    "com.typesafe.akka" %% "akka-slf4j"      % AkkaVersion,
    "com.typesafe.akka" %% "akka-http-core" % AkkaVersion,
    "com.typesafe.akka" %% "akka-http-experimental" % AkkaHttpVersion,
    "ch.megard" %% "akka-http-cors" % "0.1.2"
  )
}

Revolver.settings

And if we use cURL command:

$ curl -v -H "Content-Type: application/json" \
> -X POST "http://localhost:5000/cors-issue" \
> -d '{"id": "test"}'

We will get a response:

*   Trying ::1...
* Connected to localhost (::1) port 5000 (#0)
> POST /cors-issue HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.45.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 14
>
* upload completely sent off: 14 out of 14 bytes
< HTTP/1.1 200 OK
< Server: akka-http/2.4.6
< Date: Sat, 11 Jun 2016 10:55:05 GMT
< Content-Length: 0
<
* Connection #0 to host localhost left intact

And that’s OK. But if we try POST request using AJAX (with jQuery):

jQuery.ajax({
            type: "POST",
            url: "http://localhost:5000/cors-issue/",
            contentType: "application/json",
            crossDomain: true,
            data: {"name": name},
            dataType: "json",
            success: function(status) {
                console.log("OK: " + status)
            },
            error: function(xhr,status,error) {
                console.log("NOT OK: " + xhr + " " + status + " " + error)
            }
});

We will get an error:

> POST http://localhost:5000/cors-issue/ 
> XMLHttpRequest cannot load http://localhost:5000/cors-issue/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access. The response had HTTP status code 404.
> NOT OK: [object Object] error 

Where I made a mistake?

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:9 (4 by maintainers)

github_iconTop GitHub Comments

4reactions
lomigmegardcommented, Jun 11, 2016

Hi Daniel,

Short answer

The correct url to use in your AJAX call is http://localhost:5000/cors-issue (no trailing slash). That’s where the discrepancy with your CURL command comes from. With the trailing slash, both clients (jquery and curl) will return a 404, this has nothing to do with CORS.

Quick fix: remove the trailing slash or change your http route definition (particularly look at the pathEndOrSingleSlash directive).

Longer answer

The above fix will only address this specific problem, but in the general case any rejected request (by the akka-http directives) will not be properly marked with the CORS headers. The reason is that the CORS library is based on directives that add headers to the HttpResponse. When a request is rejected, it will go through the cors directives untouched.

What you want is to handle rejection before applying the cors directive. That way the CORS headers can be added to all responses, including the rejected ones.

A possible pattern is as follow:

val routes: Route = handleRejections(CorsDirectives.corsRejectionHandler) {
    cors(settings) {
      handleRejections(RejectionHandler.default) {
        path("cors-issue") {
          post {
            complete(HttpResponse(200))
          }
        }
      }
    }
  }

Test it with:

curl -i -XPOST -H "Origin:http://localhost:5000"  "http://localhost:5000/cors-issue"

You see in the response the correct Access-Control-Allow-Origin header.

Now try an invalid path (your original issue):

curl -i -XPOST -H "Origin:http://localhost:5000"  "http://localhost:5000/xxx"

You still get the Access-Control-Allow-Origin header with a 404 response.


I know this pattern has to be highlighted in the documentation. I will try to improve it soon.

0reactions
l15k4commented, Oct 16, 2020

Yeah, there is 4 more tests which pass except for the one that tests that response headers are set for request that times out, ie : withRequestTimeout(20.millis)

Read more comments on GitHub >

github_iconTop Results From Across the Web

Reason: CORS header 'Access-Control-Allow-Origin' missing
The response to the CORS request is missing the required Access-Control-Allow-Origin header, which is used to determine whether or not the ...
Read more >
Access-Control-Allow-Origin: * not working? - Stack Overflow
Enabling Access-Control-Allow-Origin header in the response is not sufficient. Server side implementation should also provide proper ...
Read more >
3 Ways to Fix the CORS Error — and How the Access-Control ...
In short, no. The access-control-allow-origin plugin essentially turns off the browser's same-origin policy. For every request, it will add the ...
Read more >
Resolve the "No 'Access-Control-Allow-Origin' header" error ...
Confirm the origin's cross-origin resource sharing (CORS) policy allows the origin to return the Access-Control-Allow-Origin header ... Note: If you receive ...
Read more >
Is Access-Control-Allow-Origin: * insecure?
The Access-Control-Allow-Origin specifies the allowed origin that can make cross-origin requests. The special value * means “all origins” which ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found