Packages
exvcr
0.14.1
0.17.1
0.17.0
0.16.0
0.15.2
0.15.1
0.15.0
0.14.4
0.14.3
0.14.2
0.14.1
0.14.0
0.13.5
0.13.4
0.13.3
0.13.2
0.13.1
0.13.0
0.12.3
0.12.2
0.12.1
0.12.0
0.11.2
0.11.1
0.11.0
0.10.4
0.10.3
0.10.2
0.10.1
0.10.0
0.9.1
0.9.0
0.8.12
0.8.11
0.8.10
0.8.9
0.8.8
0.8.7
0.8.6
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.1
0.4.0
0.3.9
0.3.8
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.1
0.2.0
0.1.7
0.1.6
0.1.5
HTTP request/response recording library for elixir, inspired by VCR.
Current section
Files
Jump to
Current section
Files
lib/exvcr/adapter/hackney.ex
defmodule ExVCR.Adapter.Hackney do
@moduledoc """
Provides adapter methods to mock :hackney methods.
"""
use ExVCR.Adapter
alias ExVCR.Adapter.Hackney.Store
alias ExVCR.Util
defmacro __using__(_opts) do
quote do
Store.start
end
end
defdelegate convert_from_string(string), to: ExVCR.Adapter.Hackney.Converter
defdelegate convert_to_string(request, response), to: ExVCR.Adapter.Hackney.Converter
defdelegate parse_request_body(request_body), to: ExVCR.Adapter.Hackney.Converter
@doc """
Returns the name of the mock target module.
"""
def module_name do
:hackney
end
@doc """
Returns list of the mock target methods with function name and callback.
Implementation for global mock.
"""
def target_methods() do
[
{:request, &ExVCR.Recorder.request([&1, &2, &3, &4, &5])},
{:request, &ExVCR.Recorder.request([&1, &2, &3, &4])},
{:request, &ExVCR.Recorder.request([&1, &2, &3])},
{:request, &ExVCR.Recorder.request([&1, &2])},
{:request, &ExVCR.Recorder.request([&1])},
{:body, &handle_body_request([&1])},
{:body, &handle_body_request([&1, &2])}
]
end
@doc """
Returns list of the mock target methods with function name and callback.
"""
def target_methods(recorder) do
[
{:request, &ExVCR.Recorder.request(recorder, [&1, &2, &3, &4, &5])},
{:request, &ExVCR.Recorder.request(recorder, [&1, &2, &3, &4])},
{:request, &ExVCR.Recorder.request(recorder, [&1, &2, &3])},
{:request, &ExVCR.Recorder.request(recorder, [&1, &2])},
{:request, &ExVCR.Recorder.request(recorder, [&1])},
{:body, &handle_body_request(recorder, [&1])},
{:body, &handle_body_request(recorder, [&1, &2])}
]
end
@doc """
Generate key for searching response.
"""
def generate_keys_for_request(request) do
url = Enum.fetch!(request, 1)
method = Enum.fetch!(request, 0)
request_body = Enum.fetch(request, 3) |> parse_request_body
headers = Enum.at(request, 2, []) |> Util.stringify_keys()
[url: url, method: method, request_body: request_body, headers: headers]
end
@doc """
Callback from ExVCR.Handler when response is retrieved from the HTTP server.
"""
def hook_response_from_server(response) do
apply_filters(response)
end
defp apply_filters({:ok, status_code, headers, reference}) do
filtered_headers = ExVCR.Filter.remove_blacklisted_headers(headers)
{:ok, status_code, filtered_headers, reference}
end
defp apply_filters({:ok, status_code, headers}) do
filtered_headers = ExVCR.Filter.remove_blacklisted_headers(headers)
{:ok, status_code, filtered_headers}
end
defp apply_filters({:error, reason}) do
{:error, reason}
end
@doc """
Callback from ExVCR.Handler when response is retrieved from the json file cache.
"""
def hook_response_from_cache(_request, nil), do: nil
def hook_response_from_cache(_request, %ExVCR.Response{type: "error"} = response), do: response
def hook_response_from_cache(_request, %ExVCR.Response{body: nil} = response), do: response
def hook_response_from_cache([_, _, _, _, opts], %ExVCR.Response{body: body} = response) do
if :with_body in opts || {:with_body, true} in opts do
response
else
client = make_ref()
client_key_atom = client |> inspect |> String.to_atom
Store.set(client_key_atom, body)
%{response | body: client}
end
end
defp handle_body_request(args) do
ExVCR.Actor.CurrentRecorder.get()
|> handle_body_request(args)
end
defp handle_body_request(nil, args) do
:meck.passthrough(args)
end
defp handle_body_request(recorder, [client]) do
handle_body_request(recorder, [client, :infinity])
end
defp handle_body_request(recorder, [client, max_length]) do
client_key_atom = client |> inspect |> String.to_atom
if body = Store.get(client_key_atom) do
Store.delete(client_key_atom)
{:ok, body}
else
case :meck.passthrough([client, max_length]) do
{:ok, body} ->
body = ExVCR.Filter.filter_sensitive_data(body)
client_key_string = inspect(client)
ExVCR.Recorder.update(recorder,
fn(%{request: _request, response: response}) ->
response.body == client_key_string
end,
fn(%{request: request, response: response}) ->
%{request: request, response: %{response | body: body}}
end
)
{:ok, body}
{ret, body} ->
{ret, body}
end
end
end
@doc """
Returns the response from the ExVCR.Reponse record.
"""
def get_response_value_from_cache(response) do
if response.type == "error" do
{:error, response.body}
else
case response.body do
nil -> {:ok, response.status_code, response.headers}
_ -> {:ok, response.status_code, response.headers, response.body}
end
end
end
@doc """
Default definitions for stub.
"""
def default_stub_params(:headers), do: %{"Content-Type" => "text/html"}
def default_stub_params(:status_code), do: 200
end