1
0
Fork 0
mirror of https://github.com/edgurgel/httparrot synced 2025-04-05 16:22:32 -04:00

Merge pull request #32 from alex-strizhakov/master

updating to cowboy 2.5.0
This commit is contained in:
Eduardo Gurgel 2019-06-30 13:47:08 +12:00 committed by GitHub
commit 545101d50c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
54 changed files with 790 additions and 554 deletions

1
.gitignore vendored
View file

@ -3,3 +3,4 @@
erl_crash.dump erl_crash.dump
*.ez *.ez
/doc /doc
.elixir_ls

View file

@ -2,11 +2,33 @@ language: elixir
notifications: notifications:
recipients: recipients:
- eduardo@gurgel.me - eduardo@gurgel.me
elixir: cache:
- 1.4.2 directories:
otp_release: - _build
- 18.0 - deps
- 18.1
- 19.0
sudo: false sudo: false
script: mix test script: mix test
matrix:
include:
- elixir: 1.5
otp_release: 19.3
- elixir: 1.5
otp_release: 20.3
- elixir: 1.6
otp_release: 19.3
- elixir: 1.6
otp_release: 20.3
- elixir: 1.6
otp_release: 21.0
- elixir: 1.7
otp_release: 19.3
- elixir: 1.7
otp_release: 20.3
- elixir: 1.7
otp_release: 21.0
- elixir: 1.8
otp_release: 20.3
- elixir: 1.8
otp_release: 21.0
- elixir: 1.8
otp_release: 22.0.1

View file

@ -11,91 +11,116 @@ defmodule HTTParrot do
end end
def start(_type, _args) do def start(_type, _args) do
dispatch = :cowboy_router.compile([ dispatch =
{:_, [ {'/', :cowboy_static, {:priv_file, :httparrot, "index.html"}}, :cowboy_router.compile([
{'/ip', HTTParrot.IPHandler, []}, {:_,
{'/user-agent', HTTParrot.UserAgentHandler, []}, [
{'/headers', HTTParrot.HeadersHandler, []}, {"/", :cowboy_static, {:priv_file, :httparrot, "index.html"}},
{'/get', HTTParrot.GetHandler, []}, {"/ip", HTTParrot.IPHandler, []},
{'/post', HTTParrot.PHandler, []}, {"/user-agent", HTTParrot.UserAgentHandler, []},
{'/put', HTTParrot.PHandler, []}, {"/headers", HTTParrot.HeadersHandler, []},
{'/patch', HTTParrot.PHandler, []}, {"/get", HTTParrot.GetHandler, []},
{'/delete', HTTParrot.DeleteHandler, []}, {"/post", HTTParrot.PHandler, []},
{'/deflate', HTTParrot.DeflateHandler, []}, {"/put", HTTParrot.PHandler, []},
{'/gzip', HTTParrot.GzipHandler, []}, {"/patch", HTTParrot.PHandler, []},
{'/status/:code', [code: :int], HTTParrot.StatusCodeHandler, []}, {"/delete", HTTParrot.DeleteHandler, []},
{'/redirect/:n', HTTParrot.RedirectHandler, []}, {"/deflate", HTTParrot.DeflateHandler, []},
{'/redirect-to', HTTParrot.RedirectToHandler, []}, {"/gzip", HTTParrot.GzipHandler, []},
{'/relative-redirect/:n', HTTParrot.RelativeRedirectHandler, []}, {"/status/:code", [code: :int], HTTParrot.StatusCodeHandler, []},
{'/cookies', HTTParrot.CookiesHandler, []}, {"/redirect/:n", HTTParrot.RedirectHandler, []},
{'/cookies/set[/:name/:value]', HTTParrot.SetCookiesHandler, []}, {"/redirect-to", HTTParrot.RedirectToHandler, []},
{'/cookies/delete', HTTParrot.DeleteCookiesHandler, []}, {"/relative-redirect/:n", HTTParrot.RelativeRedirectHandler, []},
{'/basic-auth/:user/:passwd', HTTParrot.BasicAuthHandler, []}, {"/cookies", HTTParrot.CookiesHandler, []},
{'/hidden-basic-auth/:user/:passwd', HTTParrot.HiddenBasicAuthHandler, []}, {"/cookies/set[/:name/:value]", HTTParrot.SetCookiesHandler, []},
{'/stream/:n', HTTParrot.StreamHandler, []}, {"/cookies/delete", HTTParrot.DeleteCookiesHandler, []},
{'/stream-bytes/:n', HTTParrot.StreamBytesHandler, []}, {"/basic-auth/:user/:passwd", HTTParrot.BasicAuthHandler, []},
{'/delay/:n', HTTParrot.DelayedHandler, []}, {"/hidden-basic-auth/:user/:passwd", HTTParrot.HiddenBasicAuthHandler, []},
{'/html', :cowboy_static, {:priv_file, :httparrot, "html.html"}}, {"/stream/:n", HTTParrot.StreamHandler, []},
{'/deny', HTTParrot.DenyHandler, []}, {"/stream-bytes/:n", HTTParrot.StreamBytesHandler, []},
{'/cache', HTTParrot.CacheHandler, []}, {"/delay/:n", HTTParrot.DelayedHandler, []},
{'/robots.txt', HTTParrot.RobotsHandler, []}, {"/html", :cowboy_static, {:priv_file, :httparrot, "html.html"}},
{'/base64/:value', HTTParrot.Base64Handler, []}, {"/deny", HTTParrot.DenyHandler, []},
{'/image', HTTParrot.ImageHandler, []}, {"/cache", HTTParrot.CacheHandler, []},
{'/websocket', HTTParrot.WebsocketHandler, []}, {"/robots.txt", HTTParrot.RobotsHandler, []},
{'/response-headers', HTTParrot.ResponseHeadersHandler, []}, {"/base64/:value", HTTParrot.Base64Handler, []},
{'/store/:key', HTTParrot.StoreRequestHandler, []}, {"/image", HTTParrot.ImageHandler, []},
{'/retrieve/:key', HTTParrot.RetrieveRequestHandler, []} ] } {"/websocket", HTTParrot.WebsocketHandler, []},
]) {"/response-headers", HTTParrot.ResponseHeadersHandler, []},
{"/store/:key", HTTParrot.StoreRequestHandler, []},
{"/retrieve/:key", HTTParrot.RetrieveRequestHandler, []}
]}
])
{:ok, http_port} = Application.fetch_env(:httparrot, :http_port) {:ok, http_port} = Application.fetch_env(:httparrot, :http_port)
IO.puts "Starting HTTParrot on port #{http_port}" IO.puts("Starting HTTParrot on port #{http_port}")
{:ok, _} = :cowboy.start_http(:http, 100,
[port: http_port], {:ok, _} =
[env: [dispatch: dispatch], :cowboy.start_clear(
onresponse: &prettify_json/4]) :http,
[port: http_port],
%{env: %{dispatch: dispatch}}
)
if Application.get_env(:httparrot, :ssl, false) do if Application.get_env(:httparrot, :ssl, false) do
{:ok, https_port} = Application.fetch_env(:httparrot, :https_port) {:ok, https_port} = Application.fetch_env(:httparrot, :https_port)
priv_dir = :code.priv_dir(:httparrot) priv_dir = :code.priv_dir(:httparrot)
IO.puts "Starting HTTParrot on port #{https_port} (SSL)" IO.puts("Starting HTTParrot on port #{https_port} (SSL)")
{:ok, _} = :cowboy.start_https(:https, 100,
[port: https_port, cacertfile: priv_dir ++ '/ssl/server-ca.crt', {:ok, _} =
certfile: priv_dir ++ '/ssl/server.crt', keyfile: priv_dir ++ '/ssl/server.key'], :cowboy.start_tls(
[env: [dispatch: dispatch], onresponse: &prettify_json/4]) :https,
[
port: https_port,
cacertfile: priv_dir ++ '/ssl/server-ca.crt',
certfile: priv_dir ++ '/ssl/server.crt',
keyfile: priv_dir ++ '/ssl/server.key'
],
%{env: %{dispatch: dispatch}}
)
end end
if unix_socket_supported?() && Application.get_env(:httparrot, :unix_socket, false) do if unix_socket_supported?() && Application.get_env(:httparrot, :unix_socket, false) do
{:ok, socket_path} = Application.fetch_env(:httparrot, :socket_path) {:ok, socket_path} = Application.fetch_env(:httparrot, :socket_path)
if File.exists?(socket_path), do: File.rm(socket_path) if File.exists?(socket_path), do: File.rm(socket_path)
IO.puts "Starting HTTParrot on unix socket #{socket_path}" IO.puts("Starting HTTParrot on unix socket #{socket_path}")
{:ok, _} = :cowboy.start_http(:http_unix, 100,
[port: 0, ip: {:local, socket_path}], {:ok, _} =
[env: [dispatch: dispatch], onresponse: &prettify_json/4]) :cowboy.start_clear(
:http_unix,
[port: 0, ip: {:local, socket_path}],
%{env: %{dispatch: dispatch}}
)
end end
Supervisor.start_link([ Supervisor.start_link(
worker(ConCache, [[ [
ttl_check: :timer.minutes(5), {ConCache,
ttl: :timer.hours(12) [
], [name: :requests_registry]]) ttl_check_interval: :timer.minutes(5),
], strategy: :one_for_one) global_ttl: :timer.hours(12),
name: :requests_registry
]}
],
strategy: :one_for_one
)
end end
def stop(_State), do: :ok def stop(_State), do: :ok
def prettify_json(status, headers, body, req) do def prettify_json(status, headers, body, req) do
if JSX.is_json? body do if JSX.is_json?(body) do
body = JSX.prettify!(body) body = JSX.prettify!(body)
headers = List.keystore(headers, "content-length", 0, {"content-length", Integer.to_charlist(String.length(body))})
{:ok, req} = :cowboy_req.reply(status, headers, body, req) headers = Map.put(headers, "content-length", Integer.to_charlist(String.length(body)))
req
:cowboy_req.reply(status, headers, body, req)
else else
req req
end end
end end
def unix_socket_supported? do def unix_socket_supported? do
case {:os.type, Integer.parse("#{:erlang.system_info(:otp_release)}")} do case {:os.type(), Integer.parse("#{:erlang.system_info(:otp_release)}")} do
{{:unix, _}, {n, _}} when n >= 19 -> true {{:unix, _}, {n, _}} when n >= 19 -> true
_ -> false _ -> false
end end

View file

@ -12,13 +12,13 @@ defmodule HTTParrot.Base64Handler do
{value, req} = :cowboy_req.binding(:value, req) {value, req} = :cowboy_req.binding(:value, req)
case decode(value) do case decode(value) do
{ :ok, result } -> {false, req, result} {:ok, result} -> {false, req, result}
:error -> {true, req, state} :error -> {true, req, state}
end end
end end
defp decode(value) do defp decode(value) do
pad(value) |> Base.url_decode64 pad(value) |> Base.url_decode64()
end end
defp pad(value) do defp pad(value) do

View file

@ -8,6 +8,7 @@ defmodule HTTParrot.BasicAuthHandler do
{user, req} = :cowboy_req.binding(:user, req) {user, req} = :cowboy_req.binding(:user, req)
{passwd, req} = :cowboy_req.binding(:passwd, req) {passwd, req} = :cowboy_req.binding(:passwd, req)
{:ok, auth, req} = :cowboy_req.parse_header("authorization", req) {:ok, auth, req} = :cowboy_req.parse_header("authorization", req)
case auth do case auth do
{"basic", {^user, ^passwd}} -> {true, req, user} {"basic", {^user, ^passwd}} -> {true, req, user}
_ -> {{false, "Basic realm=\"Fake Realm\""}, req, state} _ -> {{false, "Basic realm=\"Fake Realm\""}, req, state}
@ -23,6 +24,6 @@ defmodule HTTParrot.BasicAuthHandler do
end end
defp response(user) do defp response(user) do
[authenticated: true, user: user] |> JSX.encode! [authenticated: true, user: user] |> JSX.encode!()
end end
end end

View file

@ -19,6 +19,6 @@ defmodule HTTParrot.CacheHandler do
end end
defp response(info) do defp response(info) do
info |> JSX.encode! info |> JSX.encode!()
end end
end end

View file

@ -9,12 +9,12 @@ defmodule HTTParrot.CookiesHandler do
end end
def get_json(req, state) do def get_json(req, state) do
{cookies, req} = :cowboy_req.cookies(req) cookies = :cowboy_req.parse_cookies(req)
cookies = if cookies == [], do: [{}], else: cookies cookies = if cookies == [], do: [{}], else: cookies
{response(cookies), req, state} {response(cookies), req, state}
end end
defp response(cookies) do defp response(cookies) do
[cookies: cookies] |> JSX.encode! [cookies: cookies] |> JSX.encode!()
end end
end end

View file

@ -3,8 +3,8 @@ defmodule HTTParrot.Cowboy do
methods = Keyword.get(opts, :methods, []) methods = Keyword.get(opts, :methods, [])
quote bind_quoted: [methods: methods] do quote bind_quoted: [methods: methods] do
def init(_transport, _req, _opts) do def init(req, state) do
{:upgrade, :protocol, :cowboy_rest} {:cowboy_rest, req, state}
end end
def allowed_methods(req, state) do def allowed_methods(req, state) do

View file

@ -10,18 +10,18 @@ defmodule HTTParrot.DeflateHandler do
end end
def get_json(req, state) do def get_json(req, state) do
zlib = :zlib.open zlib = :zlib.open()
:zlib.deflateInit(zlib) :zlib.deflateInit(zlib)
{info, req} = GeneralRequestInfo.retrieve(req) {info, req} = GeneralRequestInfo.retrieve(req)
req = :cowboy_req.set_resp_header("content-encoding", "deflate", req) req = :cowboy_req.set_resp_header("content-encoding", "deflate", req)
json = response(info) |> JSX.prettify! json = response(info) |> JSX.prettify!()
response = :zlib.deflate(zlib, json, :finish) response = :zlib.deflate(zlib, json, :finish)
:zlib.deflateEnd(zlib) :zlib.deflateEnd(zlib)
{response, req, state} {response, req, state}
end end
defp response(info) do defp response(info) do
info |> JSX.encode! info |> JSX.encode!()
end end
end end

View file

