1
0
Fork 0
mirror of https://github.com/edgurgel/httparrot synced 2025-04-05 08:12:31 -04:00

updating to cowboy 2.5.0

This commit is contained in:
Alex S 2019-06-01 14:49:45 +07:00
parent 1bc15bf4c7
commit 9821d9ce61
47 changed files with 668 additions and 458 deletions

1
.gitignore vendored
View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -10,18 +10,18 @@ defmodule HTTParrot.DeflateHandler do
end
def get_json(req, state) do
zlib = :zlib.open
zlib = :zlib.open()
:zlib.deflateInit(zlib)
{info, req} = GeneralRequestInfo.retrieve(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)
:zlib.deflateEnd(zlib)
{response, req, state}
end
defp response(info) do
info |> JSX.encode!
info |> JSX.encode!()
end
end

View file

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

View file

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

View file

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

View file

@ -1,12 +1,13 @@
defmodule HTTParrot.GeneralRequestInfo do
def retrieve(req) do
{args, req} = :cowboy_req.qs_vals(req)
{headers, req} = :cowboy_req.headers(req)
{url, req} = :cowboy_req.url(req)
{{ip, port}, req} = :cowboy_req.peer(req)
args = :cowboy_req.parse_qs(req)
headers = :cowboy_req.headers(req)
url = :cowboy_req.uri(req)
{ip, _port} = :cowboy_req.peer(req)
ip = case {ip, port} do
{:local, _} -> ""
ip =
case ip do
{127, 0, 0, 1} -> ""
_ -> :inet_parse.ntoa(ip) |> to_string
end
@ -23,6 +24,7 @@ defmodule HTTParrot.GeneralRequestInfo do
"""
@spec group_by_keys(list) :: map
def group_by_keys([]), do: %{}
def group_by_keys(args) do
args
|> Enum.map(fn {k, v} -> %{k => v} end)

View file

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

View file

@ -12,11 +12,11 @@ defmodule HTTParrot.GzipHandler do
def get_json(req, state) do
{info, req} = GeneralRequestInfo.retrieve(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}
end
defp response(info) do
info |> JSX.encode!
info |> JSX.encode!()
end
end

View file

@ -6,11 +6,11 @@ defmodule HTTParrot.HeadersHandler do
end
def get_json(req, state) do
{headers, req} = :cowboy_req.headers(req)
headers = :cowboy_req.headers(req)
{response(headers), req, state}
end
defp response(headers) do
[headers: headers] |> JSX.encode!
[headers: headers] |> JSX.encode!()
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
"""
def resource_exists(req, state) do
{user, req} = :cowboy_req.binding(:user, req)
{passwd, req} = :cowboy_req.binding(:passwd, req)
{:ok, auth, req} = :cowboy_req.parse_header("authorization", req)
user = :cowboy_req.binding(:user, req)
passwd = :cowboy_req.binding(:passwd, req)
auth = :cowboy_req.parse_header("authorization", req)
case auth do
{"basic", {^user, ^passwd}} -> {true, req, user}
{:basic, ^user, ^passwd} -> {true, req, user}
_ -> {false, req, state}
end
end
@ -26,6 +27,6 @@ defmodule HTTParrot.HiddenBasicAuthHandler do
end
defp response(user) do
[authenticated: true, user: user] |> JSX.encode!
[authenticated: true, user: user] |> JSX.encode!()
end
end

View file

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

View file

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

View file

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

View file

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

View file

@ -5,7 +5,7 @@ defmodule HTTParrot.RedirectToHandler do
use HTTParrot.Cowboy, methods: ~w(GET HEAD OPTIONS)
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}
end

View file

@ -12,7 +12,7 @@ defmodule HTTParrot.RelativeRedirectHandler do
def previously_existed(req, state), do: {true, req, state}
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}
end
end

View file

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

View file

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

View file

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

View file

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

View file

