diff --git a/.gitignore b/.gitignore index a669b7e..7ddb9a9 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ soap-*.tar # Misc. /priv /.DS_Store +/.idea \ No newline at end of file diff --git a/README.md b/README.md index bc436ea..dd186b5 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,12 @@ Configure version of SOAP protocol. Supported versions `1.1`(default) and `1.2`: config :soap, :globals, version: "1.1" ``` +To force https on the soap calls, just calls + +```elixir +config :soap, :globals, force_https: true +``` + ## Usage The documentation is available on [HexDocs](https://hexdocs.pm/soap/api-reference.html). diff --git a/lib/soap.ex b/lib/soap.ex index a2248e2..4c507d2 100644 --- a/lib/soap.ex +++ b/lib/soap.ex @@ -106,11 +106,11 @@ defmodule Soap do {:ok, %Soap.Response{}} """ - @spec call(wsdl :: map(), operation :: String.t(), params :: map(), headers :: any(), opts :: any()) :: any() - def call(wsdl, operation, params, headers \\ [], opts \\ []) do + @spec call(wsdl :: map(), operation :: String.t(), params :: map(), headers :: any(), opts :: any(), flags :: any()) :: any() + def call(wsdl, operation, params, headers \\ [], opts \\ [], flags \\ []) do wsdl |> validate_operation(operation) - |> Request.call(operation, params, headers, opts) + |> Request.call(operation, params, headers, opts, flags) |> handle_response end diff --git a/lib/soap/request.ex b/lib/soap/request.ex index 65ef3e7..c141ac8 100644 --- a/lib/soap/request.ex +++ b/lib/soap/request.ex @@ -2,6 +2,8 @@ defmodule Soap.Request do @moduledoc """ Documentation for Soap.Request. """ + require Logger + alias Soap.Request.{Headers, Params} @doc """ @@ -9,27 +11,35 @@ defmodule Soap.Request do Calling HTTPoison request by Map with method, url, body, headers, options keys. """ - @spec call(wsdl :: map(), operation :: String.t(), params :: any(), headers :: any(), opts :: any()) :: any() - def call(wsdl, operation, soap_headers_and_params, request_headers \\ [], opts \\ []) + @spec call(wsdl :: map(), operation :: String.t(), params :: any(), headers :: any(), opts :: any(), flags :: any()) :: any() + def call(wsdl, operation, soap_headers_and_params, request_headers \\ [], opts \\ [], flags \\ []) - def call(wsdl, operation, {soap_headers, params}, request_headers, opts) do - url = get_url(wsdl) - request_headers = Headers.build(wsdl, operation, request_headers) + def call(wsdl, operation, {soap_headers, params}, request_headers, opts, flags) do + url = get_url(wsdl, force_https?()) body = Params.build_body(wsdl, operation, params, soap_headers) + request_headers = Headers.build(wsdl, operation, request_headers, body) + + if flags[:debug] do + Logger.debug(%{log_id: "soap-call-debug", url: url, body: body, request_headers: request_headers, opts: opts}) + end get_http_client().post(url, body, request_headers, opts) end - def call(wsdl, operation, params, request_headers, opts), - do: call(wsdl, operation, {%{}, params}, request_headers, opts) + def call(wsdl, operation, params, request_headers, opts, flags), + do: call(wsdl, operation, {%{}, params}, request_headers, opts, flags) @spec get_http_client() :: HTTPoison.Base def get_http_client do Application.get_env(:soap, :globals)[:http_client] || HTTPoison end - @spec get_url(wsdl :: map()) :: String.t() - defp get_url(wsdl) do - wsdl.endpoint + @spec force_https?() :: boolean() + def force_https? do + Application.get_env(:soap, :globals)[:force_https] || false end + + @spec get_url(wsdl :: map(), boolean()) :: String.t() + defp get_url(wsdl, true), do: String.replace(wsdl.endpoint, "http://", "https://") + defp get_url(wsdl, _), do: wsdl.endpoint end diff --git a/lib/soap/request/headers.ex b/lib/soap/request/headers.ex index 776d006..a8cfe91 100644 --- a/lib/soap/request/headers.ex +++ b/lib/soap/request/headers.ex @@ -10,11 +10,16 @@ defmodule Soap.Request.Headers do """ - @spec build(map(), String.t(), list()) :: list() - def build(wsdl, operation, custom_headers) do + @content_types %{ + "1.1" => "text/xml; charset=utf-8", + "1.2" => "application/soap+xml; charset=utf-8", + } + + @spec build(map(), String.t(), list(), String.t()) :: list() + def build(wsdl, operation, custom_headers, body) do wsdl |> extract_soap_action_by_operation(operation) - |> extract_headers(custom_headers) + |> extract_headers(custom_headers, wsdl, body) end @spec extract_soap_action_by_operation(map(), String.t()) :: String.t() @@ -22,12 +27,25 @@ defmodule Soap.Request.Headers do Enum.find(wsdl[:operations], fn x -> x[:name] == operation end)[:soap_action] end - @spec extract_headers(String.t(), list()) :: list() - defp extract_headers(soap_action, []), do: base_headers(soap_action) - defp extract_headers(_, custom_headers), do: custom_headers + @spec extract_headers(String.t(), list(), map(), String.t()) :: list() + defp extract_headers(soap_action, [], wsdl, body), do: base_headers(soap_action, wsdl, body) + defp extract_headers(_, custom_headers, _, _), do: custom_headers - @spec base_headers(String.t()) :: list() - defp base_headers(soap_action) do - [{"SOAPAction", soap_action}, {"Content-Type", "text/xml;charset=utf-8"}] + @spec base_headers(String.t(), map(), String.t()) :: list() + defp base_headers(soap_action, wsdl, body) do + uri = URI.parse(wsdl[:endpoint]) + [ + {"Content-Length", byte_size(body)}, + {"Content-Type", Map.get(@content_types, wsdl[:soap_version])}, + {"User-Agent", "strong-soap/3.4.0"}, + {"Accept", "text/html,application/xhtml+xml,application/xml,text/xml;q=0.9,*/*;q=0.8"}, + {"Accept-Encoding", "none"}, + {"Accept-Charset", "utf-8"}, + {"Connection", "close"}, + {"GET", "#{uri.path} HTTP/1.1}"}, + {"Host", uri.host}, + {"SOAPAction", "\"#{soap_action}\""}, + {"referer", wsdl[:endpoint]}, + ] end end