@ -3,9 +3,10 @@ defmodule HTTParrot.DelayedHandler do
use HTTParrot.Cowboy, methods: ~w(GET HEAD OPTIONS) use HTTParrot.Cowboy, methods: ~w(GET HEAD OPTIONS)
def malformed_request(req, state) do def malformed_request(req, state) do
{n, req} = :cowboy_req.binding(:n, req) n = :cowboy_req.binding(:n, req)
try do try do
n = n |> String.to_integer |> min(10) |> max(0) n = n |> String.to_integer() |> min(10) |> max(0)
{false, req, n} {false, req, n}
rescue rescue
ArgumentError -> {true, req, state} ArgumentError -> {true, req, state}
@ -18,11 +19,11 @@ defmodule HTTParrot.DelayedHandler do
def get_json(req, n) do def get_json(req, n) do
{info, req} = GeneralRequestInfo.retrieve(req) {info, req} = GeneralRequestInfo.retrieve(req)
:timer.sleep(n*1000) :timer.sleep(n * 1000)
{response(info), req, n} {response(info), req, n}
end end
defp response(info) do defp response(info) do
info |> JSX.encode! info |> JSX.encode!()
end end
end end

View file

@ -5,7 +5,7 @@ defmodule HTTParrot.DeleteCookiesHandler do
use HTTParrot.Cowboy, methods: ~w(GET HEAD OPTIONS) use HTTParrot.Cowboy, methods: ~w(GET HEAD OPTIONS)
def malformed_request(req, state) do def malformed_request(req, state) do
{qs_vals, req} = :cowboy_req.qs_vals(req) qs_vals = :cowboy_req.parse_qs(req)
if Enum.empty?(qs_vals), do: {true, req, state}, else: {false, req, qs_vals} if Enum.empty?(qs_vals), do: {true, req, state}, else: {false, req, qs_vals}
end end
@ -14,15 +14,18 @@ defmodule HTTParrot.DeleteCookiesHandler do
end end
def get_json(req, qs_vals) do def get_json(req, qs_vals) do
req = Enum.reduce qs_vals, req, fn({name, value}, req) -> req =
delete_cookie(name, value, req) Enum.reduce(qs_vals, req, fn {name, value}, req ->
end delete_cookie(name, value, req)
{:ok, req} = :cowboy_req.reply(302, [{"location", "/cookies"}], "Redirecting...", req) end)
req = :cowboy_req.reply(302, %{"location" => "/cookies"}, "Redirecting...", req)
{:halt, req, qs_vals} {:halt, req, qs_vals}
end end
defp delete_cookie(name, true, req), do: delete_cookie(name, "", req) defp delete_cookie(name, true, req), do: delete_cookie(name, "", req)
defp delete_cookie(name, value, req) do defp delete_cookie(name, value, req) do
:cowboy_req.set_resp_cookie(name, value, [path: "/", max_age: 0], req) :cowboy_req.set_resp_cookie(name, value, req, %{path: "/", max_age: 0})
end end
end end

View file

@ -16,6 +16,6 @@ defmodule HTTParrot.DeleteHandler do
end end
defp response(info) do defp response(info) do
info |> JSX.encode! info |> JSX.encode!()
end end
end end

View file

@ -1,14 +1,15 @@
defmodule HTTParrot.GeneralRequestInfo do defmodule HTTParrot.GeneralRequestInfo do
def retrieve(req) do def retrieve(req) do
{args, req} = :cowboy_req.qs_vals(req) args = :cowboy_req.parse_qs(req)
{headers, req} = :cowboy_req.headers(req) headers = :cowboy_req.headers(req)
{url, req} = :cowboy_req.url(req) url = IO.iodata_to_binary(:cowboy_req.uri(req))
{{ip, port}, req} = :cowboy_req.peer(req) {ip, _port} = :cowboy_req.peer(req)
ip = case {ip, port} do ip =
{:local, _} -> "" case ip do
_ -> :inet_parse.ntoa(ip) |> to_string {127, 0, 0, 1} -> ""
end _ -> :inet_parse.ntoa(ip) |> to_string
end
args = group_by_keys(args) args = group_by_keys(args)
@ -18,11 +19,12 @@ defmodule HTTParrot.GeneralRequestInfo do
@doc """ @doc """
Group by keys and if duplicated keys, aggregate them as a list Group by keys and if duplicated keys, aggregate them as a list
iex> group_by_keys([a: "v1", a: "v2", b: "v3", a: "v4"]) iex> group_by_keys([{"a", "v1"}, {"a", "v2"}, {"b", "v3"}, {"a", "v4"}])
%{a: ["v1", "v2", "v4"], b: "v3"} %{"a" => ["v1", "v2", "v4"], "b" => "v3"}
""" """
@spec group_by_keys(list) :: map @spec group_by_keys(list) :: map
def group_by_keys([]), do: %{} def group_by_keys([]), do: %{}
def group_by_keys(args) do def group_by_keys(args) do
args args
|> Enum.map(fn {k, v} -> %{k => v} end) |> Enum.map(fn {k, v} -> %{k => v} end)

View file

@ -15,6 +15,6 @@ defmodule HTTParrot.GetHandler do
end end
defp response(info) do defp response(info) do
info |> JSX.encode! info |> JSX.encode!()
end end
end end

View file

@ -12,11 +12,11 @@ defmodule HTTParrot.GzipHandler do
def get_json(req, state) do def get_json(req, state) do
{info, req} = GeneralRequestInfo.retrieve(req) {info, req} = GeneralRequestInfo.retrieve(req)
req = :cowboy_req.set_resp_header("content-encoding", "gzip", req) req = :cowboy_req.set_resp_header("content-encoding", "gzip", req)
response = response(info) |> JSX.prettify! |> :zlib.gzip response = response(info) |> JSX.prettify!() |> :zlib.gzip()
{response, req, state} {response, req, state}
end end
defp response(info) do defp response(info) do
info |> JSX.encode! info |> JSX.encode!()
end end
end end

View file

@ -6,11 +6,11 @@ defmodule HTTParrot.HeadersHandler do
end end
def get_json(req, state) do def get_json(req, state) do
{headers, req} = :cowboy_req.headers(req) headers = :cowboy_req.headers(req)
{response(headers), req, state} {response(headers), req, state}
end end
defp response(headers) do defp response(headers) do
[headers: headers] |> JSX.encode! [headers: headers] |> JSX.encode!()
end end
end end

View file

@ -8,11 +8,12 @@ defmodule HTTParrot.HiddenBasicAuthHandler do
This method should be `is_authorized`, but this handler will return 404 if the auth fails This method should be `is_authorized`, but this handler will return 404 if the auth fails
""" """
def resource_exists(req, state) do def resource_exists(req, state) do
{user, req} = :cowboy_req.binding(:user, req) user = :cowboy_req.binding(:user, req)
{passwd, req} = :cowboy_req.binding(:passwd, req) passwd = :cowboy_req.binding(:passwd, req)
{:ok, auth, req} = :cowboy_req.parse_header("authorization", req) auth = :cowboy_req.parse_header("authorization", req)
case auth do case auth do
{"basic", {^user, ^passwd}} -> {true, req, user} {:basic, ^user, ^passwd} -> {true, req, user}
_ -> {false, req, state} _ -> {false, req, state}
end end
end end
@ -26,6 +27,6 @@ defmodule HTTParrot.HiddenBasicAuthHandler do
end end
defp response(user) do defp response(user) do
[authenticated: true, user: user] |> JSX.encode! [authenticated: true, user: user] |> JSX.encode!()
end end
end end

View file

@ -5,12 +5,15 @@ defmodule HTTParrot.ImageHandler do
use HTTParrot.Cowboy, methods: ~w(GET HEAD OPTIONS) use HTTParrot.Cowboy, methods: ~w(GET HEAD OPTIONS)
def content_types_provided(req, state) do def content_types_provided(req, state) do
{[{{"image", "png", []}, :get_png}, {[{{"image", "png", []}, :get_png}, {{"image", "jpeg", []}, :get_jpeg}], req, state}
{{"image", "jpeg", []}, :get_jpeg}], req, state}
end end
@png Base.decode64!("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==") @png Base.decode64!(
@jpeg Base.decode64!("/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=") "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg=="
)
@jpeg Base.decode64!(
"/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k="
)
def get_png(req, state), do: {@png, req, state} def get_png(req, state), do: {@png, req, state}
def get_jpeg(req, state), do: {@jpeg, req, state} def get_jpeg(req, state), do: {@jpeg, req, state}

View file

@ -9,11 +9,13 @@ defmodule HTTParrot.IPHandler do
end end
def get_json(req, state) do def get_json(req, state) do
{{ip, _port}, req} = :cowboy_req.peer(req) {ip, _port} = :cowboy_req.peer(req)
{:ok, forwarded_for, _} = :cowboy_req.parse_header(<<"x-forwarded-for">>, req) forwarded_for = :cowboy_req.parse_header("x-forwarded-for", req)
case forwarded_for do case forwarded_for do
:undefined -> :undefined ->
{response(ip), req, state} {response(ip), req, state}
_ -> _ ->
{response(to_tuple(forwarded_for)), req, state} {response(to_tuple(forwarded_for)), req, state}
end end
@ -23,16 +25,16 @@ defmodule HTTParrot.IPHandler do
client_ip client_ip
|> hd |> hd
|> String.split(".") |> String.split(".")
|> Enum.map(fn(x) -> String.to_integer(x) end) |> Enum.map(fn x -> String.to_integer(x) end)
|> List.to_tuple |> List.to_tuple()
end end
defp response(:local) do defp response({127, 0, 0, 1}) do
[origin: ""] |> JSX.encode! [origin: ""] |> JSX.encode!()
end end
defp response(ip) do defp response(ip) do
ip = :inet_parse.ntoa(ip) |> to_string ip = :inet_parse.ntoa(ip) |> to_string
[origin: ip] |> JSX.encode! [origin: ip] |> JSX.encode!()
end end
end end

View file

@ -4,25 +4,27 @@ defmodule HTTParrot.PHandler do
""" """
alias HTTParrot.GeneralRequestInfo alias HTTParrot.GeneralRequestInfo
def init(_transport, _req, _opts) do def init(req, state) do
{:upgrade, :protocol, :cowboy_rest} {:cowboy_rest, req, state}
end end
@doc """ @doc """
When a request is made to /post, allowed_methods will return POST for example When a request is made to /post, allowed_methods will return POST for example
""" """
def allowed_methods(req, state) do def allowed_methods(req, state) do
{path, req} = :cowboy_req.path(req) path = :cowboy_req.path(req)
path = String.slice(path, 1..-1) path = String.slice(path, 1..-1)
{[String.upcase(path)], req, state} {[String.upcase(path)], req, state}
end end
def content_types_accepted(req, state) do def content_types_accepted(req, state) do
{[{{"application", "json", :*}, :post_binary}, {[
{{"application", "octet-stream", :*}, :post_binary}, {{"application", "json", :*}, :post_binary},
{{"text", "plain", :*}, :post_binary}, {{"application", "octet-stream", :*}, :post_binary},
{{"application", "x-www-form-urlencoded", :*}, :post_form}, {{"text", "plain", :*}, :post_binary},
{{"multipart", "form-data", :*}, :post_multipart}], req, state} {{"application", "x-www-form-urlencoded", :*}, :post_form},
{{"multipart", "form-data", :*}, :post_multipart}
], req, state}
end end
def content_types_provided(req, state) do def content_types_provided(req, state) do
@ -30,29 +32,31 @@ defmodule HTTParrot.PHandler do
end end
def post_form(req, _state) do def post_form(req, _state) do
{:ok, body, req} = :cowboy_req.body_qs(req) {:ok, body, req} = :cowboy_req.read_urlencoded_body(req)
post(req, [form: body, data: "", json: nil]) post(req, form: body, data: "", json: nil)
end end
def post_binary(req, _state) do def post_binary(req, _state) do
{:ok, body, req} = handle_binary(req) {:ok, body, req} = handle_binary(req)
if String.valid?(body) do if String.valid?(body) do
if JSX.is_json?(body) do if JSX.is_json?(body) do
post(req, [form: [{}], data: body, json: JSX.decode!(body)]) post(req, form: [{}], data: body, json: JSX.decode!(body))
else else
post(req, [form: [{}], data: body, json: nil]) post(req, form: [{}], data: body, json: nil)
end end
else else
# Octet-stream # Octet-stream
body = Base.encode64(body) body = Base.encode64(body)
post(req, [form: [{}], data: "data:application/octet-stream;base64," <> body, json: nil]) post(req, form: [{}], data: "data:application/octet-stream;base64," <> body, json: nil)
end end
end end
def handle_binary(req, chunks \\ []) do def handle_binary(req, chunks \\ []) do
case :cowboy_req.body(req) do case :cowboy_req.read_body(req) do
{:ok, chunk, req} -> {:ok, chunk, req} ->
{:ok, Enum.join(chunks ++ [chunk]), req} {:ok, Enum.join(chunks ++ [chunk]), req}
{:more, chunk, req} -> {:more, chunk, req} ->
handle_binary(req, chunks ++ [chunk]) handle_binary(req, chunks ++ [chunk])
end end
@ -65,7 +69,7 @@ defmodule HTTParrot.PHandler do
end end
defp response(info, body) do defp response(info, body) do
info ++ body |> JSX.encode! (info ++ body) |> JSX.encode!()
end end
def post_multipart(req, _state) do def post_multipart(req, _state) do
@ -74,22 +78,32 @@ defmodule HTTParrot.PHandler do
file_parts = for file <- parts, elem(file, 0) == :file, do: {elem(file, 1), elem(file, 2)} file_parts = for file <- parts, elem(file, 0) == :file, do: {elem(file, 1), elem(file, 2)}
form_parts = for form <- parts, elem(form, 0) == :form, do: {elem(form, 1), elem(form, 2)} form_parts = for form <- parts, elem(form, 0) == :form, do: {elem(form, 1), elem(form, 2)}
post(req, [form: normalize_list(form_parts), files: normalize_list(file_parts), data: "", json: nil]) post(req,
form: normalize_list(form_parts),
files: normalize_list(file_parts),
data: "",
json: nil
)
end end
def handle_multipart(req, parts \\ []) do def handle_multipart(req, parts \\ []) do
case :cowboy_req.part(req) do case :cowboy_req.read_part(req) do
{:done, req} -> {:ok, parts, req} {:done, req} ->
{:ok, parts, req}
{:ok, headers, req} -> {:ok, headers, req} ->
content_disposition = List.keyfind(headers, "content-disposition", 0) content_disposition = headers["content-disposition"]
if content_disposition do if content_disposition do
case parse_content_disposition_header(content_disposition) do case parse_content_disposition_header(content_disposition) do
%{:type => "form-data", "name" => name, "filename" => _filename} -> %{:type => "form-data", "name" => name, "filename" => _filename} ->
{:ok, file, req} = handle_multipart_body(req) {:ok, file, req} = handle_multipart_body(req)
handle_multipart(req, parts ++ [{:file, name, file}]) handle_multipart(req, parts ++ [{:file, name, file}])
%{:type => "form-data", "name" => name} -> %{:type => "form-data", "name" => name} ->
{:ok, form_part, req} = handle_multipart_body(req) {:ok, form_part, req} = handle_multipart_body(req)
handle_multipart(req, parts ++ [{:form, name, form_part}]) handle_multipart(req, parts ++ [{:form, name, form_part}])
_ -> _ ->
{:ok, parts, req} {:ok, parts, req}
end end
@ -100,17 +114,18 @@ defmodule HTTParrot.PHandler do
end end
defp handle_multipart_body(req, parts \\ []) do defp handle_multipart_body(req, parts \\ []) do
case :cowboy_req.part_body(req) do case :cowboy_req.read_part_body(req) do
{:ok, data, req} -> {:ok, data, req} ->
{:ok, Enum.join(parts ++ [data]), req} {:ok, Enum.join(parts ++ [data]), req}
{:more, data, req} -> {:more, data, req} ->
handle_multipart_body(req, parts ++ [data]) handle_multipart_body(req, parts ++ [data])
end end
end end
defp parse_content_disposition_header(header) do defp parse_content_disposition_header(header) do
parts = elem(header, 1) parts =
|> String.split(";") String.split(header, ";")
|> Enum.map(&String.trim/1) |> Enum.map(&String.trim/1)
for part <- parts, into: %{} do for part <- parts, into: %{} do