@ -6,11 +6,13 @@ defmodule HTTParrot.StoreRequestHandler do
use HTTParrot.Cowboy, methods: ~w(GET POST PUT HEAD OPTIONS)
def content_types_accepted(req, state) do
{[{{"application", "json", :*}, :post_binary},
{[
{{"application", "json", :*}, :post_binary},
{{"application", "octet-stream", :*}, :post_binary},
{{"text", "plain", :*}, :post_binary},
{{"application", "x-www-form-urlencoded", :*}, :post_form},
{{"multipart", "form-data", :*}, :post_multipart}], req, state}
{{"multipart", "form-data", :*}, :post_multipart}
], req, state}
end
def content_types_provided(req, state) do
@ -26,22 +28,23 @@ defmodule HTTParrot.StoreRequestHandler do
def post_binary(req, _state) do
{:ok, body, req} = HTTParrot.PHandler.handle_binary(req)
if String.valid?(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
save_post(req, [form: [{}], data: body, json: nil])
save_post(req, form: [{}], data: body, json: nil)
end
else
# Octet-stream
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
def post_form(req, _state) do
{:ok, body, req} = :cowboy_req.body_qs(req)
save_post(req, [form: body, data: "", json: nil])
{:ok, body, req} = :cowboy_req.read_urlencoded_body(req)
save_post(req, form: body, data: "", json: nil)
end
def post_multipart(req, _state) do
@ -50,9 +53,12 @@ defmodule HTTParrot.StoreRequestHandler do
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)}
save_post(req, [form: HTTParrot.PHandler.normalize_list(form_parts),
save_post(req,
form: HTTParrot.PHandler.normalize_list(form_parts),
files: HTTParrot.PHandler.normalize_list(file_parts),
data: "", json: nil])
data: "",
json: nil
)
end
def save_post(req, body) do
@ -62,5 +68,4 @@ defmodule HTTParrot.StoreRequestHandler do
{:ok, req} = :cowboy_req.reply(200, [], '{"saved": "true"}', req)
{:halt, req, nil}
end
end

View file

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

View file

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

View file

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

View file

