Skip to content

Commit

Permalink
Merge pull request #16 from somlor/acao-null-string-if-invalid
Browse files Browse the repository at this point in the history
Fix return value for origin when none matched
  • Loading branch information
mschae committed Mar 11, 2016
2 parents 0ed8ab9 + ee09c84 commit 9b76993
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 8 deletions.
24 changes: 18 additions & 6 deletions lib/cors_plug.ex
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,18 @@ defmodule CORSPlug do
end

def init(options) do
Dict.merge defaults, options
Keyword.merge(defaults, options)
end

def call(conn, options) do
conn = put_in conn.resp_headers, conn.resp_headers ++ headers(conn, options)
conn = put_in(conn.resp_headers, conn.resp_headers ++ headers(conn, options))
case conn.method do
"OPTIONS" -> halt send_resp conn, 204, ""
"OPTIONS" -> conn |> send_resp(204, "") |> halt
_method -> conn
end
end

# headers specific to OPTIONS request
defp headers(conn = %Plug.Conn{method: "OPTIONS"}, options) do
headers(%{conn | method: nil}, options) ++ [
{"access-control-max-age", "#{options[:max_age]}"},
Expand All @@ -35,6 +36,7 @@ defmodule CORSPlug do
]
end

# universal headers
defp headers(conn, options) do
[
{"access-control-allow-origin", origin(options[:origin], conn)},
Expand All @@ -43,15 +45,25 @@ defmodule CORSPlug do
]
end

# normalize non-list to list
defp origin(key, conn) when not is_list(key) do
key |> List.wrap |> origin(conn)
origin(List.wrap(key), conn)
end

# whitelist internal requests
defp origin([:self], conn) do
get_req_header(conn, "origin") |> List.first || "*"
end
defp origin(["*"], _conn), do: "*"

# return "*" if origin list is ["*"]
defp origin(["*"], _conn) do
"*"
end

# return request origin if in origin list, otherwise "null" string
# see: https://www.w3.org/TR/cors/#access-control-allow-origin-response-header
defp origin(origins, conn) when is_list(origins) do
req_origin = get_req_header(conn, "origin") |> List.first
if req_origin in origins, do: req_origin, else: nil
if req_origin in origins, do: req_origin, else: "null"
end
end
4 changes: 2 additions & 2 deletions test/cors_plug_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ defmodule CORSPlugTest do
get_resp_header(conn, "access-control-allow-origin")
end

test "returns nil when the origin is invalid" do
test "returns null string when the origin is invalid" do
opts = CORSPlug.init(origin: ["example1.com"])
conn = conn(:get, "/", nil, headers: [{"origin", "example2.com"}])

conn = CORSPlug.call(conn, opts)
assert [nil] == get_resp_header conn, "access-control-allow-origin"
assert ["null"] == get_resp_header conn, "access-control-allow-origin"
end

test "returns the request host when origin is :self" do
Expand Down

0 comments on commit 9b76993

Please sign in to comment.