View file

@ -5,9 +5,10 @@ defmodule HTTParrot.RedirectHandler do
use HTTParrot.Cowboy, methods: ~w(GET HEAD OPTIONS) use HTTParrot.Cowboy, methods: ~w(GET HEAD OPTIONS)
def malformed_request(req, state) do def malformed_request(req, state) do
{n, req} = :cowboy_req.binding(:n, req) n = :cowboy_req.binding(:n, req)
try do try do
n = n |> String.to_integer |> max(1) n = n |> String.to_integer() |> max(1)
{false, req, n} {false, req, n}
rescue rescue
ArgumentError -> {true, req, state} ArgumentError -> {true, req, state}
@ -18,8 +19,8 @@ defmodule HTTParrot.RedirectHandler do
def previously_existed(req, state), do: {true, req, state} def previously_existed(req, state), do: {true, req, state}
def moved_permanently(req, n) do def moved_permanently(req, n) do
{host_url, req} = :cowboy_req.host_url(req) host_url = IO.iodata_to_binary(:cowboy_req.uri(req))
url = if n > 1, do: "/redirect/#{n-1}", else: "/get" url = if n > 1, do: "/redirect/#{n - 1}", else: "/get"
{{true, host_url <> url}, req, nil} {{true, host_url <> url}, req, nil}
end end
end end

View file

@ -5,7 +5,7 @@ defmodule HTTParrot.RedirectToHandler do
use HTTParrot.Cowboy, methods: ~w(GET HEAD OPTIONS) use HTTParrot.Cowboy, methods: ~w(GET HEAD OPTIONS)
def malformed_request(req, state) do def malformed_request(req, state) do
{url, req} = :cowboy_req.qs_val("url", req, nil) %{url: url} = :cowboy_req.match_qs([{:url, [], nil}], req)
if url, do: {false, req, url}, else: {true, req, state} if url, do: {false, req, url}, else: {true, req, state}
end end

View file

@ -12,7 +12,7 @@ defmodule HTTParrot.RelativeRedirectHandler do
def previously_existed(req, state), do: {true, req, state} def previously_existed(req, state), do: {true, req, state}
def moved_permanently(req, n) do def moved_permanently(req, n) do
url = if n > 1, do: "/redirect/#{n-1}", else: "/get" url = if n > 1, do: "/redirect/#{n - 1}", else: "/get"
{{true, url}, req, nil} {{true, url}, req, nil}
end end
end end

View file

@ -15,10 +15,13 @@ defmodule HTTParrot.RequestStore do
""" """
def retrieve(key) do def retrieve(key) do
entry = ConCache.get(:requests_registry, key) entry = ConCache.get(:requests_registry, key)
case entry do case entry do
nil -> [] nil ->
_ -> []
entry
_ ->
entry
end end
end end

View file

@ -5,7 +5,8 @@ defmodule HTTParrot.ResponseHeadersHandler do
use HTTParrot.Cowboy, methods: ~w(GET HEAD OPTIONS) use HTTParrot.Cowboy, methods: ~w(GET HEAD OPTIONS)
def malformed_request(req, state) do def malformed_request(req, state) do
{qs_vals, req} = :cowboy_req.qs_vals(req) qs_vals = :cowboy_req.parse_qs(req)
if not Enum.empty?(qs_vals) do if not Enum.empty?(qs_vals) do
{false, req, qs_vals} {false, req, qs_vals}
else else
@ -18,13 +19,15 @@ defmodule HTTParrot.ResponseHeadersHandler do
end end
def get_json(req, qs_vals) do def get_json(req, qs_vals) do
req = Enum.reduce qs_vals, req, fn({key, value}, req) -> req =
:cowboy_req.set_resp_header(key, value, req) Enum.reduce(qs_vals, req, fn {key, value}, req ->
end :cowboy_req.set_resp_header(key, value, req)
end)
{response(qs_vals), req, qs_vals} {response(qs_vals), req, qs_vals}
end end
defp response(qs_vals) do defp response(qs_vals) do
qs_vals |> JSX.encode! qs_vals |> JSX.encode!()
end end
end end

View file

@ -9,13 +9,13 @@ defmodule HTTParrot.RetrieveRequestHandler do
end end
def retrieve_stored(req, state) do def retrieve_stored(req, state) do
{key, _} = :cowboy_req.binding(:key, req) key = :cowboy_req.binding(:key, req)
requests = HTTParrot.RequestStore.retrieve(key) requests = HTTParrot.RequestStore.retrieve(key)
HTTParrot.RequestStore.clear(key) HTTParrot.RequestStore.clear(key)
{response(requests), req, state} {response(requests), req, state}
end end
defp response(info) do defp response(info) do
info |> JSX.encode! info |> JSX.encode!()
end end
end end

View file

@ -5,10 +5,11 @@ defmodule HTTParrot.SetCookiesHandler do
use HTTParrot.Cowboy, methods: ~w(GET HEAD OPTIONS) use HTTParrot.Cowboy, methods: ~w(GET HEAD OPTIONS)
def malformed_request(req, state) do def malformed_request(req, state) do
{qs_vals, req} = :cowboy_req.qs_vals(req) qs_vals = :cowboy_req.parse_qs(req)
{name, req} = :cowboy_req.binding(:name, req, nil) name = :cowboy_req.binding(:name, req, nil)
if name do if name do
{value, req} = :cowboy_req.binding(:value, req, nil) value = :cowboy_req.binding(:value, req, nil)
{false, req, List.keystore(qs_vals, name, 0, {name, value})} {false, req, List.keystore(qs_vals, name, 0, {name, value})}
else else
if Enum.empty?(qs_vals), do: {true, req, state}, else: {false, req, qs_vals} if Enum.empty?(qs_vals), do: {true, req, state}, else: {false, req, qs_vals}
@ -20,14 +21,16 @@ defmodule HTTParrot.SetCookiesHandler do
end end
def get_json(req, qs_vals) do def get_json(req, qs_vals) do
req = Enum.reduce qs_vals, req, fn({name, value}, req) -> req =
set_cookie(name, value, req) Enum.reduce(qs_vals, req, fn {name, value}, req ->
end set_cookie(name, value, req)
{:ok, req} = :cowboy_req.reply(302, [{"location", "/cookies"}], "Redirecting...", req) end)
req = :cowboy_req.reply(302, %{"location" => "/cookies"}, "Redirecting...", req)
{:halt, req, qs_vals} {:halt, req, qs_vals}
end end
defp set_cookie(name, value, req) do defp set_cookie(name, value, req) do
:cowboy_req.set_resp_cookie(name, value, [path: "/"], req) :cowboy_req.set_resp_cookie(name, value, req, %{path: "/"})
end end
end end

View file

@ -9,8 +9,8 @@ defmodule HTTParrot.StatusCodeHandler do
end end
def get_json(req, state) do def get_json(req, state) do
{code, req} = :cowboy_req.binding(:code, req) code = :cowboy_req.binding(:code, req)
{:ok, req} = :cowboy_req.reply(code, [], "", req) req = :cowboy_req.reply(code, %{}, "", req)
{:halt, req, state} {:halt, req, state}
end end
end end

View file

@ -6,11 +6,13 @@ defmodule HTTParrot.StoreRequestHandler do
use HTTParrot.Cowboy, methods: ~w(GET POST PUT HEAD OPTIONS) use HTTParrot.Cowboy, methods: ~w(GET POST PUT HEAD OPTIONS)
def content_types_accepted(req, state) do def content_types_accepted(req, state) do
{[{{"application", "json", :*}, :post_binary}, {[
{{"application", "octet-stream", :*}, :post_binary}, {{"application", "json", :*}, :post_binary},
{{"text", "plain", :*}, :post_binary}, {{"application", "octet-stream", :*}, :post_binary},
{{"application", "x-www-form-urlencoded", :*}, :post_form}, {{"text", "plain", :*}, :post_binary},
{{"multipart", "form-data", :*}, :post_multipart}], req, state} {{"application", "x-www-form-urlencoded", :*}, :post_form},
{{"multipart", "form-data", :*}, :post_multipart}
], req, state}
end end
def content_types_provided(req, state) do def content_types_provided(req, state) do
@ -19,29 +21,30 @@ defmodule HTTParrot.StoreRequestHandler do
def get(req, state) do def get(req, state) do
{info, req} = GeneralRequestInfo.retrieve(req) {info, req} = GeneralRequestInfo.retrieve(req)
{key, _} = :cowboy_req.binding(:key, req) key = :cowboy_req.binding(:key, req)
HTTParrot.RequestStore.store(key, info) HTTParrot.RequestStore.store(key, info)
{'{"saved": "true"}', req, state} {'{"saved": "true"}', req, state}
end end
def post_binary(req, _state) do def post_binary(req, _state) do
{:ok, body, req} = HTTParrot.PHandler.handle_binary(req) {:ok, body, req} = HTTParrot.PHandler.handle_binary(req)
if String.valid?(body) do if String.valid?(body) do
if JSX.is_json?(body) do if JSX.is_json?(body) do
save_post(req, [form: [{}], data: body, json: JSX.decode!(body)]) save_post(req, form: [{}], data: body, json: JSX.decode!(body))
else else
save_post(req, [form: [{}], data: body, json: nil]) save_post(req, form: [{}], data: body, json: nil)
end end
else else
# Octet-stream # Octet-stream
body = Base.encode64(body) body = Base.encode64(body)
save_post(req, [form: [{}], data: "data:application/octet-stream;base64," <> body, json: nil]) save_post(req, form: [{}], data: "data:application/octet-stream;base64," <> body, json: nil)
end end
end end
def post_form(req, _state) do def post_form(req, _state) do
{:ok, body, req} = :cowboy_req.body_qs(req) {:ok, body, req} = :cowboy_req.read_urlencoded_body(req)
save_post(req, [form: body, data: "", json: nil]) save_post(req, form: body, data: "", json: nil)
end end
def post_multipart(req, _state) do def post_multipart(req, _state) do
@ -50,17 +53,19 @@ defmodule HTTParrot.StoreRequestHandler do
file_parts = for file <- parts, elem(file, 0) == :file, do: {elem(file, 1), elem(file, 2)} file_parts = for file <- parts, elem(file, 0) == :file, do: {elem(file, 1), elem(file, 2)}
form_parts = for form <- parts, elem(form, 0) == :form, do: {elem(form, 1), elem(form, 2)} form_parts = for form <- parts, elem(form, 0) == :form, do: {elem(form, 1), elem(form, 2)}
save_post(req, [form: HTTParrot.PHandler.normalize_list(form_parts), save_post(req,
files: HTTParrot.PHandler.normalize_list(file_parts), form: HTTParrot.PHandler.normalize_list(form_parts),
data: "", json: nil]) files: HTTParrot.PHandler.normalize_list(file_parts),
data: "",
json: nil
)
end end
def save_post(req, body) do def save_post(req, body) do
{info, req} = GeneralRequestInfo.retrieve(req) {info, req} = GeneralRequestInfo.retrieve(req)
{key, req} = :cowboy_req.binding(:key, req) key = :cowboy_req.binding(:key, req)
HTTParrot.RequestStore.store(key, info ++ body) HTTParrot.RequestStore.store(key, info ++ body)
{:ok, req} = :cowboy_req.reply(200, [], '{"saved": "true"}', req) req = :cowboy_req.reply(200, %{}, "{\"saved\": \"true\"}", req)
{:halt, req, nil} {:halt, req, nil}
end end
end end

View file

@ -9,14 +9,14 @@ defmodule HTTParrot.StreamBytesHandler do
end end
def malformed_request(req, state) do def malformed_request(req, state) do
{n, req} = :cowboy_req.binding(:n, req) n = :cowboy_req.binding(:n, req)
{seed, req} = :cowboy_req.qs_val("seed", req, "1234") %{seed: seed} = :cowboy_req.match_qs([{:seed, [], "1234"}], req)
{chunk_size, req} = :cowboy_req.qs_val("chunk_size", req, "1024") %{chunk_size: chunk_size} = :cowboy_req.match_qs([{:chunk_size, [], "1024"}], req)
try do try do
n = n |> String.to_integer n = n |> String.to_integer()
seed = seed |> String.to_integer seed = seed |> String.to_integer()
chunk_size = chunk_size |> String.to_integer chunk_size = chunk_size |> String.to_integer()
{false, req, {n, seed, chunk_size}} {false, req, {n, seed, chunk_size}}
rescue rescue
ArgumentError -> {true, req, state} ArgumentError -> {true, req, state}
@ -30,13 +30,13 @@ defmodule HTTParrot.StreamBytesHandler do
end end
defp stream_response(n, chunk_size) do defp stream_response(n, chunk_size) do
fn(send_func) -> fn send_func ->
Stream.repeatedly(fn -> :rand.uniform(255) end) Stream.repeatedly(fn -> :rand.uniform(255) end)
|> Stream.take(n) |> Stream.take(n)
|> Enum.chunk(chunk_size, chunk_size, []) |> Enum.chunk_every(chunk_size, chunk_size, [])
|> Enum.each(fn chunk -> |> Enum.each(fn chunk ->
send_func.(List.to_string(chunk)) send_func.(List.to_string(chunk))
end) end)
end end
end end
end end

View file

@ -9,9 +9,10 @@ defmodule HTTParrot.StreamHandler do
`n` must be an integer between 1-100 `n` must be an integer between 1-100
""" """
def malformed_request(req, state) do def malformed_request(req, state) do
{n, req} = :cowboy_req.binding(:n, req) n = :cowboy_req.binding(:n, req)
try do try do
n = n |> String.to_integer |> min(100) |> max(1) n = n |> String.to_integer() |> min(100) |> max(1)
{false, req, n} {false, req, n}
rescue rescue
ArgumentError -> {true, req, state} ArgumentError -> {true, req, state}
@ -28,10 +29,10 @@ defmodule HTTParrot.StreamHandler do
end end
defp stream_response(n, info) do defp stream_response(n, info) do
fn(send_func) -> fn send_func ->
Enum.each 0..n-1, fn (i) -> Enum.each(0..(n - 1), fn i ->
send_func.([id: i] ++ info |> JSX.encode!) send_func.(([id: i] ++ info) |> JSX.encode!())
end end)
end end
end end
end end

View file

@ -15,6 +15,6 @@ defmodule HTTParrot.UserAgentHandler do
defp response(user_agent) do defp response(user_agent) do
[{"user-agent", user_agent}] [{"user-agent", user_agent}]
|> JSX.encode! |> JSX.encode!()
end end
end end

View file

@ -1,15 +1,16 @@
defmodule HTTParrot.WebsocketHandler do defmodule HTTParrot.WebsocketHandler do
@behaviour :cowboy_websocket_handler @behaviour :cowboy_websocket
@moduledoc """ @moduledoc """
Echo given messages through websocket connection Echo given messages through websocket connection
""" """
def init(_transport, _req, _opts), do: {:upgrade, :protocol, :cowboy_websocket} def init(req, state), do: {:cowboy_websocket, req, state}
def websocket_init(_transport, req, _opts), do: {:ok, req, nil} def websocket_init(state), do: {:ok, state}
def websocket_handle({:text, text}, req, state), do: {:reply, {:text, text}, req, state} def websocket_handle({:text, text}, state), do: {:reply, {:text, text}, state}
def websocket_handle({:binary, binary}, req, state), do: {:reply, {:binary, binary}, req, state} def websocket_handle({:binary, binary}, state), do: {:reply, {:binary, binary}, state}
def websocket_info(_info, req, state), do: {:ok, req, state}
def websocket_terminate(_reason, _req, _state), do: :ok def websocket_info(_info, state), do: {:ok, state}
def terminate(_reason, _req, _state), do: :ok
end end

49
mix.exs
View file

@ -6,39 +6,50 @@ defmodule Httparrot.Mixfile do
""" """
def project do def project do
[ app: :httparrot, [
version: "1.1.0", app: :httparrot,
elixir: "~> 1.4", version: "1.2.0",
elixir: "~> 1.5",
name: "HTTParrot", name: "HTTParrot",
description: @description, description: @description,
package: package(), package: package(),
deps: deps() ] deps: deps()
]
end end
def application do def application do
[ applications: [ :compiler, [
:syntax_tools, applications: [:compiler, :syntax_tools, :cowboy, :exjsx, :con_cache],
:cowboy, mod: {HTTParrot, []},
:exjsx, env: [
:con_cache ], http_port: 8080,
mod: { HTTParrot, [] }, ssl: true,
env: [ http_port: 8080, ssl: true, https_port: 8433, https_port: 8433,
unix_socket: true, socket_path: "httparrot.sock"] ] unix_socket: true,
socket_path: "httparrot.sock"
]
]
end end
defp deps do defp deps do
[ {:cowboy, "~> 1.1.2"}, [
{:cowboy, "~> 2.5.0"},
{:exjsx, "~> 3.0 or ~> 4.0"}, {:exjsx, "~> 3.0 or ~> 4.0"},
{:con_cache, "~> 0.12.0"}, {:con_cache, "~> 0.13.0"},
{:ex_doc, "~> 0.14", only: :dev}, {:ex_doc, "~> 0.14", only: :dev},
{:meck, "~> 0.8.2", only: :test } ] {:meck, "~> 0.8.13", only: :test}
]
end end
defp package do defp package do
[ maintainers: ["Eduardo Gurgel Pinho"], [
maintainers: ["Eduardo Gurgel Pinho"],
licenses: ["MIT"], licenses: ["MIT"],
links: %{ "Github" => "https://github.com/edgurgel/httparrot", links: %{
"HTTParrot" => "http://httparrot.herokuapp.com", "Github" => "https://github.com/edgurgel/httparrot",
"httpbin" => "http://httpbin.org" } ] "HTTParrot" => "http://httparrot.herokuapp.com",
"httpbin" => "http://httpbin.org"
}
]
end end
end end

View file