@ -1,15 +1,16 @@
defmodule HTTParrot.WebsocketHandler do
@behaviour :cowboy_websocket_handler
@behaviour :cowboy_websocket
@moduledoc """
Echo given messages through websocket connection
"""
def init(_transport, _req, _opts), do: {:upgrade, :protocol, :cowboy_websocket}
def websocket_init(_transport, req, _opts), do: {:ok, req, nil}
def init(req, state), do: {:cowboy_websocket, req, state}
def websocket_init(state), do: {:ok, state}
def websocket_handle({:text, text}, req, state), do: {:reply, {:text, text}, req, state}
def websocket_handle({:binary, binary}, req, state), do: {:reply, {:binary, binary}, req, state}
def websocket_info(_info, req, state), do: {:ok, req, state}
def websocket_handle({:text, text}, state), do: {:reply, {:text, text}, state}
def websocket_handle({:binary, binary}, state), do: {:reply, {:binary, binary}, 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

43
mix.exs
View file

@ -6,39 +6,50 @@ defmodule Httparrot.Mixfile do
"""
def project do
[ app: :httparrot,
version: "1.1.0",
[
app: :httparrot,
version: "1.2.0",
elixir: "~> 1.4",
name: "HTTParrot",
description: @description,
package: package(),
deps: deps() ]
deps: deps()
]
end
def application do
[ applications: [ :compiler,
:syntax_tools,
:cowboy,
:exjsx,
:con_cache ],
mod: { HTTParrot, [] },
env: [ http_port: 8080, ssl: true, https_port: 8433,
unix_socket: true, socket_path: "httparrot.sock"] ]
[
applications: [:compiler, :syntax_tools, :cowboy, :exjsx, :con_cache],
mod: {HTTParrot, []},
env: [
http_port: 8080,
ssl: true,
https_port: 8433,
unix_socket: true,
socket_path: "httparrot.sock"
]
]
end
defp deps do
[ {:cowboy, "~> 1.1.2"},
[
{:cowboy, "~> 2.5.0"},
{:exjsx, "~> 3.0 or ~> 4.0"},
{:con_cache, "~> 0.12.0"},
{:ex_doc, "~> 0.14", only: :dev},
{:meck, "~> 0.8.2", only: :test } ]
{:meck, "~> 0.8.13", only: :test}
]
end
defp package do
[ maintainers: ["Eduardo Gurgel Pinho"],
[
maintainers: ["Eduardo Gurgel Pinho"],
licenses: ["MIT"],
links: %{ "Github" => "https://github.com/edgurgel/httparrot",
links: %{
"Github" => "https://github.com/edgurgel/httparrot",
"HTTParrot" => "http://httparrot.herokuapp.com",
"httpbin" => "http://httpbin.org" } ]
"httpbin" => "http://httpbin.org"
}
]
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"},
"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"},
"cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [:make], [], "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, "2.6.0", "8aa629f81a0fc189f261dc98a42243fa842625feea3c7ec56c48f4ccdb55490f", [:rebar3], [], "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"},
"exactor": {:hex, :exactor, "2.2.3", "a6972f43bb6160afeb73e1d8ab45ba604cd0ac8b5244c557093f6e92ce582786", [:mix], [], "hexpm"},
@ -9,7 +9,7 @@
"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_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"},
"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
setup do
new :cowboy_req
new JSX
on_exit fn -> unload() end
new(:cowboy_req)
new(JSX)
on_exit(fn -> unload() end)
:ok
end
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], :req2})
expect(JSX, :encode!, [{[[cookies: [k1: :v1]]], :json}])
assert get_json(:req1, :state) == {:json, :req2, :state}
assert validate :cowboy_req
assert validate JSX
assert validate(:cowboy_req)
assert validate(JSX)
end
end

View file

@ -4,43 +4,43 @@ defmodule HTTParrot.DelayedHandlerTest do
import HTTParrot.DelayedHandler
setup do
new HTTParrot.GeneralRequestInfo
new JSX
new :cowboy_req
on_exit fn -> unload() end
new(HTTParrot.GeneralRequestInfo)
new(JSX)
new(:cowboy_req)
on_exit(fn -> unload() end)
:ok
end
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
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
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
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
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 validate HTTParrot.GeneralRequestInfo
assert validate JSX
assert validate(HTTParrot.GeneralRequestInfo)
assert validate(JSX)
end
end

View file

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

View file

@ -4,19 +4,19 @@ defmodule HTTParrot.HeadersHandlerTest do
import HTTParrot.HeadersHandler
setup do
new :cowboy_req
new JSX
on_exit fn -> unload() end
new(:cowboy_req)
new(JSX)
on_exit(fn -> unload() end)
:ok
end
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}])
assert get_json(:req1, :state) == {:json, :req2, :state}
assert get_json(:req1, :state) == {:json, :req1, :state}
assert validate :cowboy_req
assert validate JSX
assert validate(:cowboy_req)
assert validate(JSX)
end
end

View file

@ -4,32 +4,39 @@ defmodule HTTParrot.HiddenBasicAuthHandlerTest do
import HTTParrot.HiddenBasicAuthHandler
setup do
new :cowboy_req
new JSX
on_exit fn -> unload() end
new(:cowboy_req)
new(JSX)
on_exit(fn -> unload() end)
:ok
end
test "resource_exists returns true if user and passwd match" do
expect(:cowboy_req, :binding, [{[:user, :req1], {:user, :req2}},
{[:passwd, :req2], {:passwd, :req3}}])
expect(:cowboy_req, :parse_header, [{["authorization", :req3], {:ok, {"basic", {:user, :passwd}}, :req4}}])
expect(:cowboy_req, :binding, [
{[:user, :req1], :user},
{[: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 validate JSX
assert resource_exists(:req1, :state) == {true, :req1, :user}
assert validate(:cowboy_req)
assert validate(JSX)
end
test "resource_exists returns false if user and passwd doesnt match" do
expect(:cowboy_req, :binding, [{[:user, :req1], {:user, :req2}},
{[:passwd, :req2], {:passwd, :req3}}])
expect(:cowboy_req, :parse_header, [{["authorization", :req3], {:ok, {"basic", {:not_the_user, :passwd}}, :req4}}])
expect(:cowboy_req, :binding, [{[:user, :req1], :user}, {[:passwd, :req1], :passwd}])
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 validate JSX
assert resource_exists(:req1, :state) == {false, :req1, :state}
assert validate(:cowboy_req)
assert validate(JSX)
end
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 validate JSX
assert validate(JSX)
end
end

View file

@ -4,16 +4,18 @@ defmodule HTTParrotTest do
import HTTParrot
setup do
new :cowboy_req
on_exit fn -> unload() end
new(:cowboy_req)
on_exit(fn -> unload() end)
:ok
end
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}}])
assert prettify_json(:status, [{"content-length", '12'}], "{\"a\":\"b\"}", :req1) == :req2
assert validate :cowboy_req
expect(:cowboy_req, :reply, [
{[:status, %{"content-length" => '14'}, "{\n \"a\": \"b\"\n}", :req1], :req2}
])
assert prettify_json(:status, %{"content-length" => '12'}, "{\"a\":\"b\"}", :req1) == :req2
assert validate(:cowboy_req)
end
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
setup do
new :cowboy_req
new JSX
on_exit fn -> unload() end
new(:cowboy_req)
new(JSX)
on_exit(fn -> unload() end)
:ok
end
test "returns prettified json with origin" do
ip = {127, 1, 2, 3}
expect(:cowboy_req, :peer, 1, {{ip, :host}, :req2})
expect(:cowboy_req, :parse_header, 2, {:ok, :undefined, :req2})
expect(:cowboy_req, :peer, 1, {ip, 0})
expect(:cowboy_req, :parse_header, 2, :undefined)
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 JSX
assert validate(:cowboy_req)
assert validate(JSX)
end
test "returns prettified json with client ip when available" do
ip = {127, 1, 2, 3}
expect(:cowboy_req, :peer, 1, {{ip, :host}, :req2})
expect(:cowboy_req, :parse_header, 2, {:ok, ["190.1.2.3"], :req2})
expect(:cowboy_req, :peer, 1, {ip, 0})
expect(:cowboy_req, :parse_header, 2, ["190.1.2.3"])
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 JSX
assert validate(:cowboy_req)
assert validate(JSX)
end
test "returns empty when running over unix sockets" do
expect(:cowboy_req, :peer, 1, {{:local, ""}, :req2})
expect(:cowboy_req, :parse_header, 2, {:ok, :undefined, :req2})
expect(:cowboy_req, :peer, 1, {{127, 0, 0, 1}, 0})
expect(:cowboy_req, :parse_header, 2, :undefined)
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 JSX
assert validate(:cowboy_req)
assert validate(JSX)
end
end

View file

@ -4,51 +4,55 @@ defmodule HTTParrot.PHandlerTest do
import HTTParrot.PHandler
setup do
new HTTParrot.GeneralRequestInfo
new JSX
new :cowboy_req
on_exit fn -> unload() end
new(HTTParrot.GeneralRequestInfo)
new(JSX)
new(:cowboy_req)
on_exit(fn -> unload() end)
:ok
end
Enum.each [{"/post", "POST"},
{"/patch", "PATCH"},
{"/put", "PUT"}], fn {path, verb} ->
Enum.each(
[{"/post", "POST"}, {"/patch", "PATCH"}, {"/put", "PUT"}],
fn {path, verb} ->
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
)
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(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req3})
expect(JSX, :encode!, [{[[:info, {:form, :body_qs}, {:data, ""}, {:json, nil}]], :response}])
assert post_form(:req1, :state) == {true, :req4, nil}
assert validate HTTParrot.GeneralRequestInfo
assert validate(HTTParrot.GeneralRequestInfo)
end
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(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req3})
expect(JSX, :is_json?, 1, true)
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 validate HTTParrot.GeneralRequestInfo
assert validate(HTTParrot.GeneralRequestInfo)
end
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(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req3})
expect(JSX, :is_json?, 1, false)
@ -56,28 +60,40 @@ defmodule HTTParrot.PHandlerTest do
assert post_binary(:req1, :state) == {true, :req4, nil}
assert validate HTTParrot.GeneralRequestInfo
assert validate(HTTParrot.GeneralRequestInfo)
end
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(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req3})
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 validate HTTParrot.GeneralRequestInfo
assert validate(HTTParrot.GeneralRequestInfo)
end
test "returns json with general info and P[OST, UT, ATCH] non-JSON body data for a chunked request" do
first_chunk = "first chunk"
second_chunk = "second chunk"
expect(:cowboy_req, :body, fn req ->
expect(:cowboy_req, :read_body, fn req ->
case req do
:req1 ->
{:more, first_chunk, :req2}
:req2 ->
{:ok, second_chunk, :req3}
end
@ -86,20 +102,25 @@ defmodule HTTParrot.PHandlerTest do
expect(:cowboy_req, :set_resp_body, [{[:response, :req4], :req5}])
expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req4})
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 validate HTTParrot.GeneralRequestInfo
assert validate(HTTParrot.GeneralRequestInfo)
end
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"
expect(:cowboy_req, :body, fn req ->
expect(:cowboy_req, :read_body, fn req ->
case req do
:req1 ->
{:more, first_chunk, :req2}
:req2 ->
{:ok, second_chunk, :req3}
end
@ -108,126 +129,204 @@ defmodule HTTParrot.PHandlerTest do
expect(:cowboy_req, :set_resp_body, [{[:response, :req4], :req5}])
expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req4})
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 validate HTTParrot.GeneralRequestInfo
assert validate(HTTParrot.GeneralRequestInfo)
end
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
:req1 ->
{:ok, [{"content-disposition", "form-data; name=\"key1\""}], :req2}
{:ok, %{"content-disposition" => "form-data; name=\"key1\""}, :req2}
:req3 ->
{:done, :req4}
end
end)
expect(:cowboy_req, :part_body, [{[:req2], {:ok, "value1", :req3}}])
expect(:cowboy_req, :parse_header,
[{["content-type", :req4],
{:ok, {"multipart", "form-data", [{"boundary", "----WebKitFormBoundary8BEQxJvZANFsvRV9"}]}, :req5}}])
expect(:cowboy_req, :read_part_body, [{[:req2], {:ok, "value1", :req3}}])
expect(:cowboy_req, :parse_header, [
{["content-type", :req4],
{:ok, {"multipart", "form-data", [{"boundary", "----WebKitFormBoundary8BEQxJvZANFsvRV9"}]},
:req5}}
])
expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req6})
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}])
assert post_multipart(:req1, :state) == {true, :req7, nil}
assert validate HTTParrot.GeneralRequestInfo
assert validate(HTTParrot.GeneralRequestInfo)
end
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
:req1 ->
{:ok, [{"content-disposition", "form-data; name=\"key1\""}], :req2}
{:ok, %{"content-disposition" => "form-data; name=\"key1\""}, :req2}
:req3 ->
{:ok, [{"content-disposition", "form-data; name=\"key2\""}], :req4}
{:ok, %{"content-disposition" => "form-data; name=\"key2\""}, :req4}
:req5 ->
{:done, :req6}
end
end)
expect(:cowboy_req, :part_body, fn req ->
expect(:cowboy_req, :read_part_body, fn req ->
case req do
:req2 -> {:ok, "value1", :req3}
:req4 -> {:ok, "value2", :req5}
end
end)
expect(:cowboy_req, :parse_header,
[{["content-type", :req6],
{:ok, {"multipart", "form-data", [{"boundary", "----WebKitFormBoundary8BEQxJvZANFsvRV9"}]}, :req7}}])
expect(:cowboy_req, :parse_header, [
{["content-type", :req6],
{:ok, {"multipart", "form-data", [{"boundary", "----WebKitFormBoundary8BEQxJvZANFsvRV9"}]},
:req7}}
])
expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req8})
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}])
assert post_multipart(:req1, :state) == {true, :req9, nil}
assert validate HTTParrot.GeneralRequestInfo
assert validate(HTTParrot.GeneralRequestInfo)
end
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
: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 ->
{:done, :req4}
end
end)
expect(:cowboy_req, :part_body, [{[:req2], {:ok, "here is some cool\ntest data.", :req3}}])
expect(:cowboy_req, :parse_header,
[{["content-type", :req4],
{:ok, {"multipart", "form-data", [{"boundary", "----WebKitFormBoundary8BEQxJvZANFsvRV9"}]}, :req5}}])
expect(:cowboy_req, :read_part_body, [
{[:req2], {:ok, "here is some cool\ntest data.", :req3}}
])
expect(:cowboy_req, :parse_header, [
{["content-type", :req4],
{:ok, {"multipart", "form-data", [{"boundary", "----WebKitFormBoundary8BEQxJvZANFsvRV9"}]},
:req5}}
])
expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req6})
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}])
assert post_multipart(:req1, :state) == {true, :req7, nil}
assert validate HTTParrot.GeneralRequestInfo
assert validate(HTTParrot.GeneralRequestInfo)
end
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
:req1 ->
{:ok, [{"content-disposition", "form-data; name=\"key1\""}], :req2}
{:ok, %{"content-disposition" => "form-data; name=\"key1\""}, :req2}
: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 ->
{:done, :req6}
end
end)
expect(:cowboy_req, :part_body, fn req ->
expect(:cowboy_req, :read_part_body, fn req ->
case req do
:req2 -> {:ok, "value1", :req3}
:req4 -> {:ok, "here is some cool\ntest data", :req5}
end
end)
expect(:cowboy_req, :parse_header,
[{["content-type", :req6],
{:ok, {"multipart", "form-data", [{"boundary", "----WebKitFormBoundary8BEQxJvZANFsvRV9"}]}, :req7}}])
expect(:cowboy_req, :parse_header, [
{["content-type", :req6],
{:ok, {"multipart", "form-data", [{"boundary", "----WebKitFormBoundary8BEQxJvZANFsvRV9"}]},
:req7}}
])
expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req8})
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}])
assert post_multipart(:req1, :state) == {true, :req9, nil}
assert validate HTTParrot.GeneralRequestInfo
assert validate(HTTParrot.GeneralRequestInfo)
end
end

View file

@ -4,8 +4,8 @@ defmodule HTTParrot.RedirectHandlerTest do
import HTTParrot.RedirectHandler
setup do
new :cowboy_req
on_exit fn -> unload() end
new(:cowboy_req)
on_exit(fn -> unload() end)
:ok
end
@ -14,7 +14,7 @@ defmodule HTTParrot.RedirectHandlerTest do
assert malformed_request(:req1, :state) == {true, :req2, :state}
assert validate :cowboy_req
assert validate(:cowboy_req)
end
test "malformed_request returns false if it's an integer" do
@ -22,7 +22,7 @@ defmodule HTTParrot.RedirectHandlerTest do
assert malformed_request(:req1, :state) == {false, :req2, 2}
assert validate :cowboy_req
assert validate(:cowboy_req)
end
test "malformed_request returns 1 if 'n' is less than 1" do
@ -30,23 +30,22 @@ defmodule HTTParrot.RedirectHandlerTest do
assert malformed_request(:req1, :state) == {false, :req2, 1}
assert validate :cowboy_req
assert validate(:cowboy_req)
end
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", :req2})
assert moved_permanently(:req1, 4) == {{true, "host/redirect/3"}, :req2, nil}
assert validate :cowboy_req
assert validate(:cowboy_req)
end
test "moved_permanently returns '/get' if n = 1" do
expect(:cowboy_req, :host_url, 1, {"host", :req2})
expect(:cowboy_req, :uri, 1, {"host", :req2})
assert moved_permanently(:req1, 1) == {{true, "host/get"}, :req2, nil}
assert validate :cowboy_req
assert validate(:cowboy_req)
end
end

View file

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

View file

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

View file

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

View file

@ -4,15 +4,15 @@ defmodule HTTParrot.StreamBytesHandlerTest do
import HTTParrot.StreamBytesHandler
setup do
new :cowboy_req
on_exit fn -> unload() end
new(:cowboy_req)
on_exit(fn -> unload() end)
:ok
end
test "malformed_request returns true if n is not an integer" do
expect(:cowboy_req, :binding, [{[:n, :req1], {"a2B=", :req2}}])
expect(:cowboy_req, :qs_val, fn name, req, default ->
expect(:cowboy_req, :match_qs, fn [name, req], default ->
case {name, req, default} do
{"seed", :req2, "1234"} -> {"1234", :req3}
{"chunk_size", :req3, "1024"} -> {"1024", :req4}
@ -21,13 +21,13 @@ defmodule HTTParrot.StreamBytesHandlerTest do
assert malformed_request(:req1, :state) == {true, :req4, :state}
assert validate :cowboy_req
assert validate(:cowboy_req)
end
test "malformed_request returns false if n is an integer" do
expect(:cowboy_req, :binding, [{[:n, :req1], {"2", :req2}}])
expect(:cowboy_req, :qs_val, fn name, req, default ->
expect(:cowboy_req, :match_qs, fn [name, req], default ->
case {name, req, default} do
{"seed", :req2, "1234"} -> {"1234", :req3}
{"chunk_size", :req3, "1024"} -> {"1024", :req4}
@ -36,13 +36,13 @@ defmodule HTTParrot.StreamBytesHandlerTest do
assert malformed_request(:req1, :state) == {false, :req4, {2, 1234, 1024}}
assert validate :cowboy_req
assert validate(:cowboy_req)
end
test "malformed_request returns true if seed is not an integer" do
expect(:cowboy_req, :binding, [{[:n, :req1], {"2", :req2}}])
expect(:cowboy_req, :qs_val, fn name, req, default ->
expect(:cowboy_req, :match_qs, fn [name, req], default ->
case {name, req, default} do
{"seed", :req2, "1234"} -> {"a2B=", :req3}
{"chunk_size", :req3, "1024"} -> {"1024", :req4}
@ -51,13 +51,13 @@ defmodule HTTParrot.StreamBytesHandlerTest do
assert malformed_request(:req1, :state) == {true, :req4, :state}
assert validate :cowboy_req
assert validate(:cowboy_req)
end
test "malformed_request returns false if seed is an integer" do
expect(:cowboy_req, :binding, [{[:n, :req1], {"2", :req2}}])
expect(:cowboy_req, :qs_val, fn name, req, default ->
expect(:cowboy_req, :match_qs, fn [name, req], default ->
case {name, req, default} do
{"seed", :req2, "1234"} -> {"7", :req3}
{"chunk_size", :req3, "1024"} -> {"1024", :req4}
@ -66,13 +66,13 @@ defmodule HTTParrot.StreamBytesHandlerTest do
assert malformed_request(:req1, :state) == {false, :req4, {2, 7, 1024}}
assert validate :cowboy_req
assert validate(:cowboy_req)
end
test "malformed_request returns true if chunk_size is not an integer" do
expect(:cowboy_req, :binding, [{[:n, :req1], {"2", :req2}}])
expect(:cowboy_req, :qs_val, fn name, req, default ->
expect(:cowboy_req, :match_qs, fn [name, req], default ->
case {name, req, default} do
{"seed", :req2, "1234"} -> {"1234", :req3}
{"chunk_size", :req3, "1024"} -> {"a2B=", :req4}
@ -81,13 +81,13 @@ defmodule HTTParrot.StreamBytesHandlerTest do
assert malformed_request(:req1, :state) == {true, :req4, :state}
assert validate :cowboy_req
assert validate(:cowboy_req)
end
test "malformed_request returns false if chunk_size is an integer" do
expect(:cowboy_req, :binding, [{[:n, :req1], {"2", :req2}}])
expect(:cowboy_req, :qs_val, fn name, req, default ->
expect(:cowboy_req, :match_qs, fn [name, req], default ->
case {name, req, default} do
{"seed", :req2, "1234"} -> {"1234", :req3}
{"chunk_size", :req3, "1024"} -> {"13", :req4}
@ -96,14 +96,14 @@ defmodule HTTParrot.StreamBytesHandlerTest do
assert malformed_request(:req1, :state) == {false, :req4, {2, 1234, 13}}
assert validate :cowboy_req
assert validate(:cowboy_req)
end
test "response must stream chunks" do
assert {{:chunked, func}, :req1, nil} = get_bytes(:req1, {9, 3, 4})
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)
assert_receive {:chunk, chunk1}

View file

@ -4,60 +4,59 @@ defmodule HTTParrot.StreamHandlerTest do
import HTTParrot.StreamHandler
setup do
new :cowboy_req
new HTTParrot.GeneralRequestInfo
new JSX
on_exit fn -> unload() end
new(:cowboy_req)
new(HTTParrot.GeneralRequestInfo)
new(JSX)
on_exit(fn -> unload() end)
:ok
end
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
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
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
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
test "response must stream chunks" do
expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req2})
expect(JSX, :encode!, [{[[{:id, 0}, :info]], :json1},
{[[{:id, 1}, :info]], :json2}])
expect(JSX, :encode!, [{[[{:id, 0}, :info]], :json1}, {[[{:id, 1}, :info]], :json2}])
assert {{:chunked, func}, :req2, nil} = get_json(:req1, 2)
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)
assert_receive {:chunk, :json1}
assert_receive {:chunk, :json2}
assert validate HTTParrot.GeneralRequestInfo
assert validate JSX
assert validate(HTTParrot.GeneralRequestInfo)
assert validate(JSX)
end
end