diff --git a/.github/workflows/erlang.yml b/.github/workflows/erlang.yml
index a88cf72..dda6d9d 100644
--- a/.github/workflows/erlang.yml
+++ b/.github/workflows/erlang.yml
@@ -8,19 +8,19 @@ on:
jobs:
tests:
+ name: OTP ${{ matrix.otp }}
runs-on: ubuntu-latest
- name: OTP ${{ matrix.otp }}
+
+ container:
+ image: erlang:${{ matrix.otp }}
+
strategy:
matrix:
- otp: [20.3, 21.3, 22.2]
+ otp: ['20.3', '21.3', '22.3', '23.3', '24.0-rc2']
steps:
- - uses: actions/checkout@v2
-
- - uses: gleam-lang/setup-erlang@v1.0.0
- with:
- otp-version: ${{ matrix.otp }}
+ - uses: actions/checkout@v2.0.0
- name: Run tests
run: rebar3 do eunit, ct, dialyzer
diff --git a/README.md b/README.md
index bc663f9..86ec691 100644
--- a/README.md
+++ b/README.md
@@ -2,9 +2,9 @@
# Bookish spork #
-Copyright (c) 2018-2020 Alexey Nikitin
+Copyright (c) 2018-2021 Alexey Nikitin
-__Version:__ 0.3.6
+__Version:__ 0.4.0
__Authors:__ Alexey Nikitin ([`tank@bohr.su`](mailto:tank@bohr.su)) (_web site:_ [`https://twitter.com/tank_bohr`](https://twitter.com/tank_bohr)).
@@ -52,7 +52,7 @@ First step: add to your rebar config
{profiles, [
{test, [
{deps, [
- {bookish_spork, "0.3.6"}
+ {bookish_spork, "0.4.0"}
]}
]}
]}.
@@ -111,13 +111,15 @@ It returns you an opaque structure of the request. You can inspect it with
#### Bypass comparision ####
-An elixir library [bypass](https://github.com/PSPDFKit-labs/bypass) does pretty much the same. And illustrates the same approach. It starts a cowboy web-server to replace a real service for test
+An elixir library [bypass](https://github.com/PSPDFKit-labs/bypass) does pretty much the same. And illustrates the same approach. It starts a cowboy web-server to replace a real service for test. It's a beautiful library with great API, documentation, and very concise source code. If you are an elixir developer, most likely, it will be a good fit for you.
-But bookish_spork has some advantages:
+But nevertheless bookish_spork has some advantages:
-* Bypass depends on `cowboy` and `plug`. Bookish spork has zero dependencies
-* Bookish spork works seamlessly with both erlang and elixir. Bypass is supposed to be an elixir only library
-* Bookish spork much simpler (I believe)
+* Bypass depends on `cowboy` and `plug`. Bookish spork has zero dependencies.
+* Bookish spork works seamlessly with both erlang and elixir. Bypass is supposed to be an elixir only library.
+* Bookish spork much simpler (I believe)
+ (not any more).
+* Bookish spork allows you to inspect the request very deeply and accurate. For example take a look at [`bookish_spork_request:raw_headers/1`](http://github.com/tank-bohr/bookish_spork/blob/master/doc/bookish_spork_request.md#raw_headers-1) and [`bookish_spork_request:ssl_info/1`](http://github.com/tank-bohr/bookish_spork/blob/master/doc/bookish_spork_request.md#ssl_info-1) and [`bookish_spork_request:tls_ext/1`](http://github.com/tank-bohr/bookish_spork/blob/master/doc/bookish_spork_request.md#tls_ext-1). It can be useful for HTTP clients testing.
#### Elli comparision ####
@@ -227,9 +229,9 @@ defmodule ChuckNorrisApiTest do
use ExUnit.Case
doctest ChuckNorrisApi
- setup_all do
- {:ok, _} = :bookish_spork.start_server
- {:ok, %{}}
+ setup do
+ {:ok, _} = :bookish_spork.start_server()
+ on_exit(fn -> :bookish_spork.stop_server() end)
end
test "retrieves a random joke" do
@@ -238,8 +240,8 @@ defmodule ChuckNorrisApiTest do
}"])
assert ChuckNorrisApi.random == "Chuck norris tried to crank that soulja boy but it wouldn't crank up"
- {:ok, request} = :bookish_spork.capture_request
- assert request.uri == '/jokes/random'
+ {:ok, request} = :bookish_spork.capture_request()
+ assert request.uri === "/jokes/random"
end
end
diff --git a/doc/README.md b/doc/README.md
index 4a28e56..66b7966 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -2,9 +2,9 @@
# Bookish spork #
-Copyright (c) 2018-2020 Alexey Nikitin
+Copyright (c) 2018-2021 Alexey Nikitin
-__Version:__ 0.3.6
+__Version:__ 0.4.0
__Authors:__ Alexey Nikitin ([`tank@bohr.su`](mailto:tank@bohr.su)) (_web site:_ [`https://twitter.com/tank_bohr`](https://twitter.com/tank_bohr)).
@@ -52,7 +52,7 @@ First step: add to your rebar config
{profiles, [
{test, [
{deps, [
- {bookish_spork, "0.3.6"}
+ {bookish_spork, "0.4.0"}
]}
]}
]}.
@@ -111,13 +111,15 @@ It returns you an opaque structure of the request. You can inspect it with
#### Bypass comparision ####
-An elixir library [bypass](https://github.com/PSPDFKit-labs/bypass) does pretty much the same. And illustrates the same approach. It starts a cowboy web-server to replace a real service for test
+An elixir library [bypass](https://github.com/PSPDFKit-labs/bypass) does pretty much the same. And illustrates the same approach. It starts a cowboy web-server to replace a real service for test. It's a beautiful library with great API, documentation, and very concise source code. If you are an elixir developer, most likely, it will be a good fit for you.
-But bookish_spork has some advantages:
+But nevertheless bookish_spork has some advantages:
-* Bypass depends on `cowboy` and `plug`. Bookish spork has zero dependencies
-* Bookish spork works seamlessly with both erlang and elixir. Bypass is supposed to be an elixir only library
-* Bookish spork much simpler (I believe)
+* Bypass depends on `cowboy` and `plug`. Bookish spork has zero dependencies.
+* Bookish spork works seamlessly with both erlang and elixir. Bypass is supposed to be an elixir only library.
+* Bookish spork much simpler (I believe)
+ (not any more).
+* Bookish spork allows you to inspect the request very deeply and accurate. For example take a look at [`bookish_spork_request:raw_headers/1`](bookish_spork_request.md#raw_headers-1) and [`bookish_spork_request:ssl_info/1`](bookish_spork_request.md#ssl_info-1) and [`bookish_spork_request:tls_ext/1`](bookish_spork_request.md#tls_ext-1). It can be useful for HTTP clients testing.
#### Elli comparision ####
@@ -227,9 +229,9 @@ defmodule ChuckNorrisApiTest do
use ExUnit.Case
doctest ChuckNorrisApi
- setup_all do
- {:ok, _} = :bookish_spork.start_server
- {:ok, %{}}
+ setup do
+ {:ok, _} = :bookish_spork.start_server()
+ on_exit(fn -> :bookish_spork.stop_server() end)
end
test "retrieves a random joke" do
@@ -238,8 +240,8 @@ defmodule ChuckNorrisApiTest do
}"])
assert ChuckNorrisApi.random == "Chuck norris tried to crank that soulja boy but it wouldn't crank up"
- {:ok, request} = :bookish_spork.capture_request
- assert request.uri == '/jokes/random'
+ {:ok, request} = :bookish_spork.capture_request()
+ assert request.uri === "/jokes/random"
end
end
diff --git a/doc/bookish_spork_request.md b/doc/bookish_spork_request.md
index cc809b3..21a7928 100644
--- a/doc/bookish_spork_request.md
+++ b/doc/bookish_spork_request.md
@@ -22,7 +22,7 @@ __abstract datatype__: `t()`
## Function Index ##
-
+
@@ -65,11 +65,11 @@ from_transport(Transport::bookish_sp
### header/2 ###
-header(Request::t(), HeaderName::string()) -> string() | nil
+header(Request::t(), HeaderName::string() | binary()) -> binary() | nil
-Returns a particular header from request. Header name is lowerced
+Returns a particular header from request.
@@ -80,7 +80,7 @@ headers(Request::t()) -> map()
-http headers map. Header names are normalized and lowercased
+HTTP headers map. Header names are normalized and lowercased
@@ -102,7 +102,18 @@ method(Request::t()) -> atom()
-http verb: 'GET', 'POST','PUT', 'DELETE', 'OPTIONS', ...
+http verb in lower case: get, post, put, delete, options, ...
+
+
+
+### raw_headers/1 ###
+
+
+raw_headers(Request::t()) -> proplists:proplist()
+
+
+
+HTTP raw headers. Headers order and case are preserved
diff --git a/doc/overview.edoc b/doc/overview.edoc
index b0ad118..e93570e 100644
--- a/doc/overview.edoc
+++ b/doc/overview.edoc
@@ -112,17 +112,19 @@ It returns you an opaque structure of the request. You can inspect it with
=== Bypass comparision ===
-An elixir library bypass does pretty much the same. And illustrates the same approach. It starts a cowboy web-server to replace a real service for test
+An elixir library bypass does pretty much the same. And illustrates the same approach. It starts a cowboy web-server to replace a real service for test. It's a beautiful library with great API, documentation, and very concise source code. If you are an elixir developer, most likely, it will be a good fit for you.
-But bookish_spork has some advantages:
+But nevertheless bookish_spork has some advantages:
- - Bypass depends on `cowboy' and `plug'. Bookish spork has zero dependencies
+ - Bypass depends on `cowboy' and `plug'. Bookish spork has zero dependencies.
- - Bookish spork works seamlessly with both erlang and elixir. Bypass is supposed to be an elixir only library
+ - Bookish spork works seamlessly with both erlang and elixir. Bypass is supposed to be an elixir only library.
- - Bookish spork much simpler (I believe)
+ Bookish spork much simpler (I believe) (not any more).
+
+ - Bookish spork allows you to inspect the request very deeply and accurate. For example take a look at {@link bookish_spork_request:raw_headers/1} and {@link bookish_spork_request:ssl_info/1} and {@link bookish_spork_request:tls_ext/1}. It can be useful for HTTP clients testing.
@@ -221,9 +223,9 @@ defmodule ChuckNorrisApiTest do
use ExUnit.Case
doctest ChuckNorrisApi
- setup_all do
- {:ok, _} = :bookish_spork.start_server
- {:ok, %{}}
+ setup do
+ {:ok, _} = :bookish_spork.start_server()
+ on_exit(fn -> :bookish_spork.stop_server() end)
end
test "retrieves a random joke" do
@@ -232,8 +234,8 @@ defmodule ChuckNorrisApiTest do
}"])
assert ChuckNorrisApi.random == "Chuck norris tried to crank that soulja boy but it wouldn't crank up"
- {:ok, request} = :bookish_spork.capture_request
- assert request.uri == '/jokes/random'
+ {:ok, request} = :bookish_spork.capture_request()
+ assert request.uri === "/jokes/random"
end
end
diff --git a/elvis.config b/elvis.config
index 7cb1aff..5c46bd5 100644
--- a/elvis.config
+++ b/elvis.config
@@ -9,6 +9,12 @@
{elvis_style, function_naming_convention, #{
ignore => [bookish_spork_request],
regex => "^([a-z][a-z0-9]*_?)*$"
+ }},
+ {elvis_style, state_record_and_type, #{
+ ignore => [
+ bookish_spork_acceptor,
+ bookish_spork_blocking_queue
+ ]
}}
],
ruleset => erl_files
diff --git a/rebar.config b/rebar.config
index 7f1f30a..a4f1b28 100644
--- a/rebar.config
+++ b/rebar.config
@@ -10,7 +10,7 @@
{profiles, [
{test, [
{deps, [
- {gun, "1.3.1"}
+ {gun, "1.3.3"}
]},
{plugins, [
@@ -33,7 +33,7 @@
]},
{elvis, [
{plugins, [
- {rebar3_lint, "0.1.11"}
+ {rebar3_lint, "0.4.0"}
]}
]}
]}.
diff --git a/src/bookish_spork_handler.erl b/src/bookish_spork_handler.erl
index 069f577..9d3ff1a 100644
--- a/src/bookish_spork_handler.erl
+++ b/src/bookish_spork_handler.erl
@@ -85,7 +85,8 @@ receive_request(#state{transport = Transport, request = RequestIn} = State) ->
{ok, {http_request, Method, {abs_path, Uri}, Version}} ->
RequestOut = bookish_spork_request:request_line(RequestIn, Method, Uri, Version),
?FUNCTION_NAME(State#state{request = RequestOut});
- {ok, {http_header, _, Header, _, Value}} ->
+ {ok, {http_header, _, NormalizedHeader, PreserveCaseHeader, Value}} ->
+ Header = choose_header(NormalizedHeader, PreserveCaseHeader),
RequestOut = bookish_spork_request:add_header(RequestIn, Header, Value),
?FUNCTION_NAME(State#state{request = RequestOut});
{ok, http_eoh} ->
@@ -136,6 +137,11 @@ complete_connection(State = #state{transport = Transport, request = Request}) ->
{halt, normal}
end.
+choose_header(NormalizedHeader, undefined) ->
+ NormalizedHeader;
+choose_header(_NormalizedHeader, PreserveCaseHeader) ->
+ PreserveCaseHeader.
+
reduce_while(State, []) ->
{noreply, State};
reduce_while(State, [Fun|Rest]) ->
diff --git a/src/bookish_spork_request.erl b/src/bookish_spork_request.erl
index a310a92..5cc5dd0 100644
--- a/src/bookish_spork_request.erl
+++ b/src/bookish_spork_request.erl
@@ -20,6 +20,7 @@
version/1,
header/2,
headers/1,
+ raw_headers/1,
body/1,
body/2,
socket/1,
@@ -41,6 +42,7 @@
method := nil | atom(),
uri := nil | binary(),
version := nil | http_version(),
+ raw_headers := proplists:proplist(),
headers := map(),
body := nil | binary(),
ssl_info := nil | proplists:proplist(),
@@ -72,6 +74,7 @@ new() ->
method => nil,
uri => nil,
version => nil,
+ raw_headers => [],
headers => #{},
body => nil,
ssl_info => nil,
@@ -79,7 +82,7 @@ new() ->
transport => nil
}.
--spec new(From :: list() | map() | ssl:sslsocket()) -> t().
+-spec new(From :: list() | map()) -> t().
%% @private
new(List) when is_list(List) ->
new(maps:from_list(List));
@@ -106,17 +109,23 @@ from_transport(Transport) ->
request_line(Request, Method, Uri, Version) ->
maps:merge(Request, #{
uri => list_to_binary(Uri),
- method => Method,
+ method => lowercase_method(Method),
version => Version
}).
--spec add_header(Request :: t(), Name :: string(), Value :: string()) -> t().
+-spec add_header(Request :: t(), Name :: atom() | binary(), Value :: string() | binary()) -> t().
%% @private
add_header(Request, Name, Value) when is_atom(Name) ->
- add_header(Request, atom_to_list(Name), Value);
-add_header(#{ headers := Headers } = Request, Name, Value) ->
- HeaderName = string:lowercase(Name),
- maps:update(headers, maps:put(HeaderName, Value, Headers), Request).
+ add_header(Request, atom_to_binary(Name, utf8), Value);
+add_header(Request, Name, Value) when is_list(Name) ->
+ add_header(Request, list_to_binary(Name), Value);
+add_header(Request, Name, Value) when is_list(Value) ->
+ add_header(Request, Name, list_to_binary(Value));
+add_header(#{ raw_headers := RawHeaders0, headers := Headers0 } = Request, Name, Value) ->
+ RawHeaders = [{Name, Value} | RawHeaders0],
+ Headers = maps:put(string:lowercase(Name), Value, Headers0),
+ maps:update(headers, Headers,
+ maps:update(raw_headers, RawHeaders, Request)).
-spec content_length(Request :: t()) -> integer().
%% @doc Content-Length header value as intger
@@ -125,11 +134,11 @@ content_length(Request) ->
nil ->
0;
ContentLength ->
- list_to_integer(ContentLength)
+ binary_to_integer(ContentLength)
end.
-spec method(Request :: t()) -> atom().
-%% @doc http verb: 'GET', 'POST','PUT', 'DELETE', 'OPTIONS', ...
+%% @doc http verb in lower case: get, post, put, delete, options, ...
method(#{ method := Method}) ->
Method.
@@ -143,16 +152,23 @@ uri(#{ uri := Uri}) ->
version(#{ version := Version }) ->
Version.
--spec header(Request :: t(), HeaderName :: string()) -> string() | nil.
-%% @doc Returns a particular header from request. Header name is lowerced
-header(#{ headers := Headers }, HeaderName) ->
- maps:get(HeaderName, Headers, nil).
+-spec header(Request :: t(), HeaderName :: string() | binary()) -> binary() | nil.
+%% @doc Returns a particular header from request.
+header(Request, HeaderName) when is_list(HeaderName) ->
+ header(Request, list_to_binary(HeaderName));
+header(#{ headers := Headers }, HeaderName) when is_binary(HeaderName) ->
+ maps:get(string:lowercase(HeaderName), Headers, nil).
-spec headers(Request :: t()) -> map().
-%% @doc http headers map. Header names are normalized and lowercased
+%% @doc HTTP headers map. Header names are normalized and lowercased
headers(#{ headers := Headers }) ->
Headers.
+-spec raw_headers(Request :: t()) -> proplists:proplist().
+%% @doc HTTP raw headers. Headers order and case are preserved
+raw_headers(#{ raw_headers := RawHeaders }) ->
+ RawHeaders.
+
-spec body(Request :: t()) -> binary().
%% @doc request body
body(#{ body := Body }) ->
@@ -188,11 +204,14 @@ transport(#{transport := Transport}) ->
-spec is_keepalive(Request :: t()) -> boolean().
%% @doc tells you if the request is keepalive or not [https://tools.ietf.org/html/rfc6223]
-is_keepalive(#{ headers := #{"connection" := Conn }, version := {1, 0} }) ->
- string:lowercase(Conn) =:= "keep-alive";
+is_keepalive(#{ headers := #{<<"connection">> := Conn }, version := {1, 0} }) ->
+ string:lowercase(Conn) =:= <<"keep-alive">>;
is_keepalive(#{ version := {1, 0} }) ->
false;
-is_keepalive(#{ headers := #{"connection" := "close"}, version := {1, 1} }) ->
+is_keepalive(#{ headers := #{<<"connection">> := <<"close">>}, version := {1, 1} }) ->
false;
is_keepalive(_) ->
true.
+
+lowercase_method(Method) ->
+ binary_to_existing_atom(string:lowercase(atom_to_binary(Method, latin1)), latin1).
diff --git a/test/bookish_spork_SUITE.erl b/test/bookish_spork_SUITE.erl
index 37bfb8d..6ff6342 100644
--- a/test/bookish_spork_SUITE.erl
+++ b/test/bookish_spork_SUITE.erl
@@ -1,5 +1,6 @@
-module(bookish_spork_SUITE).
+-include("bookish_spork_test_helpers.hrl").
-include_lib("common_test/include/ct.hrl").
-include_lib("eunit/include/eunit.hrl").
@@ -27,21 +28,18 @@
wait_for_async_request_completed_test/1,
multiple_async_requests_test/1,
multiple_async_with_closed_connection_requests_test/1,
- capture_requests_test/1
+ capture_requests_test/1,
+ raw_headers_test/1
]).
--define(CUSTOM_PORT, 9871).
--define(HTTPC_SUCCESS(Status), {ok, {{_, Status, _}, _, _}}).
--define(HTTPC_OK, ?HTTPC_SUCCESS(200)).
--define(HTTPC_NO_CONTENT, ?HTTPC_SUCCESS(204)).
-
all() ->
[base_integration_test, customized_response_test, failed_capture_test,
stub_multiple_requests_test, stub_with_fun_test, keepalive_connection_test,
without_keepalive_test, ssl_test, tls_ext_test, connection_id_test,
request_when_there_is_no_stub_test, http_error_test,
wait_for_async_request_completed_test, multiple_async_requests_test,
- multiple_async_with_closed_connection_requests_test, capture_requests_test].
+ multiple_async_with_closed_connection_requests_test, capture_requests_test,
+ raw_headers_test].
init_per_suite(Config) ->
ok = application:ensure_started(inets),
@@ -68,10 +66,10 @@ base_integration_test(_Config) ->
{ok, {{"HTTP/1.1", 204, "No Content"}, _ResponseHeaders, _Body}} =
httpc:request(get, {"http://localhost:32002/o/lo/lo?q=kjk", RequestHeaders}, [], []),
{ok, Request} = bookish_spork:capture_request(),
- ?assertEqual('GET', bookish_spork_request:method(Request)),
+ ?assertEqual(get, bookish_spork_request:method(Request)),
?assertEqual(<<"/o/lo/lo?q=kjk">>, bookish_spork_request:uri(Request)),
?assertEqual({1, 1}, bookish_spork_request:version(Request)),
- ?assertMatch(#{"host" := "localhost:32002"}, bookish_spork_request:headers(Request)).
+ ?assertMatch(#{<<"host">> := <<"localhost:32002">>}, bookish_spork_request:headers(Request)).
customized_response_test(Config) ->
CustomPort = integer_to_list(?config(custom_port, Config)),
@@ -88,11 +86,11 @@ customized_response_test(Config) ->
?assertEqual("test", proplists:get_value("x-custom-response-header", ResponseHeaders)),
?assertEqual(<<"Hello, Test">>, string:chomp(Body)),
{ok, Request} = bookish_spork:capture_request(),
- ?assertEqual('POST', bookish_spork_request:method(Request)),
+ ?assertEqual(post, bookish_spork_request:method(Request)),
?assertEqual(<<"/api/v1/users">>, bookish_spork_request:uri(Request)),
?assertEqual({1, 1}, bookish_spork_request:version(Request)),
?assertEqual(RequestBody, bookish_spork_request:body(Request)),
- ?assertMatch(#{"accept" := "text/plain"}, bookish_spork_request:headers(Request)).
+ ?assertMatch(#{<<"accept">> := <<"text/plain">>}, bookish_spork_request:headers(Request)).
failed_capture_test(_Config) ->
?assertMatch({error, _}, bookish_spork:capture_request(), "Got an error when there is no stub").
@@ -135,15 +133,7 @@ tls_ext_test(_Config) ->
{"https://localhost:32002/tls", [{"Connection", "close"}]}, [], []),
{ok, Request} = bookish_spork:capture_request(),
TlsExt = bookish_spork_request:tls_ext(Request),
- ?assertMatch(#{
- renegotiation_info := _,
- ec_point_formats := _,
- elliptic_curves := _,
- signature_algs := _,
- alpn := _,
- sni := _,
- srp := _
- }, TlsExt).
+ ?assertMatch(?TLS_EXT, TlsExt).
-else.
tls_ext_test(_Config) ->
{skip, "Nothing to test"}.
@@ -232,6 +222,14 @@ capture_requests_test(_Config) ->
Requests = bookish_spork:capture_requests(),
?assertEqual([<<"/one">>, <<"/two">>], [bookish_spork_request:uri(Req) || Req <- Requests]).
+raw_headers_test(_Config) ->
+ ok = bookish_spork:stub_request(),
+ ?HTTPC_NO_CONTENT = httpc:request(get, {"http://localhost:32002/test", ?CUSTOM_CASE_HEADERS},
+ [], [{headers_as_is, true}]),
+ [Request] = bookish_spork:capture_requests(),
+ RawHeaders = bookish_spork_request:raw_headers(Request),
+ ?assertEqual(?RAW_HEADERS, RawHeaders, "Raw headers preserve order and case").
+
gun_request(ConnectionPid) ->
StreamRef = gun:get(ConnectionPid, "/"),
{ok, Body} = gun:await_body(ConnectionPid, StreamRef),
diff --git a/test/bookish_spork_request_test.erl b/test/bookish_spork_request_test.erl
index c635cff..4ff2bd5 100644
--- a/test/bookish_spork_request_test.erl
+++ b/test/bookish_spork_request_test.erl
@@ -9,7 +9,7 @@ elixir_interface_test_() ->
?_assertEqual(Request, bookish_spork_request:'__struct__'(#{}))].
new_test_() ->
- Method = 'POST',
+ Method = post,
Uri = "/foo/bar",
Version = {1, 1},
Body = <<"Hello">>,
@@ -22,14 +22,16 @@ new_test_() ->
method => Method,
uri => list_to_binary(Uri),
version => Version,
- headers => #{"x-foo" => "Bar"},
+ headers => #{<<"x-foo">> => <<"Bar">>},
+ raw_headers => [{<<"X-Foo">>, <<"Bar">>}],
body => Body
},
List = [
{method, Method},
{uri, list_to_binary(Uri)},
{version, Version},
- {headers, #{"x-foo" => "Bar"}},
+ {headers, #{<<"x-foo">> => <<"Bar">>}},
+ {raw_headers, [{<<"X-Foo">>, <<"Bar">>}]},
{body, Body}
],
[?_assertEqual(Request, bookish_spork_request:new(Map)),
@@ -43,7 +45,7 @@ content_length_test_() ->
add_header_test() ->
Request = bookish_spork_request:add_header(bookish_spork_request:new(), "X-Lol", "kjk"),
- ?assertEqual(#{"x-lol" => "kjk"}, bookish_spork_request:headers(Request),
+ ?assertEqual(#{<<"x-lol">> => <<"kjk">>}, bookish_spork_request:headers(Request),
"Converts header name to lower case").
diff --git a/test/bookish_spork_test_helpers.hrl b/test/bookish_spork_test_helpers.hrl
new file mode 100644
index 0000000..396c377
--- /dev/null
+++ b/test/bookish_spork_test_helpers.hrl
@@ -0,0 +1,65 @@
+-ifndef(BOOKISH_SPORK_TEST_HELPERS_HRL).
+-define(BOOKISH_SPORK_TEST_HELPERS_HRL, true).
+
+-define(CUSTOM_PORT, 9871).
+-define(HTTPC_SUCCESS(Status), {ok, {{_, Status, _}, _, _}}).
+-define(HTTPC_OK, ?HTTPC_SUCCESS(200)).
+-define(HTTPC_NO_CONTENT, ?HTTPC_SUCCESS(204)).
+
+-define(CUSTOM_CASE_HEADERS, [
+ {"DNT", "1"},
+ {"Connection", "close"},
+ {"x-vEry-cAmEl-cAsE", "yEs"}
+]).
+
+-ifdef(OTP_RELEASE).
+-if(?OTP_RELEASE >= 23).
+-define(RAW_HEADERS, [
+ {<<"DNT">>, <<"1">>},
+ {<<"Connection">>, <<"close">>},
+ {<<"x-vEry-cAmEl-cAsE">>, <<"yEs">>}
+]).
+-else.
+-define(RAW_HEADERS, [
+ {<<"Dnt">>, <<"1">>},
+ {<<"Connection">>, <<"close">>},
+ {<<"X-Very-Camel-Case">>, <<"yEs">>}
+]).
+-endif.
+-else.
+-define(RAW_HEADERS, [
+ {<<"Dnt">>, <<"1">>},
+ {<<"Connection">>, <<"close">>},
+ {<<"X-Very-Camel-Case">>, <<"yEs">>}
+]).
+-endif.
+
+-ifdef(OTP_RELEASE).
+-if(?OTP_RELEASE >= 23).
+-define(TLS_EXT, #{
+ alpn := _,
+ client_hello_versions := _,
+ cookie := _,
+ ec_point_formats := _,
+ elliptic_curves := _,
+ key_share := _,
+ pre_shared_key := _,
+ psk_key_exchange_modes := _,
+ signature_algs := _,
+ signature_algs_cert := _,
+ sni := _
+}).
+-else.
+-define(TLS_EXT, #{
+ alpn := _,
+ ec_point_formats := _,
+ elliptic_curves := _,
+ renegotiation_info := _,
+ signature_algs := _,
+ sni := _,
+ srp := _
+}).
+-endif.
+-endif.
+
+-endif.