@ -1,7 +1,7 @@
%{ %{
"con_cache": {:hex, :con_cache, "0.12.0", "2d961aec219aa5a914473873f348f5a6088292dc69d5192a9d25f8a1e13e9905", [:mix], [{:exactor, "~> 2.2.0", [hex: :exactor, repo: "hexpm", optional: false]}], "hexpm"}, "con_cache": {:hex, :con_cache, "0.13.1", "047e097ab2a8c6876e12d0c29e29a86d487b592df97b98e3e2abedad574e215d", [:mix], [], "hexpm"},
"cowboy": {:hex, :cowboy, "1.1.2", "61ac29ea970389a88eca5a65601460162d370a70018afe6f949a29dca91f3bb0", [:rebar3], [{:cowlib, "~> 1.0.2", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.3.2", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"}, "cowboy": {:hex, :cowboy, "2.5.0", "4ef3ae066ee10fe01ea3272edc8f024347a0d3eb95f6fbb9aed556dacbfc1337", [:rebar3], [{:cowlib, "~> 2.6.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.6.2", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
"cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [:make], [], "hexpm"}, "cowlib": {:hex, :cowlib, "2.6.0", "8aa629f81a0fc189f261dc98a42243fa842625feea3c7ec56c48f4ccdb55490f", [:rebar3], [], "hexpm"},
"earmark": {:hex, :earmark, "1.2.6", "b6da42b3831458d3ecc57314dff3051b080b9b2be88c2e5aa41cd642a5b044ed", [:mix], [], "hexpm"}, "earmark": {:hex, :earmark, "1.2.6", "b6da42b3831458d3ecc57314dff3051b080b9b2be88c2e5aa41cd642a5b044ed", [:mix], [], "hexpm"},
"ex_doc": {:hex, :ex_doc, "0.19.1", "519bb9c19526ca51d326c060cb1778d4a9056b190086a8c6c115828eaccea6cf", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.7", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, "ex_doc": {:hex, :ex_doc, "0.19.1", "519bb9c19526ca51d326c060cb1778d4a9056b190086a8c6c115828eaccea6cf", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.7", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"},
"exactor": {:hex, :exactor, "2.2.3", "a6972f43bb6160afeb73e1d8ab45ba604cd0ac8b5244c557093f6e92ce582786", [:mix], [], "hexpm"}, "exactor": {:hex, :exactor, "2.2.3", "a6972f43bb6160afeb73e1d8ab45ba604cd0ac8b5244c557093f6e92ce582786", [:mix], [], "hexpm"},
@ -9,7 +9,7 @@
"jsx": {:hex, :jsx, "2.8.2", "7acc7d785b5abe8a6e9adbde926a24e481f29956dd8b4df49e3e4e7bcc92a018", [:mix, :rebar3], [], "hexpm"}, "jsx": {:hex, :jsx, "2.8.2", "7acc7d785b5abe8a6e9adbde926a24e481f29956dd8b4df49e3e4e7bcc92a018", [:mix, :rebar3], [], "hexpm"},
"makeup": {:hex, :makeup, "0.5.5", "9e08dfc45280c5684d771ad58159f718a7b5788596099bdfb0284597d368a882", [:mix], [{:nimble_parsec, "~> 0.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"}, "makeup": {:hex, :makeup, "0.5.5", "9e08dfc45280c5684d771ad58159f718a7b5788596099bdfb0284597d368a882", [:mix], [{:nimble_parsec, "~> 0.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"},
"makeup_elixir": {:hex, :makeup_elixir, "0.10.0", "0f09c2ddf352887a956d84f8f7e702111122ca32fbbc84c2f0569b8b65cbf7fa", [:mix], [{:makeup, "~> 0.5.5", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"}, "makeup_elixir": {:hex, :makeup_elixir, "0.10.0", "0f09c2ddf352887a956d84f8f7e702111122ca32fbbc84c2f0569b8b65cbf7fa", [:mix], [{:makeup, "~> 0.5.5", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"},
"meck": {:hex, :meck, "0.8.2", "f15f7d513e14ec8c8dee9a95d4ae585b3e5a88bf0fa6a7573240d6ddb58a7236", [:make, :rebar], [], "hexpm"}, "meck": {:hex, :meck, "0.8.13", "ffedb39f99b0b99703b8601c6f17c7f76313ee12de6b646e671e3188401f7866", [:rebar3], [], "hexpm"},
"nimble_parsec": {:hex, :nimble_parsec, "0.4.0", "ee261bb53214943679422be70f1658fff573c5d0b0a1ecd0f18738944f818efe", [:mix], [], "hexpm"}, "nimble_parsec": {:hex, :nimble_parsec, "0.4.0", "ee261bb53214943679422be70f1658fff573c5d0b0a1ecd0f18738944f818efe", [:mix], [], "hexpm"},
"ranch": {:hex, :ranch, "1.3.2", "e4965a144dc9fbe70e5c077c65e73c57165416a901bd02ea899cfd95aa890986", [:rebar3], [], "hexpm"}, "ranch": {:hex, :ranch, "1.6.2", "6db93c78f411ee033dbb18ba8234c5574883acb9a75af0fb90a9b82ea46afa00", [:rebar3], [], "hexpm"},
} }

View file

@ -4,19 +4,19 @@ defmodule HTTParrot.CookiesHandlerTest do
import HTTParrot.CookiesHandler import HTTParrot.CookiesHandler
setup do setup do
new :cowboy_req new(:cowboy_req)
new JSX new(JSX)
on_exit fn -> unload() end on_exit(fn -> unload() end)
:ok :ok
end end
test "returns a JSON with all the cookies o/" do test "returns a JSON with all the cookies o/" do
expect(:cowboy_req, :cookies, 1, {[k1: :v1], :req2}) expect(:cowboy_req, :parse_cookies, 1, k1: :v1)
expect(JSX, :encode!, [{[[cookies: [k1: :v1]]], :json}]) expect(JSX, :encode!, [{[[cookies: [k1: :v1]]], :json}])
assert get_json(:req1, :state) == {:json, :req2, :state} assert get_json(:req1, :state) == {:json, :req1, :state}
assert validate :cowboy_req assert validate(:cowboy_req)
assert validate JSX assert validate(JSX)
end end
end end

View file

@ -4,43 +4,43 @@ defmodule HTTParrot.DelayedHandlerTest do
import HTTParrot.DelayedHandler import HTTParrot.DelayedHandler
setup do setup do
new HTTParrot.GeneralRequestInfo new(HTTParrot.GeneralRequestInfo)
new JSX new(JSX)
new :cowboy_req new(:cowboy_req)
on_exit fn -> unload() end on_exit(fn -> unload() end)
:ok :ok
end end
test "malformed_request returns false if it's not an integer" do test "malformed_request returns false if it's not an integer" do
expect(:cowboy_req, :binding, [{[:n, :req1], {"a2B=", :req2}}]) expect(:cowboy_req, :binding, [{[:n, :req1], "a2B="}])
assert malformed_request(:req1, :state) == {true, :req2, :state} assert malformed_request(:req1, :state) == {true, :req1, :state}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "malformed_request returns false if it's an integer" do test "malformed_request returns false if it's an integer" do
expect(:cowboy_req, :binding, [{[:n, :req1], {"2", :req2}}]) expect(:cowboy_req, :binding, [{[:n, :req1], "2"}])
assert malformed_request(:req1, :state) == {false, :req2, 2} assert malformed_request(:req1, :state) == {false, :req1, 2}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "malformed_request returns 0 if 'n' is less than 0" do test "malformed_request returns 0 if 'n' is less than 0" do
expect(:cowboy_req, :binding, [{[:n, :req1], {"-1", :req2}}]) expect(:cowboy_req, :binding, [{[:n, :req1], "-1"}])
assert malformed_request(:req1, :state) == {false, :req2, 0} assert malformed_request(:req1, :state) == {false, :req1, 0}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "malformed_request returns 10 if 'n' is greater than 10" do test "malformed_request returns 10 if 'n' is greater than 10" do
expect(:cowboy_req, :binding, [{[:n, :req1], {"20", :req2}}]) expect(:cowboy_req, :binding, [{[:n, :req1], "20"}])
assert malformed_request(:req1, :state) == {false, :req2, 10} assert malformed_request(:req1, :state) == {false, :req1, 10}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "returns json with query values, headers, url and origin" do test "returns json with query values, headers, url and origin" do
@ -49,7 +49,7 @@ defmodule HTTParrot.DelayedHandlerTest do
assert get_json(:req1, 0) == {:json, :req2, 0} assert get_json(:req1, 0) == {:json, :req2, 0}
assert validate HTTParrot.GeneralRequestInfo assert validate(HTTParrot.GeneralRequestInfo)
assert validate JSX assert validate(JSX)
end end
end end

View file

@ -4,18 +4,24 @@ defmodule HTTParrot.DeleteCookiesHandlerTest do
import HTTParrot.DeleteCookiesHandler import HTTParrot.DeleteCookiesHandler
setup do setup do
new :cowboy_req new(:cowboy_req)
on_exit fn -> unload() end on_exit(fn -> unload() end)
:ok :ok
end end
test "delete cookies and redirect to /cookies " do test "delete cookies and redirect to /cookies " do
expect(:cowboy_req, :set_resp_cookie, [{[:k1, :v1, [path: "/", max_age: 0], :req1], :req2}, expect(:cowboy_req, :set_resp_cookie, [
{[:k2, :v2, [path: "/", max_age: 0], :req2], :req3}]) {["k1", "v1", :req1, %{path: "/", max_age: 0}], :req2},
expect(:cowboy_req, :reply, [{[302, [{"location", "/cookies"}], "Redirecting...", :req3], {:ok, :req4}}]) {["k2", "v2", :req2, %{path: "/", max_age: 0}], :req3}
])
assert get_json(:req1, [k1: :v1, k2: :v2]) == {:halt, :req4, [k1: :v1, k2: :v2]} expect(:cowboy_req, :reply, [
{[302, %{"location" => "/cookies"}, "Redirecting...", :req3], :req4}
])
assert validate :cowboy_req assert get_json(:req1, [{"k1", "v1"}, {"k2", "v2"}]) ==
{:halt, :req4, [{"k1", "v1"}, {"k2", "v2"}]}
assert validate(:cowboy_req)
end end
end end

View file

@ -4,8 +4,8 @@ defmodule HTTParrot.GeneralRequestInfoTest do
import HTTParrot.GeneralRequestInfo import HTTParrot.GeneralRequestInfo
setup do setup do
new :cowboy_req new(:cowboy_req)
on_exit fn -> unload() end on_exit(fn -> unload() end)
:ok :ok
end end
@ -13,60 +13,65 @@ defmodule HTTParrot.GeneralRequestInfoTest do
test "returns a list of args, headers, url and original ip" do test "returns a list of args, headers, url and original ip" do
qs_vals = [{"a", "b"}] qs_vals = [{"a", "b"}]
headers = [header1: "value 1", header2: "value 2"] headers = %{"header1" => "value 1", "header2" => "value 2"}
ip = {127, 1, 2, 3} ip = {127, 1, 2, 3}
url = "http://localhost/get?a=b" url = "http://localhost/get?a=b"
expect(:cowboy_req, :qs_vals, 1, {qs_vals, :req2}) expect(:cowboy_req, :parse_qs, 1, qs_vals)
expect(:cowboy_req, :headers, 1, {headers, :req3}) expect(:cowboy_req, :headers, 1, headers)
expect(:cowboy_req, :url, 1, {url, :req4}) expect(:cowboy_req, :uri, 1, url)
expect(:cowboy_req, :peer, 1, {{ip, :host}, :req5}) expect(:cowboy_req, :peer, 1, {ip, 0})
assert retrieve(:req1) == {[args: %{"a" => "b"}, headers: headers, url: url, origin: "127.1.2.3"], :req5} assert retrieve(:req1) ==
{[args: %{"a" => "b"}, headers: headers, url: url, origin: "127.1.2.3"], :req1}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "returns a list of args with duplicated keys, headers, url and original ip" do test "returns a list of args with duplicated keys, headers, url and original ip" do
qs_vals = [{"a", "b"}, {"a", "c"}] qs_vals = [{"a", "b"}, {"a", "c"}]
headers = [header1: "value 1", header2: "value 2"] headers = %{"header1" => "value 1", "header2" => "value 2"}
ip = {127, 1, 2, 3} ip = {127, 1, 2, 3}
url = "http://localhost/get?a=b&a=c" url = "http://localhost/get?a=b&a=c"
expect(:cowboy_req, :qs_vals, 1, {qs_vals, :req2}) expect(:cowboy_req, :parse_qs, 1, qs_vals)
expect(:cowboy_req, :headers, 1, {headers, :req3}) expect(:cowboy_req, :headers, 1, headers)
expect(:cowboy_req, :url, 1, {url, :req4}) expect(:cowboy_req, :uri, 1, url)
expect(:cowboy_req, :peer, 1, {{ip, :host}, :req5}) expect(:cowboy_req, :peer, 1, {ip, 0})
assert retrieve(:req1) == {[args: %{"a" => ["b", "c"]}, headers: headers, url: url, origin: "127.1.2.3"], :req5} assert retrieve(:req1) ==
{[args: %{"a" => ["b", "c"]}, headers: headers, url: url, origin: "127.1.2.3"],
:req1}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "returns a list of empty args, headers, url and original ip" do test "returns a list of empty args, headers, url and original ip" do
qs_vals = [] qs_vals = []
headers = [header1: "value 1", header2: "value 2"] headers = %{"header1" => "value 1", "header2" => "value 2"}
ip = {127, 1, 2, 3} ip = {127, 1, 2, 3}
url = "http://localhost/get" url = "http://localhost/get"
expect(:cowboy_req, :qs_vals, 1, {qs_vals, :req2}) expect(:cowboy_req, :parse_qs, 1, qs_vals)
expect(:cowboy_req, :headers, 1, {headers, :req3}) expect(:cowboy_req, :headers, 1, headers)
expect(:cowboy_req, :url, 1, {url, :req4}) expect(:cowboy_req, :uri, 1, url)
expect(:cowboy_req, :peer, 1, {{ip, :host}, :req5}) expect(:cowboy_req, :peer, 1, {ip, 0})
assert retrieve(:req1) == {[args: %{}, headers: headers, url: url, origin: "127.1.2.3"], :req5} assert retrieve(:req1) ==
{[args: %{}, headers: headers, url: url, origin: "127.1.2.3"], :req1}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "returns empty origin when using unix sockets" do test "returns empty origin when using unix sockets" do
qs_vals = [{"a", "b"}] qs_vals = [{"a", "b"}]
headers = [header1: "value 1", header2: "value 2"] headers = %{"header1" => "value 1", "header2" => "value 2"}
url = "http://localhost/get?a=b" url = "http://localhost/get?a=b"
expect(:cowboy_req, :qs_vals, 1, {qs_vals, :req2}) expect(:cowboy_req, :parse_qs, 1, qs_vals)
expect(:cowboy_req, :headers, 1, {headers, :req3}) expect(:cowboy_req, :headers, 1, headers)
expect(:cowboy_req, :url, 1, {url, :req4}) expect(:cowboy_req, :uri, 1, url)
expect(:cowboy_req, :peer, 1, {{:local, ""}, :req5}) expect(:cowboy_req, :peer, 1, {{127, 0, 0, 1}, 0})
assert retrieve(:req1) == {[args: %{"a" => "b"}, headers: headers, url: url, origin: ""], :req5} assert retrieve(:req1) ==
{[args: %{"a" => "b"}, headers: headers, url: url, origin: ""], :req1}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
end end

View file

@ -4,19 +4,19 @@ defmodule HTTParrot.HeadersHandlerTest do
import HTTParrot.HeadersHandler import HTTParrot.HeadersHandler
setup do setup do
new :cowboy_req new(:cowboy_req)
new JSX new(JSX)
on_exit fn -> unload() end on_exit(fn -> unload() end)
:ok :ok
end end
test "returns prettified json with headers list" do test "returns prettified json with headers list" do
expect(:cowboy_req, :headers, 1, {:headers, :req2}) expect(:cowboy_req, :headers, 1, :headers)
expect(JSX, :encode!, [{[[headers: :headers]], :json}]) expect(JSX, :encode!, [{[[headers: :headers]], :json}])
assert get_json(:req1, :state) == {:json, :req2, :state} assert get_json(:req1, :state) == {:json, :req1, :state}
assert validate :cowboy_req assert validate(:cowboy_req)
assert validate JSX assert validate(JSX)
end end
end end

View file

@ -4,32 +4,39 @@ defmodule HTTParrot.HiddenBasicAuthHandlerTest do
import HTTParrot.HiddenBasicAuthHandler import HTTParrot.HiddenBasicAuthHandler
setup do setup do
new :cowboy_req new(:cowboy_req)
new JSX new(JSX)
on_exit fn -> unload() end on_exit(fn -> unload() end)
:ok :ok
end end
test "resource_exists returns true if user and passwd match" do test "resource_exists returns true if user and passwd match" do
expect(:cowboy_req, :binding, [{[:user, :req1], {:user, :req2}}, expect(:cowboy_req, :binding, [
{[:passwd, :req2], {:passwd, :req3}}]) {[:user, :req1], :user},
expect(:cowboy_req, :parse_header, [{["authorization", :req3], {:ok, {"basic", {:user, :passwd}}, :req4}}]) {[:passwd, :req1], :passwd}
])
assert resource_exists(:req1, :state) == {true, :req4, :user} expect(:cowboy_req, :parse_header, [
{["authorization", :req1], {:basic, :user, :passwd}}
])
assert validate :cowboy_req assert resource_exists(:req1, :state) == {true, :req1, :user}
assert validate JSX
assert validate(:cowboy_req)
assert validate(JSX)
end end
test "resource_exists returns false if user and passwd doesnt match" do test "resource_exists returns false if user and passwd doesnt match" do
expect(:cowboy_req, :binding, [{[:user, :req1], {:user, :req2}}, expect(:cowboy_req, :binding, [{[:user, :req1], :user}, {[:passwd, :req1], :passwd}])
{[:passwd, :req2], {:passwd, :req3}}])
expect(:cowboy_req, :parse_header, [{["authorization", :req3], {:ok, {"basic", {:not_the_user, :passwd}}, :req4}}])
assert resource_exists(:req1, :state) == {false, :req4, :state} expect(:cowboy_req, :parse_header, [
{["authorization", :req1], {:basic, :not_the_user, :passwd}}
])
assert validate :cowboy_req assert resource_exists(:req1, :state) == {false, :req1, :state}
assert validate JSX
assert validate(:cowboy_req)
assert validate(JSX)
end end
test "returns user and if it's authenticated" do test "returns user and if it's authenticated" do
@ -37,6 +44,6 @@ defmodule HTTParrot.HiddenBasicAuthHandlerTest do
assert get_json(:req1, :user) == {:json, :req1, nil} assert get_json(:req1, :user) == {:json, :req1, nil}
assert validate JSX assert validate(JSX)
end end
end end

View file

@ -4,16 +4,18 @@ defmodule HTTParrotTest do
import HTTParrot import HTTParrot
setup do setup do
new :cowboy_req new(:cowboy_req)
on_exit fn -> unload() end on_exit(fn -> unload() end)
:ok :ok
end end
test "'prettify_json' prettifies body response if it's a JSON" do test "'prettify_json' prettifies body response if it's a JSON" do
expect(:cowboy_req, :reply, [{[:status, [{"content-length", '14'}], "{\n \"a\": \"b\"\n}", :req1], {:ok, :req2}}]) expect(:cowboy_req, :reply, [
assert prettify_json(:status, [{"content-length", '12'}], "{\"a\":\"b\"}", :req1) == :req2 {[:status, %{"content-length" => '14'}, "{\n \"a\": \"b\"\n}", :req1], :req2}
assert validate :cowboy_req ])
assert prettify_json(:status, %{"content-length" => '12'}, "{\"a\":\"b\"}", :req1) == :req2
assert validate(:cowboy_req)
end end
test "'prettify_json' does nothing if body is not a JSON" do test "'prettify_json' does nothing if body is not a JSON" do

View file

@ -4,44 +4,44 @@ defmodule HTTParrot.IPHandlerTest do
import HTTParrot.IPHandler import HTTParrot.IPHandler
setup do setup do
new :cowboy_req new(:cowboy_req)
new JSX new(JSX)
on_exit fn -> unload() end on_exit(fn -> unload() end)
:ok :ok
end end
test "returns prettified json with origin" do test "returns prettified json with origin" do
ip = {127, 1, 2, 3} ip = {127, 1, 2, 3}
expect(:cowboy_req, :peer, 1, {{ip, :host}, :req2}) expect(:cowboy_req, :peer, 1, {ip, 0})
expect(:cowboy_req, :parse_header, 2, {:ok, :undefined, :req2}) expect(:cowboy_req, :parse_header, 2, :undefined)
expect(JSX, :encode!, [{[[origin: "127.1.2.3"]], :json}]) expect(JSX, :encode!, [{[[origin: "127.1.2.3"]], :json}])
assert get_json(:req1, :state) == {:json, :req2, :state} assert get_json(:req1, :state) == {:json, :req1, :state}
assert validate :cowboy_req assert validate(:cowboy_req)
assert validate JSX assert validate(JSX)
end end
test "returns prettified json with client ip when available" do test "returns prettified json with client ip when available" do
ip = {127, 1, 2, 3} ip = {127, 1, 2, 3}
expect(:cowboy_req, :peer, 1, {{ip, :host}, :req2}) expect(:cowboy_req, :peer, 1, {ip, 0})
expect(:cowboy_req, :parse_header, 2, {:ok, ["190.1.2.3"], :req2}) expect(:cowboy_req, :parse_header, 2, ["190.1.2.3"])
expect(JSX, :encode!, [{[[origin: "190.1.2.3"]], :json}]) expect(JSX, :encode!, [{[[origin: "190.1.2.3"]], :json}])
assert get_json(:req1, :state) == {:json, :req2, :state} assert get_json(:req1, :state) == {:json, :req1, :state}
assert validate :cowboy_req assert validate(:cowboy_req)
assert validate JSX assert validate(JSX)
end end
test "returns empty when running over unix sockets" do test "returns empty when running over unix sockets" do
expect(:cowboy_req, :peer, 1, {{:local, ""}, :req2}) expect(:cowboy_req, :peer, 1, {{127, 0, 0, 1}, 0})
expect(:cowboy_req, :parse_header, 2, {:ok, :undefined, :req2}) expect(:cowboy_req, :parse_header, 2, :undefined)
expect(JSX, :encode!, [{[[origin: ""]], :json}]) expect(JSX, :encode!, [{[[origin: ""]], :json}])
assert get_json(:req1, :state) == {:json, :req2, :state} assert get_json(:req1, :state) == {:json, :req1, :state}
assert validate :cowboy_req assert validate(:cowboy_req)
assert validate JSX assert validate(JSX)
end end
end end

View file

@ -4,51 +4,55 @@ defmodule HTTParrot.PHandlerTest do
import HTTParrot.PHandler import HTTParrot.PHandler
setup do setup do
new HTTParrot.GeneralRequestInfo new(HTTParrot.GeneralRequestInfo)
new JSX new(JSX)
new :cowboy_req new(:cowboy_req)
on_exit fn -> unload() end on_exit(fn -> unload() end)
:ok :ok
end end
Enum.each [{"/post", "POST"}, Enum.each(
{"/patch", "PATCH"}, [{"/post", "POST"}, {"/patch", "PATCH"}, {"/put", "PUT"}],
{"/put", "PUT"}], fn {path, verb} -> fn {path, verb} ->
test "allowed_methods return verb related to #{path}" do test "allowed_methods return verb related to #{path}" do
expect(:cowboy_req, :path, 1, {unquote(path), :req2}) expect(:cowboy_req, :path, 1, unquote(path))
assert allowed_methods(:req1, :state) == {[unquote(verb)], :req2, :state} assert allowed_methods(:req1, :state) == {[unquote(verb)], :req1, :state}
assert validate :cowboy_req assert validate(:cowboy_req)
end
end end
end )
test "returns json with general info and P[OST, ATCH, UT] form data" do test "returns json with general info and P[OST, ATCH, UT] form data" do
expect(:cowboy_req, :body_qs, 1, {:ok, :body_qs, :req2}) expect(:cowboy_req, :read_urlencoded_body, 1, {:ok, :body_qs, :req2})
expect(:cowboy_req, :set_resp_body, [{[:response, :req3], :req4}]) expect(:cowboy_req, :set_resp_body, [{[:response, :req3], :req4}])
expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req3}) expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req3})
expect(JSX, :encode!, [{[[:info, {:form, :body_qs}, {:data, ""}, {:json, nil}]], :response}]) expect(JSX, :encode!, [{[[:info, {:form, :body_qs}, {:data, ""}, {:json, nil}]], :response}])
assert post_form(:req1, :state) == {true, :req4, nil} assert post_form(:req1, :state) == {true, :req4, nil}
assert validate HTTParrot.GeneralRequestInfo assert validate(HTTParrot.GeneralRequestInfo)
end end
test "returns json with general info and P[OST, ATCH, UT] JSON body data" do test "returns json with general info and P[OST, ATCH, UT] JSON body data" do
expect(:cowboy_req, :body, 1, {:ok, "body", :req2}) expect(:cowboy_req, :read_body, 1, {:ok, "body", :req2})
expect(:cowboy_req, :set_resp_body, [{[:response, :req3], :req4}]) expect(:cowboy_req, :set_resp_body, [{[:response, :req3], :req4}])
expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req3}) expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req3})
expect(JSX, :is_json?, 1, true) expect(JSX, :is_json?, 1, true)
expect(JSX, :decode!, 1, :decoded_json) expect(JSX, :decode!, 1, :decoded_json)
expect(JSX, :encode!, [{[[:info, {:form, [{}]}, {:data, "body"}, {:json, :decoded_json}]], :response}])
expect(JSX, :encode!, [
{[[:info, {:form, [{}]}, {:data, "body"}, {:json, :decoded_json}]], :response}
])
assert post_binary(:req1, :state) == {true, :req4, nil} assert post_binary(:req1, :state) == {true, :req4, nil}
assert validate HTTParrot.GeneralRequestInfo assert validate(HTTParrot.GeneralRequestInfo)
end end
test "returns json with general info and P[OST, ATCH, UT] non-JSON body data" do test "returns json with general info and P[OST, ATCH, UT] non-JSON body data" do
expect(:cowboy_req, :body, 1, {:ok, "body", :req2}) expect(:cowboy_req, :read_body, 1, {:ok, "body", :req2})
expect(:cowboy_req, :set_resp_body, [{[:response, :req3], :req4}]) expect(:cowboy_req, :set_resp_body, [{[:response, :req3], :req4}])
expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req3}) expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req3})
expect(JSX, :is_json?, 1, false) expect(JSX, :is_json?, 1, false)
@ -56,28 +60,40 @@ defmodule HTTParrot.PHandlerTest do
assert post_binary(:req1, :state) == {true, :req4, nil} assert post_binary(:req1, :state) == {true, :req4, nil}
assert validate HTTParrot.GeneralRequestInfo assert validate(HTTParrot.GeneralRequestInfo)
end end
test "returns json with general info and P[OST, ATCH, UT] octet-stream body data" do test "returns json with general info and P[OST, ATCH, UT] octet-stream body data" do
expect(:cowboy_req, :body, 1, {:ok, <<0xffff :: 16>>, :req2}) expect(:cowboy_req, :read_body, 1, {:ok, <<0xFFFF::16>>, :req2})
expect(:cowboy_req, :set_resp_body, [{[:response, :req3], :req4}]) expect(:cowboy_req, :set_resp_body, [{[:response, :req3], :req4}])
expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req3}) expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req3})
expect(JSX, :is_json?, 1, false) expect(JSX, :is_json?, 1, false)
expect(JSX, :encode!, [{[[:info, {:form, [{}]}, {:data, "data:application/octet-stream;base64,//8="}, {:json, nil}]], :response}])
expect(JSX, :encode!, [
{[
[
:info,
{:form, [{}]},
{:data, "data:application/octet-stream;base64,//8="},
{:json, nil}
]
], :response}
])
assert post_binary(:req1, :state) == {true, :req4, nil} assert post_binary(:req1, :state) == {true, :req4, nil}
assert validate HTTParrot.GeneralRequestInfo assert validate(HTTParrot.GeneralRequestInfo)
end end
test "returns json with general info and P[OST, UT, ATCH] non-JSON body data for a chunked request" do test "returns json with general info and P[OST, UT, ATCH] non-JSON body data for a chunked request" do
first_chunk = "first chunk" first_chunk = "first chunk"
second_chunk = "second chunk" second_chunk = "second chunk"
expect(:cowboy_req, :body, fn req ->
expect(:cowboy_req, :read_body, fn req ->
case req do case req do
:req1 -> :req1 ->
{:more, first_chunk, :req2} {:more, first_chunk, :req2}
:req2 -> :req2 ->
{:ok, second_chunk, :req3} {:ok, second_chunk, :req3}
end end
@ -86,20 +102,25 @@ defmodule HTTParrot.PHandlerTest do
expect(:cowboy_req, :set_resp_body, [{[:response, :req4], :req5}]) expect(:cowboy_req, :set_resp_body, [{[:response, :req4], :req5}])
expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req4}) expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req4})
expect(JSX, :is_json?, 1, false) expect(JSX, :is_json?, 1, false)
expect(JSX, :encode!, [{[[:info, {:form, [{}]}, {:data, first_chunk <> second_chunk}, {:json, nil}]], :response}])
expect(JSX, :encode!, [
{[[:info, {:form, [{}]}, {:data, first_chunk <> second_chunk}, {:json, nil}]], :response}
])
assert post_binary(:req1, :state) == {true, :req5, nil} assert post_binary(:req1, :state) == {true, :req5, nil}
assert validate HTTParrot.GeneralRequestInfo assert validate(HTTParrot.GeneralRequestInfo)
end end
test "returns json with general info and P[OST, UT, ATCH] octect-stream body data for a chunked request" do test "returns json with general info and P[OST, UT, ATCH] octect-stream body data for a chunked request" do
first_chunk = "first chunk" <> <<0xffff :: 16>> first_chunk = "first chunk" <> <<0xFFFF::16>>
second_chunk = "second chunk" second_chunk = "second chunk"
expect(:cowboy_req, :body, fn req ->
expect(:cowboy_req, :read_body, fn req ->
case req do case req do
:req1 -> :req1 ->
{:more, first_chunk, :req2} {:more, first_chunk, :req2}
:req2 -> :req2 ->
{:ok, second_chunk, :req3} {:ok, second_chunk, :req3}
end end
@ -108,126 +129,204 @@ defmodule HTTParrot.PHandlerTest do
expect(:cowboy_req, :set_resp_body, [{[:response, :req4], :req5}]) expect(:cowboy_req, :set_resp_body, [{[:response, :req4], :req5}])
expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req4}) expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req4})
expect(JSX, :is_json?, 1, false) expect(JSX, :is_json?, 1, false)
expect(JSX, :encode!, [{[[:info, {:form, [{}]}, {:data, "data:application/octet-stream;base64,#{Base.encode64(first_chunk <> second_chunk)}"}, {:json, nil}]], :response}])
expect(JSX, :encode!, [
{[
[
:info,
{:form, [{}]},
{:data,
"data:application/octet-stream;base64,#{Base.encode64(first_chunk <> second_chunk)}"},
{:json, nil}
]
], :response}
])
assert post_binary(:req1, :state) == {true, :req5, nil} assert post_binary(:req1, :state) == {true, :req5, nil}
assert validate HTTParrot.GeneralRequestInfo assert validate(HTTParrot.GeneralRequestInfo)
end end
test "returns json with general info and P[OST, ATCH, UT] form data for multipart request (simple)" do test "returns json with general info and P[OST, ATCH, UT] form data for multipart request (simple)" do
expect(:cowboy_req, :part, fn req -> expect(:cowboy_req, :read_part, fn req ->
case req do case req do
:req1 -> :req1 ->
{:ok, [{"content-disposition", "form-data; name=\"key1\""}], :req2} {:ok, %{"content-disposition" => "form-data; name=\"key1\""}, :req2}
:req3 -> :req3 ->
{:done, :req4} {:done, :req4}
end end
end) end)
expect(:cowboy_req, :part_body, [{[:req2], {:ok, "value1", :req3}}]) expect(:cowboy_req, :read_part_body, [{[:req2], {:ok, "value1", :req3}}])
expect(:cowboy_req, :parse_header,
[{["content-type", :req4], expect(:cowboy_req, :parse_header, [
{:ok, {"multipart", "form-data", [{"boundary", "----WebKitFormBoundary8BEQxJvZANFsvRV9"}]}, :req5}}]) {["content-type", :req4],
{:ok, {"multipart", "form-data", [{"boundary", "----WebKitFormBoundary8BEQxJvZANFsvRV9"}]},
:req5}}
])
expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req6}) expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req6})
expect(JSX, :is_json?, 1, false) expect(JSX, :is_json?, 1, false)
expect(JSX, :encode!, [{[[:info, {:form, [{"key1", "value1"}]}, {:files, [{}]}, {:data, ""}, {:json, nil}]], :response}])
expect(JSX, :encode!, [
{[[:info, {:form, [{"key1", "value1"}]}, {:files, [{}]}, {:data, ""}, {:json, nil}]],
:response}
])
expect(:cowboy_req, :set_resp_body, [{[:response, :req6], :req7}]) expect(:cowboy_req, :set_resp_body, [{[:response, :req6], :req7}])
assert post_multipart(:req1, :state) == {true, :req7, nil} assert post_multipart(:req1, :state) == {true, :req7, nil}
assert validate HTTParrot.GeneralRequestInfo assert validate(HTTParrot.GeneralRequestInfo)
end end
test "returns json with general info and P[OST, ATCH, UT] form data for multipart requests (multiple parts)" do test "returns json with general info and P[OST, ATCH, UT] form data for multipart requests (multiple parts)" do
expect(:cowboy_req, :part, fn req -> expect(:cowboy_req, :read_part, fn req ->
case req do case req do
:req1 -> :req1 ->
{:ok, [{"content-disposition", "form-data; name=\"key1\""}], :req2} {:ok, %{"content-disposition" => "form-data; name=\"key1\""}, :req2}
:req3 -> :req3 ->
{:ok, [{"content-disposition", "form-data; name=\"key2\""}], :req4} {:ok, %{"content-disposition" => "form-data; name=\"key2\""}, :req4}
:req5 -> :req5 ->
{:done, :req6} {:done, :req6}
end end
end) end)
expect(:cowboy_req, :part_body, fn req -> expect(:cowboy_req, :read_part_body, fn req ->
case req do case req do
:req2 -> {:ok, "value1", :req3} :req2 -> {:ok, "value1", :req3}
:req4 -> {:ok, "value2", :req5} :req4 -> {:ok, "value2", :req5}
end end
end) end)
expect(:cowboy_req, :parse_header, expect(:cowboy_req, :parse_header, [
[{["content-type", :req6], {["content-type", :req6],
{:ok, {"multipart", "form-data", [{"boundary", "----WebKitFormBoundary8BEQxJvZANFsvRV9"}]}, :req7}}]) {:ok, {"multipart", "form-data", [{"boundary", "----WebKitFormBoundary8BEQxJvZANFsvRV9"}]},
:req7}}
])
expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req8}) expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req8})
expect(JSX, :is_json?, 1, false) expect(JSX, :is_json?, 1, false)
expect(JSX, :encode!, [{[[:info, {:form, [{"key1", "value1"}, {"key2", "value2"}]}, {:files, [{}]}, {:data, ""}, {:json, nil}]], :response}])
expect(JSX, :encode!, [
{[
[
:info,
{:form, [{"key1", "value1"}, {"key2", "value2"}]},
{:files, [{}]},
{:data, ""},
{:json, nil}
]
], :response}
])
expect(:cowboy_req, :set_resp_body, [{[:response, :req8], :req9}]) expect(:cowboy_req, :set_resp_body, [{[:response, :req8], :req9}])
assert post_multipart(:req1, :state) == {true, :req9, nil} assert post_multipart(:req1, :state) == {true, :req9, nil}
assert validate HTTParrot.GeneralRequestInfo assert validate(HTTParrot.GeneralRequestInfo)
end end
test "returns json with general info and P[OST, UT, ATCH] file data (one file)" do test "returns json with general info and P[OST, UT, ATCH] file data (one file)" do
expect(:cowboy_req, :part, fn req -> expect(:cowboy_req, :read_part, fn req ->
case req do case req do
:req1 -> :req1 ->
{:ok, [{"content-disposition", "form-data; name=\"file1\"; filename=\"testdata.txt\""}, {"content-type", "text/plain"}], :req2} {:ok,
%{
"content-disposition" => "form-data; name=\"file1\"; filename=\"testdata.txt\"",
"content-type" => "text/plain"
}, :req2}
:req3 -> :req3 ->
{:done, :req4} {:done, :req4}
end end
end) end)
expect(:cowboy_req, :part_body, [{[:req2], {:ok, "here is some cool\ntest data.", :req3}}]) expect(:cowboy_req, :read_part_body, [
expect(:cowboy_req, :parse_header, {[:req2], {:ok, "here is some cool\ntest data.", :req3}}
[{["content-type", :req4], ])
{:ok, {"multipart", "form-data", [{"boundary", "----WebKitFormBoundary8BEQxJvZANFsvRV9"}]}, :req5}}])
expect(:cowboy_req, :parse_header, [
{["content-type", :req4],
{:ok, {"multipart", "form-data", [{"boundary", "----WebKitFormBoundary8BEQxJvZANFsvRV9"}]},
:req5}}
])
expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req6}) expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req6})
expect(JSX, :is_json?, 1, false) expect(JSX, :is_json?, 1, false)
expect(JSX, :encode!, [{[[:info, {:form, [{}]}, {:files, [{"file1", "here is some cool\ntest data."}]}, {:data, ""}, {:json, nil}]], :response}])
expect(JSX, :encode!, [
{[
[
:info,
{:form, [{}]},
{:files, [{"file1", "here is some cool\ntest data."}]},
{:data, ""},
{:json, nil}
]
], :response}
])
expect(:cowboy_req, :set_resp_body, [{[:response, :req6], :req7}]) expect(:cowboy_req, :set_resp_body, [{[:response, :req6], :req7}])
assert post_multipart(:req1, :state) == {true, :req7, nil} assert post_multipart(:req1, :state) == {true, :req7, nil}
assert validate HTTParrot.GeneralRequestInfo assert validate(HTTParrot.GeneralRequestInfo)
end end
test "returns json with general info and P[OST, UT, ATCH] form data and file data (form-data plus one file)" do test "returns json with general info and P[OST, UT, ATCH] form data and file data (form-data plus one file)" do
expect(:cowboy_req, :part, fn req -> expect(:cowboy_req, :read_part, fn req ->
case req do case req do
:req1 -> :req1 ->
{:ok, [{"content-disposition", "form-data; name=\"key1\""}], :req2} {:ok, %{"content-disposition" => "form-data; name=\"key1\""}, :req2}
:req3 -> :req3 ->
{:ok, [{"content-disposition", "form-data; name=\"file1\"; filename=\"testdata.txt\""}, {"content-type", "text/plain"}], :req4} {:ok,
%{
"content-disposition" => "form-data; name=\"file1\"; filename=\"testdata.txt\"",
"content-type" => "text/plain"
}, :req4}
:req5 -> :req5 ->
{:done, :req6} {:done, :req6}
end end
end) end)
expect(:cowboy_req, :part_body, fn req -> expect(:cowboy_req, :read_part_body, fn req ->
case req do case req do
:req2 -> {:ok, "value1", :req3} :req2 -> {:ok, "value1", :req3}
:req4 -> {:ok, "here is some cool\ntest data", :req5} :req4 -> {:ok, "here is some cool\ntest data", :req5}
end end
end) end)
expect(:cowboy_req, :parse_header, expect(:cowboy_req, :parse_header, [
[{["content-type", :req6], {["content-type", :req6],
{:ok, {"multipart", "form-data", [{"boundary", "----WebKitFormBoundary8BEQxJvZANFsvRV9"}]}, :req7}}]) {:ok, {"multipart", "form-data", [{"boundary", "----WebKitFormBoundary8BEQxJvZANFsvRV9"}]},
:req7}}
])
expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req8}) expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req8})
expect(JSX, :is_json?, 1, false) expect(JSX, :is_json?, 1, false)
expect(JSX, :encode!, [{[[:info, {:form, [{"key1", "value1"}]}, {:files, [{"file1", "here is some cool\ntest data"}]}, {:data, ""}, {:json, nil}]], :response}])
expect(JSX, :encode!, [
{[
[
:info,
{:form, [{"key1", "value1"}]},
{:files, [{"file1", "here is some cool\ntest data"}]},
{:data, ""},
{:json, nil}
]
], :response}
])
expect(:cowboy_req, :set_resp_body, [{[:response, :req8], :req9}]) expect(:cowboy_req, :set_resp_body, [{[:response, :req8], :req9}])
assert post_multipart(:req1, :state) == {true, :req9, nil} assert post_multipart(:req1, :state) == {true, :req9, nil}
assert validate HTTParrot.GeneralRequestInfo assert validate(HTTParrot.GeneralRequestInfo)
end end
end end

