Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save joshuataylor/111870e15b83ce29761efc9ac1b5c69d to your computer and use it in GitHub Desktop.
Save joshuataylor/111870e15b83ce29761efc9ac1b5c69d to your computer and use it in GitHub Desktop.
So you have setup your API to accept CORS requests on certain paths on your API using [cors_plug](https://github.com/mschae/cors_plug) or [corsica](https://github.com/whatyouhide/corsica) and you are wondering how you test this with ExUnit.
## Back to basics: Does the endpoint actually work?
Well the first thing to do is to check if your endpoint is actually working with CORS.
You can do this via cURL:
curl http://localhost:4000/api/posts -v -H "Origin: https://example.com"
You will need to change the URL to your API Endpoint and your Origin to the URL you have allowed to access this endpoint.
If you would like to test this with an example endpoint, I've setup a heroku app at [https://cors-example-phoenix.herokuapp.com/api/posts](https://cors-example-phoenix.herokuapp.com/api/posts) you can try.
You should then see the output of the command, hopefully containing the `access-control-allow-origin` header:
* Trying ::1:4000...
* TCP_NODELAY set
* connect to ::1 port 4000 failed: Connection refused
* Trying 127.0.0.1:4000...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 4000 (#0)
> GET /api/posts HTTP/1.1
> Host: localhost:4000
> User-Agent: curl/7.67.0
> Accept: */*
> Origin: https://example.com
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< server: Cowboy
< date: Thu, 19 Dec 2019 14:17:33 GMT
< content-length: 222222
< content-type: application/json; charset=utf-8
< cache-control: max-age=0, private, must-revalidate
< access-control-allow-credentials: true
< access-control-allow-origin: https://example.com
< x-request-id: 3ngsmtk913a87kadq00017l8
If it does not contain the `access-control-allow-origin` header then the request either did not go through CORS correctly (failed to validate) or something else is going on. Corsica (which I recommend) [supports logging](https://hexdocs.pm/corsica/Corsica.html#module-logging) which I *highly* recommend you enable when playing around with cors in dev mode as it'll help you understand what is actually going on under the hood.
With corsica, you can see this in the logs:
[debug] Simple CORS request from Origin "https://foobar.com" is not allowed
If it does work and you do have the `access-control-allow-origin` header, change the Origin to something that DOES NOT match the origin you've set in your app and you shouldn't see the header.
## Testing with ExUnit
Your test can now look like this:
test "CORS will only work with example.com", %{conn: conn} do
assert conn
|> put_req_header("origin", "https://example.com")
|> get("/api/posts", %{q: "90210"})
|> get_resp_header("access-control-allow-origin") == ["https://example.com"]
assert conn
|> put_req_header("origin", "https://foobar.com")
|> get("/api/posts", %{q: "90210"})
|> get_resp_header("access-control-allow-origin") == []
end
As you can see, we use `put_req_header("origin", "https://foobar.com")` before making the request to set the origin as the URL we want to test. Since ExUnit actually starts a proper web server with Cowboy then does routing with Plug (if using Phoenix), we can test things like this super easily.
I've got an example repo setup on [Github](https://github.com/joshuataylor/phoenix-cors-example).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment