Problem with 'Access-Control-Allow-Origin'
See original GitHub issueHi, 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:
- Created 7 years ago
- Comments:9 (4 by maintainers)
Top 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 >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
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 thecors
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:
Test it with:
You see in the response the correct
Access-Control-Allow-Origin
header.Now try an invalid path (your original issue):
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.
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)