View file

@ -4,49 +4,48 @@ defmodule HTTParrot.RedirectHandlerTest do
import HTTParrot.RedirectHandler import HTTParrot.RedirectHandler
setup do setup do
new :cowboy_req new(:cowboy_req)
on_exit fn -> unload() end on_exit(fn -> unload() end)
:ok :ok
end end
test "malformed_request returns true if it's not an integer" do test "malformed_request returns true if it's not an integer" do
expect(:cowboy_req, :binding, [{[:n, :req1], {"a2B=", :req2}}]) expect(:cowboy_req, :binding, [{[:n, :req1], "a2B="}])
assert malformed_request(:req1, :state) == {true, :req2, :state} assert malformed_request(:req1, :state) == {true, :req1, :state}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "malformed_request returns false if it's an integer" do test "malformed_request returns false if it's an integer" do
expect(:cowboy_req, :binding, [{[:n, :req1], {"2", :req2}}]) expect(:cowboy_req, :binding, [{[:n, :req1], "2"}])
assert malformed_request(:req1, :state) == {false, :req2, 2} assert malformed_request(:req1, :state) == {false, :req1, 2}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "malformed_request returns 1 if 'n' is less than 1" do test "malformed_request returns 1 if 'n' is less than 1" do
expect(:cowboy_req, :binding, [{[:n, :req1], {"0", :req2}}]) expect(:cowboy_req, :binding, [{[:n, :req1], "0"}])
assert malformed_request(:req1, :state) == {false, :req2, 1} assert malformed_request(:req1, :state) == {false, :req1, 1}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "moved_permanently returns 'redirect/n-1' if n > 1" do test "moved_permanently returns 'redirect/n-1' if n > 1" do
expect(:cowboy_req, :host_url, 1, {"host", :req2}) expect(:cowboy_req, :uri, 1, "host")
assert moved_permanently(:req1, 4) == {{true, "host/redirect/3"}, :req2, nil} assert moved_permanently(:req1, 4) == {{true, "host/redirect/3"}, :req1, nil}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "moved_permanently returns '/get' if n = 1" do test "moved_permanently returns '/get' if n = 1" do
expect(:cowboy_req, :host_url, 1, {"host", :req2}) expect(:cowboy_req, :uri, 1, "host")
assert moved_permanently(:req1, 1) == {{true, "host/get"}, :req2, nil} assert moved_permanently(:req1, 1) == {{true, "host/get"}, :req1, nil}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
end end

