mirror of
https://github.com/edgurgel/httparrot
synced 2025-04-05 08:12:31 -04:00
Compare commits
50 commits
Author | SHA1 | Date | |
---|---|---|---|
|
cb6373be97 | ||
|
e716a1a327 | ||
|
4f87d8262a | ||
|
ca31d47221 | ||
|
690dc6fc30 | ||
|
5982706dbb | ||
|
312b6723f3 | ||
|
d2607766b0 | ||
|
6b30597487 | ||
|
71675f8d3d | ||
|
aa7ca908f0 | ||
|
d6d83a8ac6 | ||
|
3b7d5d5eea | ||
|
b09754cae3 | ||
|
c638ef7ef9 | ||
|
171d74bb75 | ||
|
5b3409d5b1 | ||
|
3666f9db39 | ||
|
44c68b2f4e | ||
|
deb4015277 | ||
|
d411887e09 | ||
|
eb91575330 | ||
|
5fe28208a3 | ||
|
dec8d9a039 | ||
|
cccd19a0fe | ||
|
1f4f716124 | ||
|
545101d50c | ||
|
755a9fa827 | ||
|
7f59106d14 | ||
|
dbee63e5ea | ||
|
c43ac0dc7c | ||
|
c9ce3f0bc4 | ||
|
65d9502c74 | ||
|
3d13a6a680 | ||
|
8f179399de | ||
|
0d9c6f6854 | ||
|
3f2bbe78df | ||
|
eedc9798bc | ||
|
9821d9ce61 | ||
|
1bc15bf4c7 | ||
|
10e2633bf9 | ||
|
8f4b1a4a89 | ||
|
e355751abf | ||
|
84fa15df9b | ||
|
f3ed8f8ba3 | ||
|
41367be61f | ||
|
03c68d85a6 | ||
|
82600a98c8 | ||
|
fa901347cd | ||
|
9552b529c4 |
81 changed files with 1287 additions and 771 deletions
4
.formatter.exs
Normal file
4
.formatter.exs
Normal file
|
@ -0,0 +1,4 @@
|
|||
# Used by "mix format"
|
||||
[
|
||||
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
|
||||
]
|
54
.github/workflows/main.yml
vendored
Normal file
54
.github/workflows/main.yml
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
name: CI
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
format:
|
||||
name: Format & credo
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2.3.1
|
||||
|
||||
- name: Install OTP and Elixir
|
||||
uses: erlef/setup-beam@v1
|
||||
with:
|
||||
otp-version: 26.x
|
||||
elixir-version: 1.16.x
|
||||
|
||||
- name: Install dependencies
|
||||
run: mix deps.get
|
||||
|
||||
- name: Compile with --warnings-as-errors
|
||||
run: mix compile --warnings-as-errors
|
||||
|
||||
- name: Run "mix format"
|
||||
run: mix format --check-formatted
|
||||
|
||||
test:
|
||||
name: Test (Elixir ${{matrix.elixir}} | Erlang/OTP ${{matrix.otp}})
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- otp: 26.x
|
||||
elixir: 1.16.x
|
||||
coverage: true
|
||||
- otp: 27.x
|
||||
elixir: 1.17.x
|
||||
env:
|
||||
MIX_ENV: test
|
||||
steps:
|
||||
- uses: actions/checkout@v2.3.1
|
||||
|
||||
- name: Install OTP and Elixir
|
||||
uses: erlef/setup-beam@v1
|
||||
with:
|
||||
otp-version: ${{matrix.otp}}
|
||||
elixir-version: ${{matrix.elixir}}
|
||||
|
||||
- name: Install dependencies
|
||||
run: mix deps.get --only test
|
||||
|
||||
- name: Run tests
|
||||
run: mix test --trace
|
27
.gitignore
vendored
27
.gitignore
vendored
|
@ -1,5 +1,26 @@
|
|||
/_build
|
||||
/deps
|
||||
# The directory Mix will write compiled artifacts to.
|
||||
/_build/
|
||||
|
||||
# If you run "mix test --cover", coverage assets end up here.
|
||||
/cover/
|
||||
|
||||
# The directory Mix downloads your dependencies sources to.
|
||||
/deps/
|
||||
|
||||
# Where third-party dependencies like ExDoc output generated docs.
|
||||
/doc/
|
||||
|
||||
# Ignore .fetch files in case you like to edit your project deps locally.
|
||||
/.fetch
|
||||
|
||||
# If the VM crashes, it generates a dump, let's ignore it too.
|
||||
erl_crash.dump
|
||||
|
||||
# Also ignore archive artifacts (built via "mix archive.build").
|
||||
*.ez
|
||||
/doc
|
||||
|
||||
# Ignore package tarball (built via "mix hex.build").
|
||||
httparrot-*.tar
|
||||
|
||||
# Temporary files, for example, from tests.
|
||||
/tmp/
|
||||
|
|
12
.travis.yml
12
.travis.yml
|
@ -1,12 +0,0 @@
|
|||
language: elixir
|
||||
notifications:
|
||||
recipients:
|
||||
- eduardo@gurgel.me
|
||||
elixir:
|
||||
- 1.4.2
|
||||
otp_release:
|
||||
- 18.0
|
||||
- 18.1
|
||||
- 19.0
|
||||
sudo: false
|
||||
script: mix test
|
38
Dockerfile
Normal file
38
Dockerfile
Normal file
|
@ -0,0 +1,38 @@
|
|||
# Based on https://github.com/hexpm/hexpm/blob/08e80ed4fe82b145f6cee1d01da16e162add2a56/Dockerfile
|
||||
FROM elixir:1.9.0-alpine as build
|
||||
|
||||
ENV MIX_ENV=prod
|
||||
|
||||
RUN mkdir /app
|
||||
WORKDIR /app
|
||||
|
||||
RUN mix local.hex --force && mix local.rebar --force
|
||||
|
||||
# install mix dependencies
|
||||
COPY mix.exs mix.lock ./
|
||||
COPY config config
|
||||
RUN mix deps.get
|
||||
RUN mix deps.compile
|
||||
|
||||
# build project
|
||||
COPY priv priv
|
||||
COPY lib lib
|
||||
RUN mix compile
|
||||
|
||||
# build release
|
||||
COPY rel rel
|
||||
RUN mix release
|
||||
|
||||
# prepare release image
|
||||
FROM alpine:3.9 AS app
|
||||
RUN apk add --update bash openssl
|
||||
|
||||
RUN mkdir /app
|
||||
WORKDIR /app
|
||||
|
||||
COPY --from=build /app/_build/prod/rel/httparrot ./
|
||||
RUN chown -R nobody: /app
|
||||
USER nobody
|
||||
|
||||
ENV HOME=/app
|
||||
CMD /app/bin/httparrot start
|
|
@ -1,4 +1,6 @@
|
|||
Copyright (c) 2013-2014 Eduardo Gurgel Pinho
|
||||
# The MIT License
|
||||
|
||||
Copyright (c) 2013 Eduardo Gurgel <eduardo@gurgel.me>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
85
README.md
85
README.md
|
@ -1,49 +1,56 @@
|
|||
# HTTParrot [](https://travis-ci.org/edgurgel/httparrot)
|
||||
# HTTParrot
|
||||
|
||||
HTTP server built on top of Cowboy using (mostly) `cowboy_rest` handlers to serve useful endpoints for testing purposes. Its goal is to be as close as possible to [HTTPBin](http://httpbin.org).
|
||||
[](https://travis-ci.org/edgurgel/httparrot)
|
||||
[](https://hex.pm/packages/httparrot)
|
||||
[](https://hexdocs.pm/httparrot/)
|
||||
[](https://hex.pm/packages/httparrot)
|
||||
[](https://github.com/edgurgel/httparrot/blob/master/LICENSE.md)
|
||||
[](https://github.com/edgurgel/httparrot/commits/master)
|
||||
|
||||
HTTP server built on top of [Cowboy](https://hex.pm/packages/cowboy) using (mostly) `cowboy_rest` handlers to serve useful endpoints for testing purposes. Its goal is to be as close as possible to [HTTPBin](http://httpbin.org).
|
||||
|
||||
## Endpoints
|
||||
|
||||
* / This page.
|
||||
* /ip Returns Origin IP.
|
||||
* /user-agent Returns user-agent.
|
||||
* /headers Returns header dict.
|
||||
* /get Returns GET data.
|
||||
* /post Returns POST data.
|
||||
* /put Returns PUT data.
|
||||
* /patch Returns PATCH data.
|
||||
* /delete Returns DELETE data
|
||||
* /gzip Returns gzip-encoded data.
|
||||
* /status/:code Returns given HTTP Status code.
|
||||
* /response-headers?key=val Returns given response headers.
|
||||
* /redirect/:n 301 Redirects n times.
|
||||
* /redirect-to?url=foo 301 Redirects to the foo URL.
|
||||
* /relative-redirect/:n 301 Relative redirects n times.
|
||||
* /cookies Returns cookie data.
|
||||
* /cookies/set?name=value Sets one or more simple cookies.
|
||||
* /cookies/set/name/value Sets one cookie .
|
||||
* /cookies/delete?name Deletes one or more simple cookies.
|
||||
* /basic-auth/:user/:passwd Challenges HTTPBasic Auth.
|
||||
* /hidden-basic-auth/:user/:passwd 404'd BasicAuth.
|
||||
* /digest-auth/:qop/:user/:passwd Challenges HTTP Digest Auth.
|
||||
* /stream/:n Streams n–100 lines.
|
||||
* /delay/:n Delays responding for n–10 seconds.
|
||||
* /html Renders an HTML Page.
|
||||
* /robots.txt Returns some robots.txt rules.
|
||||
* /deny Denied by robots.txt file.
|
||||
* /cache Returns 200 unless an If-Modified-Since header is provided, when it returns a 304 Not Modified.
|
||||
* /base64/:value Decodes base64url-encoded string.
|
||||
* /image Return an image based on Accept header.
|
||||
* /websocket Echo message received through websocket
|
||||
* `/` This page.
|
||||
* `/ip` Returns Origin IP.
|
||||
* `/user-agent` Returns user-agent.
|
||||
* `/headers` Returns header dict.
|
||||
* `/get` Returns GET data.
|
||||
* `/post` Returns POST data.
|
||||
* `/put` Returns PUT data.
|
||||
* `/patch` Returns PATCH data.
|
||||
* `/delete` Returns DELETE data
|
||||
* `/gzip` Returns gzip-encoded data.
|
||||
* `/status/:code` Returns given HTTP Status code.
|
||||
* `/response-headers?key=val` Returns given response headers.
|
||||
* `/redirect/:n` 301 Redirects n times.
|
||||
* `/redirect-to?url=foo` 301 Redirects to the foo URL.
|
||||
* `/relative-redirect/:n` 301 Relative redirects n times.
|
||||
* `/cookies` Returns cookie data.
|
||||
* `/cookies/set?name=value` Sets one or more simple cookies.
|
||||
* `/cookies/set/name/value` Sets one cookie .
|
||||
* `/cookies/delete?name` Deletes one or more simple cookies.
|
||||
* `/basic-auth/:user/:passwd` Challenges HTTPBasic Auth.
|
||||
* `/hidden-basic-auth/:user/:passwd` 404'd BasicAuth.
|
||||
* `/digest-auth/:qop/:user/:passwd` Challenges HTTP Digest Auth.
|
||||
* `/stream/:n` Streams n–100 lines.
|
||||
* `/delay/:n` Delays responding for n–10 seconds.
|
||||
* `/html` Renders an HTML Page.
|
||||
* `/robots.txt` Returns some robots.txt rules.
|
||||
* `/deny` Denied by robots.txt file.
|
||||
* `/cache` Returns 200 unless an If-Modified-Since header is provided, when it returns a 304 Not Modified.
|
||||
* `/base64/:value` Decodes base64url-encoded string.
|
||||
* `/image` Return an image based on Accept header.
|
||||
* `/websocket` Echo message received through websocket
|
||||
|
||||
## TODO
|
||||
|
||||
* [ ] /deflate Returns deflate-encoded data.
|
||||
* [ ] /digest-auth/:qop/:user/:passwd Challenges HTTP Digest Auth.
|
||||
* [ ] `/deflate` Returns deflate-encoded data.
|
||||
* [ ] `/digest-auth/:qop/:user/:passwd` Challenges HTTP Digest Auth.
|
||||
|
||||
## License
|
||||
## Copyright and License
|
||||
|
||||
Copyright 2013-2016 Eduardo Gurgel <eduardo@gurgel.me>
|
||||
Copyright (c) 2013 Eduardo Gurgel <eduardo@gurgel.me>
|
||||
|
||||
This work is free. You can redistribute it and/or modify it under the
|
||||
terms of the MIT License. See the LICENSE file for more details.
|
||||
This work is free. You can redistribute it and/or modify it under the
|
||||
terms of the MIT License. See the [LICENSE.md](./LICENSE.md) file for more details.
|
||||
|
|
10
build.sh
Executable file
10
build.sh
Executable file
|
@ -0,0 +1,10 @@
|
|||
#!/usr/bin/env bash
|
||||
# exit on error
|
||||
set -o errexit
|
||||
|
||||
# Initial setup
|
||||
mix deps.get --only prod
|
||||
MIX_ENV=prod mix compile
|
||||
|
||||
# Build the release and overwrite the existing release directory
|
||||
MIX_ENV=prod mix release --overwrite
|
16
config/config.exs
Normal file
16
config/config.exs
Normal file
|
@ -0,0 +1,16 @@
|
|||
import Config
|
||||
|
||||
port = System.get_env("PORT", "8080")
|
||||
port = String.to_integer(port)
|
||||
|
||||
ssl_port = System.get_env("SSL_PORT", "8433")
|
||||
ssl_port = String.to_integer(ssl_port)
|
||||
|
||||
unix_socket = System.get_env("UNIX_SOCKET", "false")
|
||||
unix_socket = if unix_socket == "true", do: true, else: false
|
||||
|
||||
config :httparrot,
|
||||
http_port: port,
|
||||
https_port: ssl_port,
|
||||
unix_socket: unix_socket,
|
||||
socket_path: System.get_env("SOCKET_PATH", "httparrot.sock")
|
16
config/runtime.exs
Normal file
16
config/runtime.exs
Normal file
|
@ -0,0 +1,16 @@
|
|||
import Config
|
||||
|
||||
port = System.get_env("PORT", "8080")
|
||||
port = String.to_integer(port)
|
||||
|
||||
ssl_port = System.get_env("SSL_PORT", "8433")
|
||||
ssl_port = String.to_integer(ssl_port)
|
||||
|
||||
unix_socket = System.get_env("UNIX_SOCKET", "false")
|
||||
unix_socket = if unix_socket == "true", do: true, else: false
|
||||
|
||||
config :httparrot,
|
||||
http_port: port,
|
||||
https_port: ssl_port,
|
||||
unix_socket: unix_socket,
|
||||
socket_path: System.get_env("SOCKET_PATH", "httparrot.sock")
|
147
lib/httparrot.ex
147
lib/httparrot.ex
|
@ -7,95 +7,120 @@ defmodule HTTParrot do
|
|||
end
|
||||
|
||||
def init(_) do
|
||||
supervise([], strategy: :simple_one_for_one)
|
||||
Supervisor.start_link([], strategy: :one_for_one)
|
||||
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,
|
||||
[port: http_port],
|
||||
[env: [dispatch: dispatch],
|
||||
onresponse: &prettify_json/4])
|
||||
IO.puts("Starting HTTParrot on port #{http_port}")
|
||||
|
||||
{:ok, _} =
|
||||
:cowboy.start_clear(
|
||||
:http,
|
||||
[port: http_port],
|
||||
%{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 ++ ~c"/ssl/server-ca.crt",
|
||||
certfile: priv_dir ++ ~c"/ssl/server.crt",
|
||||
keyfile: priv_dir ++ ~c"/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,
|
||||
[port: 0, ip: {:local, socket_path}],
|
||||
[env: [dispatch: dispatch], onresponse: &prettify_json/4])
|
||||
IO.puts("Starting HTTParrot on unix socket #{socket_path}")
|
||||
|
||||
{:ok, _} =
|
||||
:cowboy.start_clear(
|
||||
:http_unix,
|
||||
[port: 0, ip: {:local, socket_path}],
|
||||
%{env: %{dispatch: dispatch}}
|
||||
)
|
||||
end
|
||||
|
||||
Supervisor.start_link([
|
||||
worker(ConCache, [[
|
||||
ttl_check: :timer.minutes(5),
|
||||
ttl: :timer.hours(12)
|
||||
], [name: :requests_registry]])
|
||||
], strategy: :one_for_one)
|
||||
Supervisor.start_link(
|
||||
[
|
||||
{ConCache,
|
||||
[
|
||||
ttl_check_interval: :timer.minutes(5),
|
||||
global_ttl: :timer.hours(12),
|
||||
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_char_list(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
|
||||
|
|
|
@ -9,16 +9,16 @@ defmodule HTTParrot.Base64Handler do
|
|||
end
|
||||
|
||||
def malformed_request(req, state) do
|
||||
{value, req} = :cowboy_req.binding(:value, req)
|
||||
value = :cowboy_req.binding(:value, req)
|
||||
|
||||
case decode(value) do
|
||||
{ :ok, result } -> {false, req, result}
|
||||
:error -> {true, req, state}
|
||||
{: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
|
||||
|
|
|
@ -5,11 +5,12 @@ defmodule HTTParrot.BasicAuthHandler do
|
|||
use HTTParrot.Cowboy, methods: ~w(GET HEAD OPTIONS)
|
||||
|
||||
def is_authorized(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, "Basic realm=\"Fake Realm\""}, req, state}
|
||||
end
|
||||
end
|
||||
|
@ -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
|
||||
|
|
|
@ -19,6 +19,6 @@ defmodule HTTParrot.CacheHandler do
|
|||
end
|
||||
|
||||
defp response(info) do
|
||||
info |> JSX.encode!
|
||||
info |> JSX.encode!()
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,12 +9,12 @@ defmodule HTTParrot.CookiesHandler do
|
|||
end
|
||||
|
||||
def get_json(req, state) do
|
||||
{cookies, req} = :cowboy_req.cookies(req)
|
||||
cookies = :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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = :cowboy_req.parse_qs(req)
|
||||
if Enum.empty?(qs_vals), do: {true, req, state}, else: {false, req, qs_vals}
|
||||
end
|
||||
|
||||
|
@ -14,15 +14,18 @@ defmodule HTTParrot.DeleteCookiesHandler do
|
|||
end
|
||||
|
||||
def get_json(req, qs_vals) do
|
||||
req = Enum.reduce qs_vals, req, fn({name, value}, req) ->
|
||||
delete_cookie(name, value, req)
|
||||
end
|
||||
{:ok, req} = :cowboy_req.reply(302, [{"location", "/cookies"}], "Redirecting...", req)
|
||||
{:halt, req, qs_vals}
|
||||
req =
|
||||
Enum.reduce(qs_vals, req, fn {name, value}, req ->
|
||||
delete_cookie(name, value, req)
|
||||
end)
|
||||
|
||||
req = :cowboy_req.reply(302, %{"location" => "/cookies"}, "Redirecting...", req)
|
||||
{:stop, 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)
|
||||
:cowboy_req.set_resp_cookie(name, value, req, %{path: "/", max_age: 0})
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,6 +5,10 @@ defmodule HTTParrot.DeleteHandler do
|
|||
alias HTTParrot.GeneralRequestInfo
|
||||
use HTTParrot.Cowboy, methods: ~w(DELETE)
|
||||
|
||||
def content_types_provided(req, state) do
|
||||
{[{{"application", "json", []}, :get_json}], req, state}
|
||||
end
|
||||
|
||||
def delete_resource(req, state) do
|
||||
{info, req} = GeneralRequestInfo.retrieve(req)
|
||||
req = :cowboy_req.set_resp_body(response(info), req)
|
||||
|
@ -12,6 +16,6 @@ defmodule HTTParrot.DeleteHandler do
|
|||
end
|
||||
|
||||
defp response(info) do
|
||||
info |> JSX.encode!
|
||||
info |> JSX.encode!()
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,7 +18,7 @@ defmodule HTTParrot.DenyHandler do
|
|||
\ .-"` `"-. /
|
||||
'. .'
|
||||
'-......-'
|
||||
YOU SHOUDN'T BE HERE
|
||||
YOU SHOULDN'T BE HERE
|
||||
"""
|
||||
def get_plain(req, state) do
|
||||
{@body, req, state}
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
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 = IO.iodata_to_binary(:cowboy_req.uri(req))
|
||||
{ip, _port} = :cowboy_req.peer(req)
|
||||
|
||||
ip = case {ip, port} do
|
||||
{:local, _} -> ""
|
||||
_ -> :inet_parse.ntoa(ip) |> to_string
|
||||
end
|
||||
ip =
|
||||
case ip do
|
||||
{127, 0, 0, 1} -> ""
|
||||
:local -> ""
|
||||
_ -> :inet_parse.ntoa(ip) |> to_string
|
||||
end
|
||||
|
||||
args = group_by_keys(args)
|
||||
|
||||
|
@ -18,11 +20,12 @@ defmodule HTTParrot.GeneralRequestInfo do
|
|||
@doc """
|
||||
Group by keys and if duplicated keys, aggregate them as a list
|
||||
|
||||
iex> group_by_keys([a: "v1", a: "v2", b: "v3", a: "v4"])
|
||||
%{a: ["v1", "v2", "v4"], b: "v3"}
|
||||
iex> group_by_keys([{"a", "v1"}, {"a", "v2"}, {"b", "v3"}, {"a", "v4"}])
|
||||
%{"a" => ["v1", "v2", "v4"], "b" => "v3"}
|
||||
"""
|
||||
@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)
|
||||
|
|
|
@ -15,6 +15,6 @@ defmodule HTTParrot.GetHandler do
|
|||
end
|
||||
|
||||
defp response(info) do
|
||||
info |> JSX.encode!
|
||||
info |> JSX.encode!()
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -9,17 +9,32 @@ defmodule HTTParrot.IPHandler do
|
|||
end
|
||||
|
||||
def get_json(req, state) do
|
||||
{{ip, _port}, req} = :cowboy_req.peer(req)
|
||||
{ip, _port} = :cowboy_req.peer(req)
|
||||
forwarded_for = :cowboy_req.parse_header("x-forwarded-for", req)
|
||||
|
||||
{response(ip), req, state}
|
||||
case forwarded_for do
|
||||
:undefined ->
|
||||
{response(ip), req, state}
|
||||
|
||||
_ ->
|
||||
{response(to_tuple(forwarded_for)), req, state}
|
||||
end
|
||||
end
|
||||
|
||||
defp response(:local) do
|
||||
[origin: ""] |> JSX.encode!
|
||||
defp to_tuple(client_ip) do
|
||||
client_ip
|
||||
|> hd
|
||||
|> String.split(".")
|
||||
|> Enum.map(fn x -> String.to_integer(x) end)
|
||||
|> List.to_tuple()
|
||||
end
|
||||
|
||||
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
|
||||
|
|
|
@ -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 = String.slice(path, 1..-1)
|
||||
path = :cowboy_req.path(req)
|
||||
path = String.slice(path, 1..-1//1)
|
||||
{[String.upcase(path)], req, state}
|
||||
end
|
||||
|
||||
def content_types_accepted(req, state) do
|
||||
{[{{"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}
|
||||
{[
|
||||
{{"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}
|
||||
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,21 +114,22 @@ 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(";")
|
||||
|> Enum.map(&String.strip/1)
|
||||
parts =
|
||||
String.split(header, ";")
|
||||
|> Enum.map(&String.trim/1)
|
||||
|
||||
for part <- parts, into: %{} do
|
||||
case String.split(part, "=") |> Enum.map(&String.strip/1) do
|
||||
case String.split(part, "=") |> Enum.map(&String.trim/1) do
|
||||
[type] -> {:type, type}
|
||||
[key, value] -> {key, String.replace(value, "\"", "")}
|
||||
end
|
||||
|
|
|
@ -5,9 +5,10 @@ defmodule HTTParrot.RedirectHandler 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 |> max(1)
|
||||
n = n |> String.to_integer() |> max(1)
|
||||
{false, req, n}
|
||||
rescue
|
||||
ArgumentError -> {true, req, state}
|
||||
|
@ -18,8 +19,12 @@ 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 =
|
||||
IO.iodata_to_binary(
|
||||
:cowboy_req.uri(req, %{path: :undefined, qs: :undefined, fragment: :undefined})
|
||||
)
|
||||
|
||||
url = if n > 1, do: "/redirect/#{n - 1}", else: "/get"
|
||||
{{true, host_url <> url}, req, nil}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
defmodule HTTParrot.RequestStore do
|
||||
@moduledoc """
|
||||
Used to store and retrived requests
|
||||
Used to store and retrieved requests
|
||||
"""
|
||||
@doc """
|
||||
Store the requests to the key
|
||||
|
@ -15,15 +15,18 @@ defmodule HTTParrot.RequestStore do
|
|||
"""
|
||||
def retrieve(key) do
|
||||
entry = ConCache.get(:requests_registry, key)
|
||||
|
||||
case entry do
|
||||
nil -> []
|
||||
_ ->
|
||||
entry
|
||||
nil ->
|
||||
[]
|
||||
|
||||
_ ->
|
||||
entry
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Clear the saved data on the coresponding key
|
||||
Clear the saved data on the corresponding key
|
||||
"""
|
||||
def clear(key) do
|
||||
ConCache.delete(:requests_registry, key)
|
||||
|
|
|
@ -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 = :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) ->
|
||||
:cowboy_req.set_resp_header(key, value, req)
|
||||
end
|
||||
req =
|
||||
Enum.reduce(qs_vals, req, fn {key, value}, req ->
|
||||
:cowboy_req.set_resp_header(key, value, req)
|
||||
end)
|
||||
|
||||
{response(qs_vals), req, qs_vals}
|
||||
end
|
||||
|
||||
defp response(qs_vals) do
|
||||
qs_vals |> JSX.encode!
|
||||
qs_vals |> JSX.encode!()
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
defmodule HTTParrot.RetrieveRequestHandler do
|
||||
@moduledoc """
|
||||
Retreive saved request and clear the conresponding :id
|
||||
Retrieve saved request and clear the conresponding :id
|
||||
"""
|
||||
use HTTParrot.Cowboy, methods: ~w(GET POST PUT HEAD OPTIONS)
|
||||
|
||||
|
@ -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
|
||||
|
|
|
@ -5,10 +5,11 @@ 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)
|
||||
{name, req} = :cowboy_req.binding(:name, req, nil)
|
||||
qs_vals = :cowboy_req.parse_qs(req)
|
||||
name = :cowboy_req.binding(:name, req, nil)
|
||||
|
||||
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})}
|
||||
else
|
||||
if Enum.empty?(qs_vals), do: {true, req, state}, else: {false, req, qs_vals}
|
||||
|
@ -20,14 +21,16 @@ defmodule HTTParrot.SetCookiesHandler do
|
|||
end
|
||||
|
||||
def get_json(req, qs_vals) do
|
||||
req = Enum.reduce qs_vals, req, fn({name, value}, req) ->
|
||||
set_cookie(name, value, req)
|
||||
end
|
||||
{:ok, req} = :cowboy_req.reply(302, [{"location", "/cookies"}], "Redirecting...", req)
|
||||
{:halt, req, qs_vals}
|
||||
req =
|
||||
Enum.reduce(qs_vals, req, fn {name, value}, req ->
|
||||
set_cookie(name, value, req)
|
||||
end)
|
||||
|
||||
req = :cowboy_req.reply(302, %{"location" => "/cookies"}, "Redirecting...", req)
|
||||
{:stop, req, qs_vals}
|
||||
end
|
||||
|
||||
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
|
||||
|
|
|
@ -9,8 +9,8 @@ defmodule HTTParrot.StatusCodeHandler do
|
|||
end
|
||||
|
||||
def get_json(req, state) do
|
||||
{code, req} = :cowboy_req.binding(:code, req)
|
||||
{:ok, req} = :cowboy_req.reply(code, [], "", req)
|
||||
{:halt, req, state}
|
||||
code = :cowboy_req.binding(:code, req)
|
||||
req = :cowboy_req.reply(code, %{}, "", req)
|
||||
{:stop, req, state}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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", "octet-stream", :*}, :post_binary},
|
||||
{{"text", "plain", :*}, :post_binary},
|
||||
{{"application", "x-www-form-urlencoded", :*}, :post_form},
|
||||
{{"multipart", "form-data", :*}, :post_multipart}], req, state}
|
||||
{[
|
||||
{{"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}
|
||||
end
|
||||
|
||||
def content_types_provided(req, state) do
|
||||
|
@ -19,29 +21,30 @@ defmodule HTTParrot.StoreRequestHandler do
|
|||
|
||||
def get(req, state) do
|
||||
{info, req} = GeneralRequestInfo.retrieve(req)
|
||||
{key, _} = :cowboy_req.binding(:key, req)
|
||||
key = :cowboy_req.binding(:key, req)
|
||||
HTTParrot.RequestStore.store(key, info)
|
||||
{'{"saved": "true"}', req, state}
|
||||
{~c'{"saved": "true"}', req, state}
|
||||
end
|
||||
|
||||
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,17 +53,19 @@ 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),
|
||||
files: HTTParrot.PHandler.normalize_list(file_parts),
|
||||
data: "", json: nil])
|
||||
save_post(req,
|
||||
form: HTTParrot.PHandler.normalize_list(form_parts),
|
||||
files: HTTParrot.PHandler.normalize_list(file_parts),
|
||||
data: "",
|
||||
json: nil
|
||||
)
|
||||
end
|
||||
|
||||
def save_post(req, body) do
|
||||
{info, req} = GeneralRequestInfo.retrieve(req)
|
||||
{key, req} = :cowboy_req.binding(:key, req)
|
||||
key = :cowboy_req.binding(:key, req)
|
||||
HTTParrot.RequestStore.store(key, info ++ body)
|
||||
{:ok, req} = :cowboy_req.reply(200, [], '{"saved": "true"}', req)
|
||||
{:halt, req, nil}
|
||||
req = :cowboy_req.reply(200, %{}, "{\"saved\": \"true\"}", req)
|
||||
{:stop, req, nil}
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -9,14 +9,14 @@ defmodule HTTParrot.StreamBytesHandler do
|
|||
end
|
||||
|
||||
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")
|
||||
n = :cowboy_req.binding(:n, req)
|
||||
%{seed: seed} = :cowboy_req.match_qs([{:seed, [], "1234"}], req)
|
||||
%{chunk_size: chunk_size} = :cowboy_req.match_qs([{:chunk_size, [], "1024"}], req)
|
||||
|
||||
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}
|
||||
|
@ -26,17 +26,21 @@ defmodule HTTParrot.StreamBytesHandler do
|
|||
def get_bytes(req, state) do
|
||||
{n, seed, chunk_size} = state
|
||||
:rand.seed(:exs64, {seed, seed, seed})
|
||||
{{:chunked, stream_response(n, chunk_size)}, req, nil}
|
||||
req = stream_response!(n, chunk_size, req)
|
||||
{:stop, req, nil}
|
||||
end
|
||||
|
||||
defp stream_response(n, chunk_size) do
|
||||
fn(send_func) ->
|
||||
Stream.repeatedly(fn -> :rand.uniform(255) end)
|
||||
|> Stream.take(n)
|
||||
|> Enum.chunk(chunk_size, chunk_size, [])
|
||||
|> Enum.each(fn chunk ->
|
||||
send_func.(List.to_string(chunk))
|
||||
end)
|
||||
end
|
||||
defp stream_response!(n, chunk_size, req) do
|
||||
req = :cowboy_req.stream_reply(200, %{"content-type" => "application/octet-stream"}, req)
|
||||
|
||||
Stream.repeatedly(fn -> :rand.uniform(255) end)
|
||||
|> Stream.take(n)
|
||||
|> Enum.chunk_every(chunk_size, chunk_size, [])
|
||||
|> Enum.each(fn chunk ->
|
||||
:cowboy_req.stream_body(List.to_string(chunk), :nofin, req)
|
||||
end)
|
||||
|
||||
:cowboy_req.stream_body("", :fin, req)
|
||||
req
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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}
|
||||
|
@ -24,14 +25,14 @@ defmodule HTTParrot.StreamHandler do
|
|||
|
||||
def get_json(req, n) do
|
||||
{info, req} = GeneralRequestInfo.retrieve(req)
|
||||
{{:chunked, stream_response(n, info)}, req, nil}
|
||||
end
|
||||
req = :cowboy_req.stream_reply(200, %{"content-type" => "application/json"}, req)
|
||||
|
||||
defp stream_response(n, info) do
|
||||
fn(send_func) ->
|
||||
Enum.each 0..n-1, fn (i) ->
|
||||
send_func.([id: i] ++ info |> JSX.encode!)
|
||||
end
|
||||
end
|
||||
Enum.each(0..(n - 1), fn i ->
|
||||
body = JSX.encode!([id: i] ++ info)
|
||||
:cowboy_req.stream_body(body, :nofin, req)
|
||||
end)
|
||||
|
||||
:cowboy_req.stream_body("", :fin, req)
|
||||
{:stop, req, nil}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,12 +9,12 @@ defmodule HTTParrot.UserAgentHandler do
|
|||
end
|
||||
|
||||
def get_json(req, state) do
|
||||
{user_agent, req} = :cowboy_req.header("user-agent", req, "null")
|
||||
user_agent = :cowboy_req.header("user-agent", req, "null")
|
||||
{response(user_agent), req, state}
|
||||
end
|
||||
|
||||
defp response(user_agent) do
|
||||
[{"user-agent", user_agent}]
|
||||
|> JSX.encode!
|
||||
|> JSX.encode!()
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
|
66
mix.exs
66
mix.exs
|
@ -1,44 +1,62 @@
|
|||
defmodule Httparrot.Mixfile do
|
||||
use Mix.Project
|
||||
|
||||
@description """
|
||||
HTTP Request & Response Server. An incomplete clone of http://httpbin.org
|
||||
"""
|
||||
@source_url "https://github.com/edgurgel/httparrot"
|
||||
@version "1.4.0"
|
||||
|
||||
def project do
|
||||
[ app: :httparrot,
|
||||
version: "1.0.0",
|
||||
elixir: "~> 1.4",
|
||||
[
|
||||
app: :httparrot,
|
||||
version: @version,
|
||||
elixir: "~> 1.16",
|
||||
name: "HTTParrot",
|
||||
description: @description,
|
||||
package: package(),
|
||||
deps: deps() ]
|
||||
deps: deps(),
|
||||
docs: docs()
|
||||
]
|
||||
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"] ]
|
||||
[
|
||||
extra_applications: [:logger],
|
||||
mod: {HTTParrot, []}
|
||||
]
|
||||
end
|
||||
|
||||
defp deps do
|
||||
[ {:cowboy, "~> 1.1.2"},
|
||||
[
|
||||
{:cowboy, "~> 2.12"},
|
||||
{:exjsx, "~> 3.0 or ~> 4.0"},
|
||||
{:con_cache, "~> 0.12.0"},
|
||||
{:ex_doc, ">= 0.0.0", only: :dev},
|
||||
{:meck, "~> 0.8.2", only: :test } ]
|
||||
{:con_cache, "~> 1.1"},
|
||||
{:earmark, "~> 1.0", only: :dev},
|
||||
{:ex_doc, "~> 0.18", only: :dev},
|
||||
{:meck, "~> 0.9", only: :test}
|
||||
]
|
||||
end
|
||||
|
||||
defp package do
|
||||
[ contributors: ["Eduardo Gurgel Pinho"],
|
||||
[
|
||||
description: "https://github.com/edgurgel/httparrot",
|
||||
maintainers: ["Eduardo Gurgel Pinho"],
|
||||
licenses: ["MIT"],
|
||||
links: %{ "Github" => "https://github.com/edgurgel/httparrot",
|
||||
"HTTParrot" => "http://httparrot.herokuapp.com",
|
||||
"httpbin" => "http://httpbin.org" } ]
|
||||
links: %{
|
||||
"Github" => @source_url,
|
||||
"HTTParrot" => "https://httparrot.onrender.com/",
|
||||
"httpbin" => "http://httpbin.org"
|
||||
}
|
||||
]
|
||||
end
|
||||
|
||||
defp docs do
|
||||
[
|
||||
extras: [
|
||||
"LICENSE.md": [title: "License"],
|
||||
"README.md": [title: "Overview"]
|
||||
],
|
||||
main: "readme",
|
||||
source_url: @source_url,
|
||||
source_ref: "v#{@version}",
|
||||
formatters: ["html"]
|
||||
]
|
||||
end
|
||||
end
|
||||
|
|
27
mix.lock
27
mix.lock
|
@ -1,10 +1,17 @@
|
|||
%{"con_cache": {:hex, :con_cache, "0.12.0", "2d961aec219aa5a914473873f348f5a6088292dc69d5192a9d25f8a1e13e9905", [:mix], [{:exactor, "~> 2.2.0", [hex: :exactor, optional: false]}]},
|
||||
"cowboy": {:hex, :cowboy, "1.1.2", "61ac29ea970389a88eca5a65601460162d370a70018afe6f949a29dca91f3bb0", [:rebar3], [{:cowlib, "~> 1.0.2", [hex: :cowlib, optional: false]}, {:ranch, "~> 1.3.2", [hex: :ranch, optional: false]}]},
|
||||
"cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [:make], []},
|
||||
"earmark": {:hex, :earmark, "1.0.1", "2c2cd903bfdc3de3f189bd9a8d4569a075b88a8981ded9a0d95672f6e2b63141", [:mix], []},
|
||||
"ex_doc": {:hex, :ex_doc, "0.13.0", "aa2f8fe4c6136a2f7cfc0a7e06805f82530e91df00e2bff4b4362002b43ada65", [:mix], [{:earmark, "~> 1.0", [hex: :earmark, optional: false]}]},
|
||||
"exactor": {:hex, :exactor, "2.2.3", "a6972f43bb6160afeb73e1d8ab45ba604cd0ac8b5244c557093f6e92ce582786", [:mix], []},
|
||||
"exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, optional: false]}]},
|
||||
"jsx": {:hex, :jsx, "2.8.2", "7acc7d785b5abe8a6e9adbde926a24e481f29956dd8b4df49e3e4e7bcc92a018", [:mix, :rebar3], []},
|
||||
"meck": {:hex, :meck, "0.8.2", "f15f7d513e14ec8c8dee9a95d4ae585b3e5a88bf0fa6a7573240d6ddb58a7236", [:make, :rebar], []},
|
||||
"ranch": {:hex, :ranch, "1.3.2", "e4965a144dc9fbe70e5c077c65e73c57165416a901bd02ea899cfd95aa890986", [:rebar3], []}}
|
||||
%{
|
||||
"con_cache": {:hex, :con_cache, "1.1.0", "45c7c6cd6dc216e47636232e8c683734b7fe293221fccd9454fa1757bc685044", [:mix], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "8655f2ae13a1e56c8aef304d250814c7ed929c12810f126fc423ecc8e871593b"},
|
||||
"cowboy": {:hex, :cowboy, "2.12.0", "f276d521a1ff88b2b9b4c54d0e753da6c66dd7be6c9fca3d9418b561828a3731", [:make, :rebar3], [{:cowlib, "2.13.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "8a7abe6d183372ceb21caa2709bec928ab2b72e18a3911aa1771639bef82651e"},
|
||||
"cowlib": {:hex, :cowlib, "2.13.0", "db8f7505d8332d98ef50a3ef34b34c1afddec7506e4ee4dd4a3a266285d282ca", [:make, :rebar3], [], "hexpm", "e1e1284dc3fc030a64b1ad0d8382ae7e99da46c3246b815318a4b848873800a4"},
|
||||
"earmark": {:hex, :earmark, "1.4.46", "8c7287bd3137e99d26ae4643e5b7ef2129a260e3dcf41f251750cb4563c8fb81", [:mix], [], "hexpm", "798d86db3d79964e759ddc0c077d5eb254968ed426399fbf5a62de2b5ff8910a"},
|
||||
"earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"},
|
||||
"ex_doc": {:hex, :ex_doc, "0.34.1", "9751a0419bc15bc7580c73fde506b17b07f6402a1e5243be9e0f05a68c723368", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "d441f1a86a235f59088978eff870de2e815e290e44a8bd976fe5d64470a4c9d2"},
|
||||
"exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm", "32e95820a97cffea67830e91514a2ad53b888850442d6d395f53a1ac60c82e07"},
|
||||
"jsx": {:hex, :jsx, "2.8.3", "a05252d381885240744d955fbe3cf810504eb2567164824e19303ea59eef62cf", [:mix, :rebar3], [], "hexpm", "fc3499fed7a726995aa659143a248534adc754ebd16ccd437cd93b649a95091f"},
|
||||
"makeup": {:hex, :makeup, "1.1.2", "9ba8837913bdf757787e71c1581c21f9d2455f4dd04cfca785c70bbfff1a76a3", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cce1566b81fbcbd21eca8ffe808f33b221f9eee2cbc7a1706fc3da9ff18e6cac"},
|
||||
"makeup_elixir": {:hex, :makeup_elixir, "0.16.2", "627e84b8e8bf22e60a2579dad15067c755531fea049ae26ef1020cad58fe9578", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "41193978704763f6bbe6cc2758b84909e62984c7752b3784bd3c218bb341706b"},
|
||||
"makeup_erlang": {:hex, :makeup_erlang, "1.0.0", "6f0eff9c9c489f26b69b61440bf1b238d95badae49adac77973cbacae87e3c2e", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "ea7a9307de9d1548d2a72d299058d1fd2339e3d398560a0e46c27dab4891e4d2"},
|
||||
"meck": {:hex, :meck, "0.9.2", "85ccbab053f1db86c7ca240e9fc718170ee5bda03810a6292b5306bf31bae5f5", [:rebar3], [], "hexpm", "81344f561357dc40a8344afa53767c32669153355b626ea9fcbc8da6b3045826"},
|
||||
"nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"},
|
||||
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
|
||||
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"},
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
|
||||
<div class='mp'>
|
||||
<h1>httparrot(1): HTTP Request & Response Service</h1>
|
||||
<p>Freely hosted in <a href="http://httparrot.herokuapp.com">HTTP</a> & <a href="https://httparrot.herokuapp.com">HTTPS</a>
|
||||
<p>Freely hosted in <a href="https://httparrot.onrender.com/">HTTPS</a>
|
||||
|
||||
<h2 id="ENDPOINTS">ENDPOINTS</h2>
|
||||
|
||||
|
@ -104,34 +104,46 @@ scenarios. Additional endpoints are being considered (e.g. <code>/deflate</code>
|
|||
|
||||
<h2 id="EXAMPLES">EXAMPLES</h2>
|
||||
|
||||
<h3 id="-curl-http-httparrot-org-ip">$ curl http://httparrot.herokuapp.com/ip</h3>
|
||||
<h3 id="-curl-http-httparrot-org-ip">$ curl https://httparrot.onrender.com/</h3>
|
||||
|
||||
<pre><code>{"origin": "24.127.96.129"}
|
||||
</code></pre>
|
||||
|
||||
<h3 id="-curl-http-httparrot-org-user-agent">$ curl http://httparrot.herokuapp.com/user-agent</h3>
|
||||
<h3 id="-curl-http-httparrot-org-user-agent">$ curl https://httparrot.onrender.com/user-agent</h3>
|
||||
|
||||
<pre><code>{"user-agent": "curl/7.19.7 (universal-apple-darwin10.0) libcurl/7.19.7 OpenSSL/0.9.8l zlib/1.2.3"}
|
||||
</code></pre>
|
||||
|
||||
<h3 id="-curl-http-httparrot-org-get">$ curl http://httparrot.herokuapp.com/get</h3>
|
||||
<h3 id="-curl-http-httparrot-org-get">$ curl https://httparrot.onrender.com/get</h3>
|
||||
|
||||
<pre><code>{
|
||||
"args": {},
|
||||
"headers": {
|
||||
"Accept": "*/*",
|
||||
"Connection": "close",
|
||||
"Content-Length": "",
|
||||
"Content-Type": "",
|
||||
"Host": "httparrot.herokuapp.com",
|
||||
"User-Agent": "curl/7.19.7 (universal-apple-darwin10.0) libcurl/7.19.7 OpenSSL/0.9.8l zlib/1.2.3"
|
||||
},
|
||||
"origin": "24.127.96.129",
|
||||
"url": "http://httparrot.herokuapp.com/get"
|
||||
}
|
||||
<pre><code>
|
||||
{
|
||||
"args": {},
|
||||
"headers": {
|
||||
"accept": "*/*",
|
||||
"accept-encoding": "gzip",
|
||||
"cdn-loop": "cloudflare; subreqs=1",
|
||||
"cf-connecting-ip": "118.148.71.18",
|
||||
"cf-ew-via": "15",
|
||||
"cf-ipcountry": "NZ",
|
||||
"cf-ray": "899c4ca20494508c-AKL",
|
||||
"cf-visitor": "{\"scheme\":\"https\"}",
|
||||
"cf-worker": "onrender.com",
|
||||
"host": "httparrot.onrender.com",
|
||||
"render-proxy-ttl": "4",
|
||||
"rndr-id": "1cf65e46-55f1-429d",
|
||||
"true-client-ip": "118.148.71.18",
|
||||
"user-agent": "curl/7.81.0",
|
||||
"x-forwarded-for": "118.148.71.18, 10.213.36.192, 10.214.43.80",
|
||||
"x-forwarded-proto": "https",
|
||||
"x-request-start": "1719395492280333"
|
||||
},
|
||||
"url": "http://httparrot.onrender.com/get",
|
||||
"origin": ""
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
<h3 id="-curl-I-http-httparrot-org-status-418">$ curl -I http://httparrot.herokuapp.com/status/201</h3>
|
||||
<h3 id="-curl-I-http-httparrot-org-status-418">$ curl -I https://httparrot.onrender.com/status/201</h3>
|
||||
|
||||
<pre><code>HTTP/1.1 201
|
||||
Server: Cowboy
|
||||
|
|
|
@ -1,16 +1,27 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIICeDCCAeGgAwIBAgIJAOvpU0y2e5J4MA0GCSqGSIb3DQEBBQUAMFUxCzAJBgNV
|
||||
BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczETMBEGA1UECgwKTmluZSBOaW5lczEPMA0G
|
||||
A1UECwwGQ293Ym95MRAwDgYDVQQDDAdST09UIENBMB4XDTEzMDIyODA1MTAwMVoX
|
||||
DTMzMDIyMzA1MTAwMVowVTELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVRleGFzMRMw
|
||||
EQYDVQQKDApOaW5lIE5pbmVzMQ8wDQYDVQQLDAZDb3dib3kxEDAOBgNVBAMMB1JP
|
||||
T1QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMzmY7Us06yjyUbpqwPx
|
||||
Iv+xh/g3V7we07ClC9GEYnvr3OQvdA1jFEHccMBUUjRoQ8DPd6uSyK5UkixABs08
|
||||
Tt5B3VsnGKr0DIN+IO4SN2PkmBqIU/BN3KdcwN65YNr3iM0KsKWeFtAZdYx4CakX
|
||||
7REbO0wjK20AH3xSBn3uFGiBAgMBAAGjUDBOMB0GA1UdDgQWBBRKfZ8KF2jlLBDm
|
||||
NL6IuEuGY0pdbzAfBgNVHSMEGDAWgBRKfZ8KF2jlLBDmNL6IuEuGY0pdbzAMBgNV
|
||||
HRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAG1I0kBxXiLkM1b7rl2zPLizREYg
|
||||
1m+ajb6rWzPOBg6TXjv58Be+H4tqoHIL/M/crixew5emftBkuAGjiKMhbIokjvan
|
||||
aPTCV8U6HHvNvz9c68HpESWbd+56cHqfsS5XCKp1OpW5tbL2UQYpFKMP4qmbv3Ea
|
||||
pBfPPmSFMBb1i2AI
|
||||
MIIEqjCCAxKgAwIBAgIRANXKM01Lqak+6N93VnHgkl4wDQYJKoZIhvcNAQELBQAw
|
||||
bTEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMSEwHwYDVQQLDBhlZHVh
|
||||
cmRvQHBvcC1vcyAoRWR1YXJkbykxKDAmBgNVBAMMH21rY2VydCBlZHVhcmRvQHBv
|
||||
cC1vcyAoRWR1YXJkbykwHhcNMjQwNjIzMDU1MzA0WhcNMzQwNjIzMDU1MzA0WjBt
|
||||
MR4wHAYDVQQKExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExITAfBgNVBAsMGGVkdWFy
|
||||
ZG9AcG9wLW9zIChFZHVhcmRvKTEoMCYGA1UEAwwfbWtjZXJ0IGVkdWFyZG9AcG9w
|
||||
LW9zIChFZHVhcmRvKTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAK6p
|
||||
DThGWoUHwCVf8DqHDFthUTvNIKRJzyxArh4GF71dHehiLVBZQ9i/jA1nRASzsVcu
|
||||
UGyZT18N+XvCCeoPevHXOPjUJZtMkhPqlt55N9gzrniEsmRRQOPzIt8+BiFjJ5Jn
|
||||
RzRD9S+9AwNIaZKUjiQ1Oexxgvd7pbWy3S/IzXCyFsKIZqYcvvpBY6FroDSEZbrk
|
||||
xMA4Fhvy2370nTrlKzuoVTGZ8WdHOsh7Ef+mCZp1QwTtCkIPHdCa3OMs5F7u4q8P
|
||||
tB4QgaWnvEmRtDwsst/CCQr4nIrQzjDwCMS41x0DZwMrQ8lzSjnAHxayWoll9aJK
|
||||
38jaDviT9qvnIjjdMHN9jJ7fDBZeonrGqdGSs/754oxpSFAiErpBY6dPGYgzkjQM
|
||||
IxKi4zqYW9ZWPSYacAmRwZsYWp50tvtwxtdY63GslFrnVjtG7e+H1rJJWsQ2Eq5w
|
||||
sQekS/EqOpufBuoildwGMiyW1CEhXezW5lCiA++kyA6DkVA2zQRi0huJ4LPvDQID
|
||||
AQABo0UwQzAOBgNVHQ8BAf8EBAMCAgQwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNV
|
||||
HQ4EFgQUSGXO0OyaSJ4ztTJkQt8atnaqe7MwDQYJKoZIhvcNAQELBQADggGBAA6c
|
||||
pCJO1U2S79McbKZylJ13Nv+qMSWvTF5ax+/tSahAgvauaQiDInLa9wOUHfiTqNwH
|
||||
q42UUexfm04Yre+R9NR9jOVHCFwT9uq3MOPKDuRS3UUUCCUjy0b0CSDc1uCi9BGu
|
||||
jykYViGNCDvTeOI8AZfIEtD77TGJt/8kn7Z6Qe9EFe1N+k8PtbFJgt1/rjIOtFz0
|
||||
638iHBSky+U4ozznxQmwwseR3KSSNS0JWQDxm/gWqy4MP1m0pW5Pd543ms2BPUzO
|
||||
2P1PkEV4jz8J4j2C3EctdoiCudqa8BCFMXIE+t/hKQ+LgbW6phoIN6DLp65Yhs7Z
|
||||
DHPq64f8005EXB8GDHLoP/HL/wnO60e+hjjvsumvCWc7EZeZiHl2QwFMQ6csExeZ
|
||||
9bky+h1WiQeV2poEyJSPOVAXThaxf3GOV+V/zrnY+DHNio/IRa4Z+/1Fwxs26+o7
|
||||
Qnkf9UqSZrKr/B7ilQ/Cb1sv3dLzIPAmfNuDjqPWb4eYT+B26n264znHlhvmWw==
|
||||
-----END CERTIFICATE-----
|
||||
|
|
|
@ -1,17 +1,26 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIICpTCCAg6gAwIBAgIJAOvpU0y2e5J5MA0GCSqGSIb3DQEBBQUAMFUxCzAJBgNV
|
||||
BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczETMBEGA1UECgwKTmluZSBOaW5lczEPMA0G
|
||||
A1UECwwGQ293Ym95MRAwDgYDVQQDDAdST09UIENBMB4XDTEzMDIyODA1MjMzNFoX
|
||||
DTMzMDIyMzA1MjMzNFowVzELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVRleGFzMRMw
|
||||
EQYDVQQKDApOaW5lIE5pbmVzMQ8wDQYDVQQLDAZDb3dib3kxEjAQBgNVBAMMCWxv
|
||||
Y2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAzbW1GjECzHUc/WST
|
||||
qLiAGqjCNccR5saVS+yoz2SPRhpoyf0/qBrX5BY0tzmgozoTiRfE4wCiVD99Cc+D
|
||||
rp/FM49r4EpZdocIovprmOmv/gwkoj95zaA6PKNn1OdmDp2hwJsX2Zm3kpbGUZTx
|
||||
jDkkccmgUb4EjL7qNHq7saQtivUCAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgB
|
||||
hvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYE
|
||||
FB6jTEIWI8T1ckORA4GezbyYxtbvMB8GA1UdIwQYMBaAFEp9nwoXaOUsEOY0voi4
|
||||
S4ZjSl1vMA0GCSqGSIb3DQEBBQUAA4GBACMboVQjrx8u/fk3gl/sR0tbA0Wf/NcS
|
||||
2Dzsy2czndgVUAG4Sqb+hfgn0dqAyUKghRrj3JDcYxYksGPIklDfPzZb7yJ39l16
|
||||
6x5ZiIzhp8CAVdPvRxRznw5rZwaXesryXu1jVSZxTr3MYZdkG6KaAM0t90+YlGLZ
|
||||
UG8fAicx0Bf+
|
||||
MIIEZTCCAs2gAwIBAgIQIJarIG+LC7mjP0IRrFcI0zANBgkqhkiG9w0BAQsFADBt
|
||||
MR4wHAYDVQQKExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExITAfBgNVBAsMGGVkdWFy
|
||||
ZG9AcG9wLW9zIChFZHVhcmRvKTEoMCYGA1UEAwwfbWtjZXJ0IGVkdWFyZG9AcG9w
|
||||
LW9zIChFZHVhcmRvKTAeFw0yNDA2MjMwNTU0MTBaFw0yNjA5MjMwNTU0MTBaMEwx
|
||||
JzAlBgNVBAoTHm1rY2VydCBkZXZlbG9wbWVudCBjZXJ0aWZpY2F0ZTEhMB8GA1UE
|
||||
CwwYZWR1YXJkb0Bwb3Atb3MgKEVkdWFyZG8pMIIBIjANBgkqhkiG9w0BAQEFAAOC
|
||||
AQ8AMIIBCgKCAQEAx8lf20sm9KkWh/u6ehJ4YpDlx7DGaebBok3JR6rdV42c9flu
|
||||
pXdi0Uu7tq4utk4rGu6gotIlPFDeRxokqNIaCUmpIW2msG6KzPBp2Lf+AR0EbdQS
|
||||
EvqiMLx5dU3yEafGKeH1z4qMobhEWIWU9F0V8zuuJvCeHRCdBkse1XQ64X6gyN1m
|
||||
5lYEEIlGfOj7rrAFdCkv63W5dUeph9yoIF//T9yhTx0yNGUeCOuqQEL5HsSdD6HL
|
||||
hqIsjmlI33uHWJd9fr72ZTjmxawRca3tS4ljR6QeZw8zE51lh5P4f1pTGa2vUPxX
|
||||
A11O8jmuXkflgLyDNlm1Pob0tuoNOpa2Zi+mAQIDAQABo4GhMIGeMA4GA1UdDwEB
|
||||
/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAfBgNVHSMEGDAWgBRIZc7Q7JpI
|
||||
njO1MmRC3xq2dqp7szBWBgNVHREETzBNggtleGFtcGxlLmNvbYINKi5leGFtcGxl
|
||||
LmNvbYIMZXhhbXBsZS50ZXN0gglsb2NhbGhvc3SHBH8AAAGHEAAAAAAAAAAAAAAA
|
||||
AAAAAAEwDQYJKoZIhvcNAQELBQADggGBAKuzr0Vb6NZV5XlByLgMb1sddIhl3DWq
|
||||
RGcAf556am51zvZQFz9W/SBm0Ww7+W1fLx7lasyawsxNhfgNHgP05WKZqghodqIw
|
||||
1tQJAu8PRuXClrvADUnvMz4a3ELCkygSZNn1Oo84YXssEBe1vy70ZTGZS8hhq5qJ
|
||||
uKTwN0/UtJXXF0dapd4T+N0kuWuoB1xsf7U9Hdn0Bmw5idWe+U2xvb4/Eo0rPUKa
|
||||
+GJafosfJ17zV5D4oUbuf1uPg8MqQJzEcQDEOcVDgds7tyy3A3igQ+v1WYDkUcUZ
|
||||
IfOoQxMfHF7mGDbAETGnn0pSRztgKdobpg7MItbdiI04XSIwgGZL4puLJZfSkRDC
|
||||
ZLqZk9JJc8DpLRjGmH7lRcKkq8TkbrKGsYOQ3bWV6rLP1xH++rE7Sld7P8bLhapQ
|
||||
hIwcy1rg38v6u2OmApfEbp+VBa62h7RqBDsW0JSNo8Ut1d0VS2HxHMNZ+pr0WVqO
|
||||
nGcNj0IS+dchbyqN7WF4X9h1iqD09qWeaw==
|
||||
-----END CERTIFICATE-----
|
||||
|
|
|
@ -1,15 +1,28 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXQIBAAKBgQDNtbUaMQLMdRz9ZJOouIAaqMI1xxHmxpVL7KjPZI9GGmjJ/T+o
|
||||
GtfkFjS3OaCjOhOJF8TjAKJUP30Jz4Oun8Uzj2vgSll2hwii+muY6a/+DCSiP3nN
|
||||
oDo8o2fU52YOnaHAmxfZmbeSlsZRlPGMOSRxyaBRvgSMvuo0eruxpC2K9QIDAQAB
|
||||
AoGAaD85c/h6bpq7Aj7CBbLaWKhFI3OqwsTITB22vsM7SE+B4zsP02UnG1OVi3UM
|
||||
zytTUxpUkKV1njQ+bYZYOVqGWF4Up8tTqUglHn0FTPok1AIemELWtz3sXvdSHC1T
|
||||
lqvFBAZ9kibn13qGyVOiyCFaMwfOM/05RvV7p3jfUMTWnNECQQDs7yCJZ8Ol8MyH
|
||||
TGZzvkjoN2zg1KwmTbSD1hkP6QAJtPdRuqFbjlEru0/PefgOXsWLRIa3/3v0qw2G
|
||||
xGkV6AXTAkEA3kNbFisqUydjPnZIYv/P6SvPdUimHJEjXbAbfNfzS9dzszrOVJd2
|
||||
XqGH7z5yzjoH3IyaIMW8GnubVzGDSjrHFwJAKSU5vELlygpwKkrNO+pelN0TLlQg
|
||||
dSJnZ8GlZorq88SWcn37iX/EftivenNO7YftvEqxLoDSkOGnnrC7Iw/A+wJBAIEe
|
||||
L/QY72WPJCBNJpAce/PA96vyoE1II3txqwZDjZspdpVQPDz4IFOpEwbxCFC1dYuy
|
||||
Qnd3Z2cbF4r3wIWGz9ECQQCJGNhUNtY+Om1ELdqPcquxE2VRV/pucnvJSTKwyo2C
|
||||
Rvm6H7kFDwPDuN23YnTOlTiho0zzCkclcIukhIVJ+dKz
|
||||
-----END RSA PRIVATE KEY-----
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDHyV/bSyb0qRaH
|
||||
+7p6EnhikOXHsMZp5sGiTclHqt1XjZz1+W6ld2LRS7u2ri62Tisa7qCi0iU8UN5H
|
||||
GiSo0hoJSakhbaawborM8GnYt/4BHQRt1BIS+qIwvHl1TfIRp8Yp4fXPioyhuERY
|
||||
hZT0XRXzO64m8J4dEJ0GSx7VdDrhfqDI3WbmVgQQiUZ86PuusAV0KS/rdbl1R6mH
|
||||
3KggX/9P3KFPHTI0ZR4I66pAQvkexJ0PocuGoiyOaUjfe4dYl31+vvZlOObFrBFx
|
||||
re1LiWNHpB5nDzMTnWWHk/h/WlMZra9Q/FcDXU7yOa5eR+WAvIM2WbU+hvS26g06
|
||||
lrZmL6YBAgMBAAECggEAY2zlJnZdGa84hk4RfITKoornv5xK8hMj1EkP3Xm8E8Fn
|
||||
FsaeePxUEkK1VXGTz6hRLWMKUF1yqHS6Wfo5ukZtLKga4ob2SKGKs/kFRBQ09Yri
|
||||
VGIQ6J8Qrl5tt6Il0QGEzf0k3rddy3GvmbpI6d+Vd+oAfmKK3X4SFzq1SpdAYk1H
|
||||
RcC+VLfu60v7yFMtk0IMKMvtXBNY4TPmvJFKv439mLDyIRA5Dsk8P6TZrf473PVJ
|
||||
JpofVVIKtug8z++CFojhiQYX2bcyIxHWdbUer/snJq4UV+0pOjVYqtB+cVjToBSV
|
||||
BGNcR+qe8Sg0HXVjpSpKUl3d3GOmCTjKeFzHbu4yTQKBgQD498zP1pW4jH1RVxo8
|
||||
RVsZWKmZip7iD9MhrUakMW9G9pUrWzl6DG7Na8pnYi5TsZXXak/f5sWhhCPxkae0
|
||||
0x4Pp7qnSqPvGuTMZQsuG8bvFBWg5XwwrLbx8AzKQ6WggnRumamV5KEwQ8pHMa20
|
||||
b2fZWPEn3KNR5LASzp9QW3cS2wKBgQDNbfYZOmrEAZw9c53VJG9S1JiqClYHg99T
|
||||
oTlklsfdNfot78odTto29LO9Tr997ZX0w93jDrxSdLyyiIdZEDVSSkbS3HSdSjfm
|
||||
nqwlogNXf5TnH88j+EkVvQWs63Q7lyrFNcEftT44ebYXH5ehzPkVbKlocztY0AWw
|
||||
iVgD8AlrUwKBgQCHE8L+fJks0KRpTk3Ap4x+mvkhgfEkC5vsaJusF9oc8UoLhOoR
|
||||
Ss+PCk19e+pQpEf84QRHIWjWceAif3kzBVwI+GKvwzJgVwIN10CSmqV7LzVw3zFb
|
||||
I0n6x9fYoY0qIb1UCHDXD31Yt17284AgJlV8ueHVU8MUenQBMDOFoKphAwKBgGGc
|
||||
/5SLSpIqhbg5iOTvtCoytPwPf0OA6QyPDnt6nivB60gKqgp1HoGAkyvAEIPg8iFl
|
||||
NLkglmHD8KoQ7+dlKUEZ5D9r28mlq5xdB0W2j0nzaKjOV5oq72dx8xFwrEFomj0t
|
||||
RsAvWgpx4xFnxKBwimcgw/rKzodsCVgSWw078O3bAoGBAOyz3sgE9c6mv5jwg2bt
|
||||
59rqGfHZizMRH0gxiC8P1Ui9dlZfnvdeBLUR/FD6XBSb450vRdcgG4AQ+HPECKkb
|
||||
kECHkBb542ymb/GqgutNLPzQ8n0Q1zO92CSX5KKmY2B+lEfer5NSc2c9gY261YMH
|
||||
AApeuDGbws/XXVLWnR1fGbH0
|
||||
-----END PRIVATE KEY-----
|
||||
|
|
8
rel/env.bat.eex
Normal file
8
rel/env.bat.eex
Normal file
|
@ -0,0 +1,8 @@
|
|||
@echo off
|
||||
rem Set the release to load code on demand (interactive) instead of preloading (embedded).
|
||||
rem set RELEASE_MODE=interactive
|
||||
|
||||
rem Set the release to work across nodes.
|
||||
rem RELEASE_DISTRIBUTION must be "sname" (local), "name" (distributed) or "none".
|
||||
rem set RELEASE_DISTRIBUTION=name
|
||||
rem set RELEASE_NODE=<%= @release.name %>
|
20
rel/env.sh.eex
Normal file
20
rel/env.sh.eex
Normal file
|
@ -0,0 +1,20 @@
|
|||
#!/bin/sh
|
||||
|
||||
# # Sets and enables heart (recommended only in daemon mode)
|
||||
# case $RELEASE_COMMAND in
|
||||
# daemon*)
|
||||
# HEART_COMMAND="$RELEASE_ROOT/bin/$RELEASE_NAME $RELEASE_COMMAND"
|
||||
# export HEART_COMMAND
|
||||
# export ELIXIR_ERL_OPTIONS="-heart"
|
||||
# ;;
|
||||
# *)
|
||||
# ;;
|
||||
# esac
|
||||
|
||||
# # Set the release to load code on demand (interactive) instead of preloading (embedded).
|
||||
# export RELEASE_MODE=interactive
|
||||
|
||||
# # Set the release to work across nodes.
|
||||
# # RELEASE_DISTRIBUTION must be "sname" (local), "name" (distributed) or "none".
|
||||
# export RELEASE_DISTRIBUTION=name
|
||||
# export RELEASE_NODE=<%= @release.name %>
|
12
rel/remote.vm.args.eex
Normal file
12
rel/remote.vm.args.eex
Normal file
|
@ -0,0 +1,12 @@
|
|||
## Customize flags given to the VM: https://www.erlang.org/doc/man/erl.html
|
||||
## -mode/-name/-sname/-setcookie are configured via env vars, do not set them here
|
||||
|
||||
## Increase number of concurrent ports/sockets
|
||||
##+Q 65536
|
||||
|
||||
## Tweak GC to run more often
|
||||
##-env ERL_FULLSWEEP_AFTER 10
|
||||
|
||||
## Enable deployment without epmd
|
||||
## (requires changing both vm.args and remote.vm.args)
|
||||
##-start_epmd false -erl_epmd_port 6789 -dist_listen false
|
12
rel/vm.args.eex
Normal file
12
rel/vm.args.eex
Normal file
|
@ -0,0 +1,12 @@
|
|||
## Customize flags given to the VM: https://www.erlang.org/doc/man/erl.html
|
||||
## -mode/-name/-sname/-setcookie are configured via env vars, do not set them here
|
||||
|
||||
## Increase number of concurrent ports/sockets
|
||||
##+Q 65536
|
||||
|
||||
## Tweak GC to run more often
|
||||
##-env ERL_FULLSWEEP_AFTER 10
|
||||
|
||||
## Enable deployment without epmd
|
||||
## (requires changing both vm.args and remote.vm.args)
|
||||
##-start_epmd false -erl_epmd_port 6789false
|
|
@ -4,22 +4,22 @@ defmodule HTTParrot.Base64HandlerTest do
|
|||
import HTTParrot.Base64Handler
|
||||
|
||||
setup do
|
||||
new :cowboy_req
|
||||
on_exit fn -> unload() end
|
||||
new(:cowboy_req)
|
||||
on_exit(fn -> unload() end)
|
||||
:ok
|
||||
end
|
||||
|
||||
test "halts with error" do
|
||||
expect(:cowboy_req, :binding, [{[:value, :req1], {"I=", :req2}}])
|
||||
expect(:cowboy_req, :binding, [{[:value, :req1], "I="}])
|
||||
|
||||
assert malformed_request(:req1, :state) == {true, :req2, :state}
|
||||
assert malformed_request(:req1, :state) == {true, :req1, :state}
|
||||
assert validate(:cowboy_req)
|
||||
end
|
||||
|
||||
test "proceeds with decoded base64 urlsafe" do
|
||||
expect(:cowboy_req, :binding, [{[:value, :req1], {"LytiYXNlNjQrLw", :req2}}])
|
||||
expect(:cowboy_req, :binding, [{[:value, :req1], "LytiYXNlNjQrLw"}])
|
||||
|
||||
assert malformed_request(:req1, :state) == {false, :req2, "/+base64+/"}
|
||||
assert malformed_request(:req1, :state) == {false, :req1, "/+base64+/"}
|
||||
assert validate(:cowboy_req)
|
||||
end
|
||||
|
||||
|
|
|
@ -4,32 +4,33 @@ defmodule HTTParrot.BasicAuthHandlerTest do
|
|||
import HTTParrot.BasicAuthHandler
|
||||
|
||||
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 "is_authorized 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}])
|
||||
expect(:cowboy_req, :parse_header, [{["authorization", :req1], {:basic, :user, :passwd}}])
|
||||
|
||||
assert is_authorized(:req1, :state) == {true, :req4, :user}
|
||||
assert is_authorized(:req1, :state) == {true, :req1, :user}
|
||||
|
||||
assert validate :cowboy_req
|
||||
assert validate JSX
|
||||
assert validate(:cowboy_req)
|
||||
assert validate(JSX)
|
||||
end
|
||||
|
||||
test "is_authorized 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 is_authorized(:req1, :state) == {{false, "Basic realm=\"Fake Realm\""}, :req4, :state}
|
||||
expect(:cowboy_req, :parse_header, [
|
||||
{["authorization", :req1], {:basic, :not_the_user, :passwd}}
|
||||
])
|
||||
|
||||
assert validate :cowboy_req
|
||||
assert validate JSX
|
||||
assert is_authorized(:req1, :state) == {{false, "Basic realm=\"Fake Realm\""}, :req1, :state}
|
||||
|
||||
assert validate(:cowboy_req)
|
||||
assert validate(JSX)
|
||||
end
|
||||
|
||||
test "returns user and if it's authenticated" do
|
||||
|
@ -37,6 +38,6 @@ defmodule HTTParrot.BasicAuthHandlerTest do
|
|||
|
||||
assert get_json(:req1, :user) == {:json, :req1, nil}
|
||||
|
||||
assert validate JSX
|
||||
assert validate(JSX)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,9 +4,9 @@ defmodule HTTParrot.CacheHandlerTest do
|
|||
import HTTParrot.CacheHandler
|
||||
|
||||
setup do
|
||||
new HTTParrot.GeneralRequestInfo
|
||||
new JSX
|
||||
on_exit fn -> unload() end
|
||||
new(HTTParrot.GeneralRequestInfo)
|
||||
new(JSX)
|
||||
on_exit(fn -> unload() end)
|
||||
:ok
|
||||
end
|
||||
|
||||
|
@ -16,7 +16,7 @@ defmodule HTTParrot.CacheHandlerTest do
|
|||
|
||||
assert get_json(:req1, :state) == {:json, :req2, :state}
|
||||
|
||||
assert validate HTTParrot.GeneralRequestInfo
|
||||
assert validate JSX
|
||||
assert validate(HTTParrot.GeneralRequestInfo)
|
||||
assert validate(JSX)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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)
|
||||
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 JSX
|
||||
assert validate(:cowboy_req)
|
||||
assert validate(JSX)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,9 +4,9 @@ defmodule HTTParrot.DeflateHandlerTest do
|
|||
import HTTParrot.DeflateHandler
|
||||
|
||||
setup do
|
||||
new HTTParrot.GeneralRequestInfo
|
||||
new JSX
|
||||
on_exit fn -> unload() end
|
||||
new(HTTParrot.GeneralRequestInfo)
|
||||
new(JSX)
|
||||
on_exit(fn -> unload() end)
|
||||
:ok
|
||||
end
|
||||
|
||||
|
@ -16,15 +16,15 @@ defmodule HTTParrot.DeflateHandlerTest do
|
|||
expect(JSX, :prettify!, [{[:json], "json"}])
|
||||
expect(:cowboy_req, :set_resp_header, 3, :req3)
|
||||
|
||||
opened_zlib = :zlib.open
|
||||
opened_zlib = :zlib.open()
|
||||
:zlib.deflateInit(opened_zlib)
|
||||
body = :zlib.deflate(opened_zlib, "json", :finish)
|
||||
:zlib.deflateEnd(opened_zlib)
|
||||
|
||||
assert get_json(:req1, :state) == {body, :req3, :state}
|
||||
|
||||
assert validate HTTParrot.GeneralRequestInfo
|
||||
assert validate JSX
|
||||
assert validate :cowboy_req
|
||||
assert validate(HTTParrot.GeneralRequestInfo)
|
||||
assert validate(JSX)
|
||||
assert validate(:cowboy_req)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -4,18 +4,24 @@ defmodule HTTParrot.DeleteCookiesHandlerTest do
|
|||
import HTTParrot.DeleteCookiesHandler
|
||||
|
||||
setup do
|
||||
new :cowboy_req
|
||||
on_exit fn -> unload() end
|
||||
new(:cowboy_req)
|
||||
on_exit(fn -> unload() end)
|
||||
:ok
|
||||
end
|
||||
|
||||
test "delete cookies and redirect to /cookies " do
|
||||
expect(:cowboy_req, :set_resp_cookie, [{[:k1, :v1, [path: "/", max_age: 0], :req1], :req2},
|
||||
{[:k2, :v2, [path: "/", max_age: 0], :req2], :req3}])
|
||||
expect(:cowboy_req, :reply, [{[302, [{"location", "/cookies"}], "Redirecting...", :req3], {:ok, :req4}}])
|
||||
expect(:cowboy_req, :set_resp_cookie, [
|
||||
{["k1", "v1", :req1, %{path: "/", max_age: 0}], :req2},
|
||||
{["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"}]) ==
|
||||
{:stop, :req4, [{"k1", "v1"}, {"k2", "v2"}]}
|
||||
|
||||
assert validate(:cowboy_req)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,10 +4,10 @@ defmodule HTTParrot.DeleteHandlerTest do
|
|||
import HTTParrot.DeleteHandler
|
||||
|
||||
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
|
||||
|
||||
|
@ -18,8 +18,8 @@ defmodule HTTParrot.DeleteHandlerTest do
|
|||
|
||||
assert delete_resource(:req1, :state) == {true, :req3, :state}
|
||||
|
||||
assert validate :cowboy_req
|
||||
assert validate HTTParrot.GeneralRequestInfo
|
||||
assert validate JSX
|
||||
assert validate(:cowboy_req)
|
||||
assert validate(HTTParrot.GeneralRequestInfo)
|
||||
assert validate(JSX)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -4,9 +4,9 @@ defmodule HTTParrot.GetHandlerTest do
|
|||
import HTTParrot.GetHandler
|
||||
|
||||
setup do
|
||||
new HTTParrot.GeneralRequestInfo
|
||||
new JSX
|
||||
on_exit fn -> unload() end
|
||||
new(HTTParrot.GeneralRequestInfo)
|
||||
new(JSX)
|
||||
on_exit(fn -> unload() end)
|
||||
:ok
|
||||
end
|
||||
|
||||
|
@ -16,7 +16,7 @@ defmodule HTTParrot.GetHandlerTest do
|
|||
|
||||
assert get_json(:req1, :state) == {:json, :req2, :state}
|
||||
|
||||
assert validate HTTParrot.GeneralRequestInfo
|
||||
assert validate JSX
|
||||
assert validate(HTTParrot.GeneralRequestInfo)
|
||||
assert validate(JSX)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,9 +4,9 @@ defmodule HTTParrot.GzipHandlerTest do
|
|||
import HTTParrot.GzipHandler
|
||||
|
||||
setup do
|
||||
new HTTParrot.GeneralRequestInfo
|
||||
new JSX
|
||||
on_exit fn -> unload() end
|
||||
new(HTTParrot.GeneralRequestInfo)
|
||||
new(JSX)
|
||||
on_exit(fn -> unload() end)
|
||||
:ok
|
||||
end
|
||||
|
||||
|
@ -20,8 +20,8 @@ defmodule HTTParrot.GzipHandlerTest do
|
|||
|
||||
assert get_json(:req1, :state) == {body, :req3, :state}
|
||||
|
||||
assert validate HTTParrot.GeneralRequestInfo
|
||||
assert validate JSX
|
||||
assert validate :cowboy_req
|
||||
assert validate(HTTParrot.GeneralRequestInfo)
|
||||
assert validate(JSX)
|
||||
assert validate(:cowboy_req)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}}])
|
||||
test "resource_exists returns false if user and passwd doesn't match" do
|
||||
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
|
||||
|
|
|
@ -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" => ~c"14"}, "{\n \"a\": \"b\"\n}", :req1], :req2}
|
||||
])
|
||||
|
||||
assert prettify_json(:status, %{"content-length" => ~c"12"}, "{\"a\":\"b\"}", :req1) == :req2
|
||||
assert validate(:cowboy_req)
|
||||
end
|
||||
|
||||
test "'prettify_json' does nothing if body is not a JSON" do
|
||||
|
|
|
@ -4,30 +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, :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, 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, :req1, :state}
|
||||
|
||||
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, :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
|
||||
|
|
|
@ -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} ->
|
||||
test "allowed_methods return verb related to #{path}" do
|
||||
expect(:cowboy_req, :path, 1, {unquote(path), :req2})
|
||||
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))
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
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
|
||||
|
|
|
@ -4,49 +4,48 @@ 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
|
||||
|
||||
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 "moved_permanently returns 'redirect/n-1' if n > 1" do
|
||||
expect(:cowboy_req, :host_url, 1, {"host", :req2})
|
||||
expect(:cowboy_req, :uri, 2, "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
|
||||
|
||||
test "moved_permanently returns '/get' if n = 1" do
|
||||
expect(:cowboy_req, :host_url, 1, {"host", :req2})
|
||||
expect(:cowboy_req, :uri, 2, "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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -4,33 +4,33 @@ defmodule HTTParrot.RelativeRedirectHandlerTest do
|
|||
import HTTParrot.RelativeRedirectHandler
|
||||
|
||||
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 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 "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
|
||||
assert moved_permanently(:req1, 1) == {{true, "/get"}, :req1, nil}
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
defmodule HTTParrot.RequestStoreTest do
|
||||
alias HTTParrot.RequestStore
|
||||
use ExUnit.Case
|
||||
|
||||
test "save, retrieve, clear" do
|
||||
request = %{req: 1}
|
||||
RequestStore.clear(:test)
|
||||
RequestStore.store(:test, request)
|
||||
assert RequestStore.retrieve(:test) == [request]
|
||||
RequestStore.clear(:test)
|
||||
RequestStore.clear(:test)
|
||||
assert RequestStore.retrieve(:test) == []
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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, [])
|
||||
|
||||
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 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
|
||||
|
||||
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
|
||||
|
|
|
@ -5,7 +5,7 @@ defmodule HTTParrot.RetrieveRequestHandlerTests do
|
|||
|
||||
setup do
|
||||
HTTParrot.RequestStore.clear(:test)
|
||||
on_exit fn -> unload() end
|
||||
on_exit(fn -> unload() end)
|
||||
:ok
|
||||
end
|
||||
|
||||
|
|
|
@ -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, [])
|
||||
|
||||
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
|
||||
|
||||
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"}])
|
||||
|
||||
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
|
||||
|
||||
test "malformed_request returns false if query string values are sent" do
|
||||
expect(:cowboy_req, :qs_vals, 1, {[{"name", "value"}], :req2})
|
||||
expect(:cowboy_req, :binding, [{[:name, :req2, nil], {nil, :req3}}])
|
||||
expect(:cowboy_req, :parse_qs, 1, [{"name", "value"}])
|
||||
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
|
||||
|
||||
test "malformed_request returns true if query string values are not sent" do
|
||||
expect(:cowboy_req, :qs_vals, 1, {[], :req2})
|
||||
expect(:cowboy_req, :binding, [{[:name, :req2, nil], {nil, :req3}}])
|
||||
expect(:cowboy_req, :parse_qs, 1, [])
|
||||
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
|
||||
|
||||
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, :req1, %{path: "/"}], :req2},
|
||||
{[: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) == {:stop, :req4, [k1: :v1, k2: :v2]}
|
||||
|
||||
assert validate(:cowboy_req)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,16 +4,16 @@ defmodule HTTParrot.StatusCodeHandlerTest do
|
|||
import HTTParrot.StatusCodeHandler
|
||||
|
||||
setup do
|
||||
new :cowboy_req
|
||||
on_exit fn -> unload() end
|
||||
new(:cowboy_req)
|
||||
on_exit(fn -> unload() end)
|
||||
:ok
|
||||
end
|
||||
|
||||
test "reply with 'code' as status code" do
|
||||
code = 123
|
||||
expect(:cowboy_req, :binding, [{[:code, :req1], {code, :req2}}])
|
||||
expect(:cowboy_req, :reply, [{[code, [], "", :req2], {:ok, :req3}}])
|
||||
assert get_json(:req1, :state) == {:halt, :req3, :state}
|
||||
assert validate :cowboy_req
|
||||
expect(:cowboy_req, :binding, [{[:code, :req1], code}])
|
||||
expect(:cowboy_req, :reply, [{[code, %{}, "", :req1], :req2}])
|
||||
assert get_json(:req1, :state) == {:stop, :req2, :state}
|
||||
assert validate(:cowboy_req)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,22 +5,22 @@ defmodule HTTParrot.StoreRequestHandlerTests do
|
|||
|
||||
setup do
|
||||
HTTParrot.RequestStore.clear(:test)
|
||||
on_exit fn -> unload() end
|
||||
on_exit(fn -> unload() end)
|
||||
:ok
|
||||
end
|
||||
|
||||
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})
|
||||
assert get(:req1, :state) == {'{"saved": "true"}', :req1, :state}
|
||||
assert get(:req1, :state) == {~c'{"saved": "true"}', :req1, :state}
|
||||
assert HTTParrot.RequestStore.retrieve(:test) == [:info]
|
||||
end
|
||||
|
||||
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})
|
||||
assert get(:req1, :state) == {'{"saved": "true"}', :req1, :state}
|
||||
assert get(:req2, :state) == {'{"saved": "true"}', :req1, :state}
|
||||
assert get(:req1, :state) == {~c'{"saved": "true"}', :req1, :state}
|
||||
assert get(:req2, :state) == {~c'{"saved": "true"}', :req1, :state}
|
||||
assert HTTParrot.RequestStore.retrieve(:test) == [:info, :info]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,111 +4,110 @@ 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, :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
|
||||
{"seed", :req2, "1234"} -> {"1234", :req3}
|
||||
{"chunk_size", :req3, "1024"} -> {"1024", :req4}
|
||||
{:seed, :req1, "1234"} -> %{seed: "1234"}
|
||||
{:chunk_size, :req1, "1024"} -> %{chunk_size: "1024"}
|
||||
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
|
||||
|
||||
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
|
||||
{"seed", :req2, "1234"} -> {"1234", :req3}
|
||||
{"chunk_size", :req3, "1024"} -> {"1024", :req4}
|
||||
{:seed, :req1, "1234"} -> %{seed: "1234"}
|
||||
{:chunk_size, :req1, "1024"} -> %{chunk_size: "1024"}
|
||||
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
|
||||
|
||||
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
|
||||
{"seed", :req2, "1234"} -> {"a2B=", :req3}
|
||||
{"chunk_size", :req3, "1024"} -> {"1024", :req4}
|
||||
{:seed, :req1, "1234"} -> %{seed: "a2B="}
|
||||
{:chunk_size, :req1, "1024"} -> %{chunk_size: "1024"}
|
||||
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
|
||||
|
||||
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
|
||||
{"seed", :req2, "1234"} -> {"7", :req3}
|
||||
{"chunk_size", :req3, "1024"} -> {"1024", :req4}
|
||||
{:seed, :req1, "1234"} -> %{seed: "7"}
|
||||
{:chunk_size, :req1, "1024"} -> %{chunk_size: "1024"}
|
||||
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
|
||||
|
||||
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
|
||||
{"seed", :req2, "1234"} -> {"1234", :req3}
|
||||
{"chunk_size", :req3, "1024"} -> {"a2B=", :req4}
|
||||
{:seed, :req1, "1234"} -> %{seed: "1234"}
|
||||
{:chunk_size, :req1, "1024"} -> %{chunk_size: "a2B="}
|
||||
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
|
||||
|
||||
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
|
||||
{"seed", :req2, "1234"} -> {"1234", :req3}
|
||||
{"chunk_size", :req3, "1024"} -> {"13", :req4}
|
||||
{:seed, :req1, "1234"} -> %{seed: "1234"}
|
||||
{:chunk_size, :req1, "1024"} -> %{chunk_size: "13"}
|
||||
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
|
||||
|
||||
test "response must stream chunks" do
|
||||
assert {{:chunked, func}, :req1, nil} = get_bytes(:req1, {9, 3, 4})
|
||||
assert is_function(func)
|
||||
expect(:cowboy_req, :stream_reply, 3, :req2)
|
||||
expect(:cowboy_req, :stream_body, 3, :ok)
|
||||
|
||||
send_func = fn(body) -> send(self(), {:chunk, body}) end
|
||||
func.(send_func)
|
||||
assert {:stop, :req2, nil} = get_bytes(:req1, {9, 3, 4})
|
||||
|
||||
assert_receive {:chunk, chunk1}
|
||||
assert_receive {:chunk, chunk2}
|
||||
assert_receive {:chunk, chunk3}
|
||||
chunk1 = :meck.capture(1, :cowboy_req, :stream_body, :_, 1)
|
||||
chunk2 = :meck.capture(2, :cowboy_req, :stream_body, :_, 1)
|
||||
chunk3 = :meck.capture(3, :cowboy_req, :stream_body, :_, 1)
|
||||
|
||||
assert String.length(chunk1) == 4
|
||||
assert String.length(chunk2) == 4
|
||||
|
|
|
@ -4,60 +4,54 @@ 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(:cowboy_req, :stream_reply, 3, :req2)
|
||||
expect(:cowboy_req, :stream_body, 3, :req2)
|
||||
expect(JSX, :encode!, [{[[{:id, 0}, :info]], :json1}, {[[{:id, 1}, :info]], :json2}])
|
||||
|
||||
assert {{:chunked, func}, :req2, nil} = get_json(:req1, 2)
|
||||
assert is_function(func)
|
||||
assert {:stop, :req2, nil} = get_json(:req1, 2)
|
||||
|
||||
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
|
||||
|
|
|
@ -1 +1 @@
|
|||
ExUnit.start
|
||||
ExUnit.start()
|
||||
|
|
|
@ -4,19 +4,19 @@ defmodule HTTParrot.UserAgentHandlerTest do
|
|||
import HTTParrot.UserAgentHandler
|
||||
|
||||
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 user agent" do
|
||||
expect(:cowboy_req, :header, [{["user-agent", :req1, "null"], {:user_agent, :req2}}])
|
||||
expect(:cowboy_req, :header, [{["user-agent", :req1, "null"], :user_agent}])
|
||||
expect(JSX, :encode!, [{[[{"user-agent", :user_agent}]], :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
|
||||
|
|
Loading…
Add table
Reference in a new issue