CORS problem

Hi all! I am running an Elm frontend that talks to a Phoenix backend. They are having trouble communicating. I am getting this error on POST requests:

(1)

[info] OPTIONS /api/v1/users
[error] Invalid preflight CORS request because the header "content-type" is not in :allow_headers
[info] Sent 200 in 17ms

My Corsica Plug config is below in (3). I’ve checked that the request header has the line (2) it should. So I think the request from Elm is OK, but Phoenix is not handing it correctly. I’ve posted all the info on the request in (4).

Any idea what’s going on??

(2)

Access-Control-Request-Headers:content-type

(3)

plug Corsica, origins: ["http://localhost:5000", "https://elm-docviewer.herokuapp.com"],
    allow_headers: ["content-type"]

(4)

Request URL:http://localhost:4000/api/v1/users
Request Method:OPTIONS
Status Code:200 OK
Remote Address:127.0.0.1:4000
Referrer Policy:no-referrer-when-downgrade

Response Headers
view source
cache-control:max-age=0, private, must-revalidate
content-length:0
date:Sat, 13 May 2017 16:09:09 GMT
server:Cowboy
x-request-id:ldd9bt0qi67tu87smtfpbr190cc67uh0

Request Headers
view source
Accept:*/*
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:localhost:4000
Origin:http://localhost:5000
Referer:http://localhost:5000/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36
2 Likes

@jxxcarlson mh, this is weird. Can you either provide a minimal example to reproduce this, or put a plug right before plug Corsica with something like

plug :print_header

defp print_header(conn, _opts) do
  IO.inspect(get_req_header(conn, "access-control-allow-headers"))
end

and let me know what gets printed? It would also be interesting to know where your plug Corsica resides. Oh and also, Corsica and Plug versions :slight_smile:

1 Like

@whatyouhide – here is what I have found so far.

A. The diagnostic using plug :print_header
B. The full output of conn
C. The diagnostic code and plug Corsica – these are in lib/text_api/endpoint.ex

A. The diagnostic using plug :print_header

----
access-control-allow-headers:
[info] OPTIONS /api/v1/users
[]
----

B. The result of adding IO.inspect(conn) to the print_header plug.
Note this substring: {"access-control-request-headers", "content-type"}

%Plug.Conn{adapter: {Plug.Adapters.Cowboy.Conn, :...}, assigns: %{},
 before_send: [#Function<1.85483275/1 in Plug.Logger.call/2>,
  #Function<0.111727833/1 in Phoenix.LiveReloader.before_send_inject_reloader/2>],
 body_params: %{}, cookies: %Plug.Conn.Unfetched{aspect: :cookies},
 halted: false, host: "localhost", method: "OPTIONS", owner: #PID<0.571.0>,
 params: %{}, path_info: ["api", "v1", "users"], path_params: %{},
 peer: {{127, 0, 0, 1}, 61071}, port: 4000,
 private: %{phoenix_endpoint: TextApi.Endpoint,
   plug_session_fetch: #Function<1.131660147/1 in Plug.Session.fetch_session/1>},
 query_params: %{}, query_string: "", remote_ip: {127, 0, 0, 1},
 req_cookies: %Plug.Conn.Unfetched{aspect: :cookies},
 req_headers: [{"host", "localhost:4000"}, {"connection", "keep-alive"},
  {"access-control-request-method", "POST"},
  {"origin", "http://localhost:5000"},
  {"user-agent",
   "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"},
  {"access-control-request-headers", "content-type"}, {"accept", "*/*"},
  {"referer", "http://localhost:5000/"},
  {"accept-encoding", "gzip, deflate, sdch, br"},
  {"accept-language", "en-US,en;q=0.8"}], request_path: "/api/v1/users",
 resp_body: nil, resp_cookies: %{},
 resp_headers: [{"cache-control", "max-age=0, private, must-revalidate"},
  {"x-request-id", "jgi90edkso4nvtsdn5p3ej9ful49cb7r"}], scheme: :http,
 script_name: [],
 secret_key_base: "7RfnGD+uh9mZAPkYYLe9MCSC67m6m3M2tgLGkfwzDDKFxzKsh3E1AoYAbFVSFxtB",
 state: :unset, status: nil}
----
[error] Invalid preflight CORS request because the header "content-type" is not in :allow_headers
[info] Sent 200 in 90ms

C. Code paragraph at the end of lib/tex_api/endpoint.ex:

 defp print_header(conn, _opts) do
   IO.puts "\n----\naccess-control-allow-headers:"
   IO.inspect(get_req_header(conn, "access-control-allow-headers"))
   IO.puts "----"
   IO.inspect(conn)
   IO.puts "----"
 end

  plug :print_header
  plug Corsica, log: [rejected: :error]

  plug Corsica, origins: ["http://localhost:5000", "https://elm-docviewer.herokuapp.com"],
    allow_headers: ["content-type"]
  plug TextApi.Router

First of all, sorry for the mess, I meant for you to inspect get_req_header(conn, "access-control-request-headers") but got the header wrong :sweat_smile:

Regardless, if the code you showed at the end:

plug :print_header
  plug Corsica, log: [rejected: :error]

  plug Corsica, origins: ["http://localhost:5000", "https://elm-docviewer.herokuapp.com"],
    allow_headers: ["content-type"]
  plug TextApi.Router

is what you’re actually using, then the problem is the double call to plug Corsica. The request would hit the plug Corsica, log: [rejected: :error] line and that call doesn’t specify Corsica options other than :log, so :allow_headers defaults to [] (no headers are allowed).

If the code above is what you actually have, then replace it with

plug Corsica,
  log: [rejected: :error],
  origins: [...],
  allow_headers: ["content-type"]

and it should work. If the code above is not what you have, let me know :slight_smile:

1 Like

All working now – thank you very much!

1 Like