View file

@ -4,20 +4,20 @@ defmodule HTTParrot.RedirectToHandlerTest do
import HTTParrot.RedirectToHandler import HTTParrot.RedirectToHandler
setup do setup do
new :cowboy_req new(:cowboy_req)
on_exit fn -> unload() end on_exit(fn -> unload() end)
:ok :ok
end end
test "malformed_request returns true if no 'url' is defined" do test "malformed_request returns true if no 'url' is defined" do
expect(:cowboy_req, :qs_val, [{["url", :req1, nil], {:url, :req2}}]) expect(:cowboy_req, :match_qs, 2, %{url: :url})
assert malformed_request(:req1, :state) == {false, :req2, :url} assert malformed_request(:req1, :state) == {false, :req1, :url}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "malformed_request returns false if no 'url' is defined" do test "malformed_request returns false if no 'url' is defined" do
expect(:cowboy_req, :qs_val, [{["url", :req1, nil], {nil, :req2}}]) expect(:cowboy_req, :match_qs, 2, %{url: nil})
assert malformed_request(:req1, :state) == {true, :req2, :state} assert malformed_request(:req1, :state) == {true, :req1, :state}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
end end

View file

@ -4,33 +4,33 @@ defmodule HTTParrot.RelativeRedirectHandlerTest do
import HTTParrot.RelativeRedirectHandler import HTTParrot.RelativeRedirectHandler
setup do setup do
new :cowboy_req new(:cowboy_req)
on_exit fn -> unload() end on_exit(fn -> unload() end)
:ok :ok
end end
test "malformed_request returns false if it's not an integer" do test "malformed_request returns false if it's not an integer" do
expect(:cowboy_req, :binding, [{[:n, :req1], {"a2B=", :req2}}]) expect(:cowboy_req, :binding, [{[:n, :req1], "a2B="}])
assert malformed_request(:req1, :state) == {true, :req2, :state} assert malformed_request(:req1, :state) == {true, :req1, :state}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "malformed_request returns false if it's an integer" do test "malformed_request returns false if it's an integer" do
expect(:cowboy_req, :binding, [{[:n, :req1], {"2", :req2}}]) expect(:cowboy_req, :binding, [{[:n, :req1], "2"}])
assert malformed_request(:req1, :state) == {false, :req2, 2} assert malformed_request(:req1, :state) == {false, :req1, 2}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "malformed_request returns 1 if 'n' is less than 1" do test "malformed_request returns 1 if 'n' is less than 1" do
expect(:cowboy_req, :binding, [{[:n, :req1], {"0", :req2}}]) expect(:cowboy_req, :binding, [{[:n, :req1], "0"}])
assert malformed_request(:req1, :state) == {false, :req2, 1} assert malformed_request(:req1, :state) == {false, :req1, 1}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "moved_permanently returns 'redirect/n-1' if n > 1" do test "moved_permanently returns 'redirect/n-1' if n > 1" do
@ -40,5 +40,4 @@ defmodule HTTParrot.RelativeRedirectHandlerTest do
test "moved_permanently returns '/get' if n = 1" do test "moved_permanently returns '/get' if n = 1" do
assert moved_permanently(:req1, 1) == {{true, "/get"}, :req1, nil} assert moved_permanently(:req1, 1) == {{true, "/get"}, :req1, nil}
end end
end end

View file

@ -4,36 +4,36 @@ defmodule HTTParrot.ResponseHeadersHandlerTest do
import HTTParrot.ResponseHeadersHandler import HTTParrot.ResponseHeadersHandler
setup do setup do
new :cowboy_req new(:cowboy_req)
new JSX new(JSX)
on_exit fn -> unload() end on_exit(fn -> unload() end)
:ok :ok
end end
test "malformed_request returns true if query string is empty" do test "malformed_request returns true if query string is empty" do
expect(:cowboy_req, :qs_vals, 1, {[], :req2}) expect(:cowboy_req, :parse_qs, 1, [])
assert malformed_request(:req1, :state) == {true, :req2, :state} assert malformed_request(:req1, :state) == {true, :req1, :state}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "malformed_request returns false if query string is not empty" do test "malformed_request returns false if query string is not empty" do
expect(:cowboy_req, :qs_vals, 1, {[{"foo", "bar"}], :req2}) expect(:cowboy_req, :parse_qs, 1, [{"foo", "bar"}])
assert malformed_request(:req1, :state) == {false, :req2, [{"foo", "bar"}]} assert malformed_request(:req1, :state) == {false, :req1, [{"foo", "bar"}]}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "query string parameters are sent as headers" do test "query string parameters are sent as headers" do
expect(:cowboy_req, :set_resp_header, [{[:k1, :v1, :req1], :req2}, expect(:cowboy_req, :set_resp_header, [{[:k1, :v1, :req1], :req2}, {[:k2, :v2, :req2], :req3}])
{[:k2, :v2, :req2], :req3}])
expect(JSX, :encode!, [{[[k1: :v1, k2: :v2]], :json}]) expect(JSX, :encode!, [{[[k1: :v1, k2: :v2]], :json}])
assert get_json(:req1, [k1: :v1, k2: :v2]) == {:json, :req3, [k1: :v1, k2: :v2]} assert get_json(:req1, k1: :v1, k2: :v2) == {:json, :req3, [k1: :v1, k2: :v2]}
assert validate :cowboy_req assert validate(:cowboy_req)
assert validate JSX assert validate(JSX)
end end
end end

View file

@ -4,56 +4,72 @@ defmodule HTTParrot.SetCookiesHandlerTest do
import HTTParrot.SetCookiesHandler import HTTParrot.SetCookiesHandler
setup do setup do
new :cowboy_req new(:cowboy_req)
on_exit fn -> unload() end on_exit(fn -> unload() end)
:ok :ok
end end
test "malformed_request returns false if /name/value is sent" do test "malformed_request returns false if /name/value is sent" do
expect(:cowboy_req, :qs_vals, 1, {[], :req2}) expect(:cowboy_req, :parse_qs, 1, [])
expect(:cowboy_req, :binding, [{[:name, :req2, nil], {"name", :req3}},
{[:value, :req3, nil], {"value", :req4}}])
assert malformed_request(:req1, :state) == {false, :req4, [{"name", "value"}]} expect(:cowboy_req, :binding, [
{[:name, :req1, nil], "name"},
{[:value, :req1, nil], "value"}
])
assert validate :cowboy_req assert malformed_request(:req1, :state) == {false, :req1, [{"name", "value"}]}
assert validate(:cowboy_req)
end end
test "malformed_request returns query string values too if /name/value is sent" do test "malformed_request returns query string values too if /name/value is sent" do
expect(:cowboy_req, :qs_vals, 1, {[{"name", "value2"}], :req2}) expect(:cowboy_req, :parse_qs, 1, [{"name", "value2"}])
expect(:cowboy_req, :binding, [{[:name, :req2, nil], {"name", :req3}},
{[:value, :req3, nil], {"value", :req4}}])
assert malformed_request(:req1, :state) == {false, :req4, [{"name", "value"}]} expect(:cowboy_req, :binding, [
{[:name, :req1, nil], "name"},
{[:value, :req1, nil], "value"}
])
assert validate :cowboy_req expect(:cowboy_req, :binding, [
{[:name, :req1, nil], "name"},
{[:value, :req1, nil], "value"}
])
assert malformed_request(:req1, :state) == {false, :req1, [{"name", "value"}]}
assert validate(:cowboy_req)
end end
test "malformed_request returns false if query string values are sent" do test "malformed_request returns false if query string values are sent" do
expect(:cowboy_req, :qs_vals, 1, {[{"name", "value"}], :req2}) expect(:cowboy_req, :parse_qs, 1, [{"name", "value"}])
expect(:cowboy_req, :binding, [{[:name, :req2, nil], {nil, :req3}}]) expect(:cowboy_req, :binding, [{[:name, :req1, nil], nil}])
assert malformed_request(:req1, :state) == {false, :req3, [{"name", "value"}]} assert malformed_request(:req1, :state) == {false, :req1, [{"name", "value"}]}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "malformed_request returns true if query string values are not sent" do test "malformed_request returns true if query string values are not sent" do
expect(:cowboy_req, :qs_vals, 1, {[], :req2}) expect(:cowboy_req, :parse_qs, 1, [])
expect(:cowboy_req, :binding, [{[:name, :req2, nil], {nil, :req3}}]) expect(:cowboy_req, :binding, [{[:name, :req1, nil], nil}])
assert malformed_request(:req1, :state) == {true, :req3, :state} assert malformed_request(:req1, :state) == {true, :req1, :state}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "redirect to /cookies " do test "redirect to /cookies " do
expect(:cowboy_req, :set_resp_cookie, [{[:k1, :v1, [path: "/"], :req1], :req2}, expect(:cowboy_req, :set_resp_cookie, [
{[:k2, :v2, [path: "/"], :req2], :req3}]) {[:k1, :v1, :req1, %{path: "/"}], :req2},
expect(:cowboy_req, :reply, [{[302, [{"location", "/cookies"}], "Redirecting...", :req3], {:ok, :req4}}]) {[:k2, :v2, :req2, %{path: "/"}], :req3}
])
assert get_json(:req1, [k1: :v1, k2: :v2]) == {:halt, :req4, [k1: :v1, k2: :v2]} expect(:cowboy_req, :reply, [
{[302, %{"location" => "/cookies"}, "Redirecting...", :req3], :req4}
])
assert validate :cowboy_req assert get_json(:req1, k1: :v1, k2: :v2) == {:halt, :req4, [k1: :v1, k2: :v2]}
assert validate(:cowboy_req)
end end
end end

View file

@ -4,16 +4,16 @@ defmodule HTTParrot.StatusCodeHandlerTest do
import HTTParrot.StatusCodeHandler import HTTParrot.StatusCodeHandler
setup do setup do
new :cowboy_req new(:cowboy_req)
on_exit fn -> unload() end on_exit(fn -> unload() end)
:ok :ok
end end
test "reply with 'code' as status code" do test "reply with 'code' as status code" do
code = 123 code = 123
expect(:cowboy_req, :binding, [{[:code, :req1], {code, :req2}}]) expect(:cowboy_req, :binding, [{[:code, :req1], code}])
expect(:cowboy_req, :reply, [{[code, [], "", :req2], {:ok, :req3}}]) expect(:cowboy_req, :reply, [{[code, %{}, "", :req1], :req2}])
assert get_json(:req1, :state) == {:halt, :req3, :state} assert get_json(:req1, :state) == {:halt, :req2, :state}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
end end

View file

@ -5,19 +5,19 @@ defmodule HTTParrot.StoreRequestHandlerTests do
setup do setup do
HTTParrot.RequestStore.clear(:test) HTTParrot.RequestStore.clear(:test)
on_exit fn -> unload() end on_exit(fn -> unload() end)
:ok :ok
end end
test "store a request" do test "store a request" do
expect(:cowboy_req, :binding, [:key, :req1], {:test, :req1}) expect(:cowboy_req, :binding, [:key, :req1], :test)
expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {:info, :req1}) expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {:info, :req1})
assert get(:req1, :state) == {'{"saved": "true"}', :req1, :state} assert get(:req1, :state) == {'{"saved": "true"}', :req1, :state}
assert HTTParrot.RequestStore.retrieve(:test) == [:info] assert HTTParrot.RequestStore.retrieve(:test) == [:info]
end end
test "store multiple requests" do test "store multiple requests" do
expect(:cowboy_req, :binding, [:key, :req1], {:test, :req1}) expect(:cowboy_req, :binding, [:key, :req1], :test)
expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {:info, :req1}) expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {:info, :req1})
assert get(:req1, :state) == {'{"saved": "true"}', :req1, :state} assert get(:req1, :state) == {'{"saved": "true"}', :req1, :state}
assert get(:req2, :state) == {'{"saved": "true"}', :req1, :state} assert get(:req2, :state) == {'{"saved": "true"}', :req1, :state}

View file

@ -4,106 +4,106 @@ defmodule HTTParrot.StreamBytesHandlerTest do
import HTTParrot.StreamBytesHandler import HTTParrot.StreamBytesHandler
setup do setup do
new :cowboy_req new(:cowboy_req)
on_exit fn -> unload() end on_exit(fn -> unload() end)
:ok :ok
end end
test "malformed_request returns true if n is not an integer" do test "malformed_request returns true if n is not an integer" do
expect(:cowboy_req, :binding, [{[:n, :req1], {"a2B=", :req2}}]) expect(:cowboy_req, :binding, [{[:n, :req1], "a2B="}])
expect(:cowboy_req, :qs_val, fn name, req, default -> expect(:cowboy_req, :match_qs, fn [{name, [], default}], req ->
case {name, req, default} do case {name, req, default} do
{"seed", :req2, "1234"} -> {"1234", :req3} {:seed, :req1, "1234"} -> %{seed: "1234"}
{"chunk_size", :req3, "1024"} -> {"1024", :req4} {:chunk_size, :req1, "1024"} -> %{chunk_size: "1024"}
end end
end) end)
assert malformed_request(:req1, :state) == {true, :req4, :state} assert malformed_request(:req1, :state) == {true, :req1, :state}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "malformed_request returns false if n is an integer" do test "malformed_request returns false if n is an integer" do
expect(:cowboy_req, :binding, [{[:n, :req1], {"2", :req2}}]) expect(:cowboy_req, :binding, [{[:n, :req1], "2"}])
expect(:cowboy_req, :qs_val, fn name, req, default -> expect(:cowboy_req, :match_qs, fn [{name, [], default}], req ->
case {name, req, default} do case {name, req, default} do
{"seed", :req2, "1234"} -> {"1234", :req3} {:seed, :req1, "1234"} -> %{seed: "1234"}
{"chunk_size", :req3, "1024"} -> {"1024", :req4} {:chunk_size, :req1, "1024"} -> %{chunk_size: "1024"}
end end
end) end)
assert malformed_request(:req1, :state) == {false, :req4, {2, 1234, 1024}} assert malformed_request(:req1, :state) == {false, :req1, {2, 1234, 1024}}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "malformed_request returns true if seed is not an integer" do test "malformed_request returns true if seed is not an integer" do
expect(:cowboy_req, :binding, [{[:n, :req1], {"2", :req2}}]) expect(:cowboy_req, :binding, [{[:n, :req1], "2"}])
expect(:cowboy_req, :qs_val, fn name, req, default -> expect(:cowboy_req, :match_qs, fn [{name, [], default}], req ->
case {name, req, default} do case {name, req, default} do
{"seed", :req2, "1234"} -> {"a2B=", :req3} {:seed, :req1, "1234"} -> %{seed: "a2B="}
{"chunk_size", :req3, "1024"} -> {"1024", :req4} {:chunk_size, :req1, "1024"} -> %{chunk_size: "1024"}
end end
end) end)
assert malformed_request(:req1, :state) == {true, :req4, :state} assert malformed_request(:req1, :state) == {true, :req1, :state}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "malformed_request returns false if seed is an integer" do test "malformed_request returns false if seed is an integer" do
expect(:cowboy_req, :binding, [{[:n, :req1], {"2", :req2}}]) expect(:cowboy_req, :binding, [{[:n, :req1], "2"}])
expect(:cowboy_req, :qs_val, fn name, req, default -> expect(:cowboy_req, :match_qs, fn [{name, [], default}], req ->
case {name, req, default} do case {name, req, default} do
{"seed", :req2, "1234"} -> {"7", :req3} {:seed, :req1, "1234"} -> %{seed: "7"}
{"chunk_size", :req3, "1024"} -> {"1024", :req4} {:chunk_size, :req1, "1024"} -> %{chunk_size: "1024"}
end end
end) end)
assert malformed_request(:req1, :state) == {false, :req4, {2, 7, 1024}} assert malformed_request(:req1, :state) == {false, :req1, {2, 7, 1024}}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "malformed_request returns true if chunk_size is not an integer" do test "malformed_request returns true if chunk_size is not an integer" do
expect(:cowboy_req, :binding, [{[:n, :req1], {"2", :req2}}]) expect(:cowboy_req, :binding, [{[:n, :req1], "2"}])
expect(:cowboy_req, :qs_val, fn name, req, default -> expect(:cowboy_req, :match_qs, fn [{name, [], default}], req ->
case {name, req, default} do case {name, req, default} do
{"seed", :req2, "1234"} -> {"1234", :req3} {:seed, :req1, "1234"} -> %{seed: "1234"}
{"chunk_size", :req3, "1024"} -> {"a2B=", :req4} {:chunk_size, :req1, "1024"} -> %{chunk_size: "a2B="}
end end
end) end)
assert malformed_request(:req1, :state) == {true, :req4, :state} assert malformed_request(:req1, :state) == {true, :req1, :state}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "malformed_request returns false if chunk_size is an integer" do test "malformed_request returns false if chunk_size is an integer" do
expect(:cowboy_req, :binding, [{[:n, :req1], {"2", :req2}}]) expect(:cowboy_req, :binding, [{[:n, :req1], "2"}])
expect(:cowboy_req, :qs_val, fn name, req, default -> expect(:cowboy_req, :match_qs, fn [{name, [], default}], req ->
case {name, req, default} do case {name, req, default} do
{"seed", :req2, "1234"} -> {"1234", :req3} {:seed, :req1, "1234"} -> %{seed: "1234"}
{"chunk_size", :req3, "1024"} -> {"13", :req4} {:chunk_size, :req1, "1024"} -> %{chunk_size: "13"}
end end
end) end)
assert malformed_request(:req1, :state) == {false, :req4, {2, 1234, 13}} assert malformed_request(:req1, :state) == {false, :req1, {2, 1234, 13}}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "response must stream chunks" do test "response must stream chunks" do
assert {{:chunked, func}, :req1, nil} = get_bytes(:req1, {9, 3, 4}) assert {{:chunked, func}, :req1, nil} = get_bytes(:req1, {9, 3, 4})
assert is_function(func) assert is_function(func)
send_func = fn(body) -> send(self(), {:chunk, body}) end send_func = fn body -> send(self(), {:chunk, body}) end
func.(send_func) func.(send_func)
assert_receive {:chunk, chunk1} assert_receive {:chunk, chunk1}

View file

@ -4,60 +4,59 @@ defmodule HTTParrot.StreamHandlerTest do
import HTTParrot.StreamHandler import HTTParrot.StreamHandler
setup do setup do
new :cowboy_req new(:cowboy_req)
new HTTParrot.GeneralRequestInfo new(HTTParrot.GeneralRequestInfo)
new JSX new(JSX)
on_exit fn -> unload() end on_exit(fn -> unload() end)
:ok :ok
end end
test "malformed_request returns true if it's not an integer" do test "malformed_request returns true if it's not an integer" do
expect(:cowboy_req, :binding, [{[:n, :req1], {"a2B=", :req2}}]) expect(:cowboy_req, :binding, [{[:n, :req1], "a2B="}])
assert malformed_request(:req1, :state) == {true, :req2, :state} assert malformed_request(:req1, :state) == {true, :req1, :state}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "malformed_request returns false if it's an integer" do test "malformed_request returns false if it's an integer" do
expect(:cowboy_req, :binding, [{[:n, :req1], {"2", :req2}}]) expect(:cowboy_req, :binding, [{[:n, :req1], "2"}])
assert malformed_request(:req1, :state) == {false, :req2, 2} assert malformed_request(:req1, :state) == {false, :req1, 2}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "malformed_request returns 1 if 'n' is less than 1" do test "malformed_request returns 1 if 'n' is less than 1" do
expect(:cowboy_req, :binding, [{[:n, :req1], {"0", :req2}}]) expect(:cowboy_req, :binding, [{[:n, :req1], "0"}])
assert malformed_request(:req1, :state) == {false, :req2, 1} assert malformed_request(:req1, :state) == {false, :req1, 1}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "malformed_request returns 100 if 'n' is greater than 100" do test "malformed_request returns 100 if 'n' is greater than 100" do
expect(:cowboy_req, :binding, [{[:n, :req1], {"200", :req2}}]) expect(:cowboy_req, :binding, [{[:n, :req1], "200"}])
assert malformed_request(:req1, :state) == {false, :req2, 100} assert malformed_request(:req1, :state) == {false, :req1, 100}
assert validate :cowboy_req assert validate(:cowboy_req)
end end
test "response must stream chunks" do test "response must stream chunks" do
expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req2}) expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req2})
expect(JSX, :encode!, [{[[{:id, 0}, :info]], :json1}, expect(JSX, :encode!, [{[[{:id, 0}, :info]], :json1}, {[[{:id, 1}, :info]], :json2}])
{[[{:id, 1}, :info]], :json2}])
assert {{:chunked, func}, :req2, nil} = get_json(:req1, 2) assert {{:chunked, func}, :req2, nil} = get_json(:req1, 2)
assert is_function(func) assert is_function(func)
send_func = fn(body) -> send(self(), {:chunk, body}) end send_func = fn body -> send(self(), {:chunk, body}) end
func.(send_func) func.(send_func)
assert_receive {:chunk, :json1} assert_receive {:chunk, :json1}
assert_receive {:chunk, :json2} assert_receive {:chunk, :json2}
assert validate HTTParrot.GeneralRequestInfo assert validate(HTTParrot.GeneralRequestInfo)
assert validate JSX assert validate(JSX)
end end
end end

View file

@ -1 +1 @@
ExUnit.start ExUnit.start()