Skip to content
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ soap-*.tar
# Misc.
/priv
/.DS_Store
/.idea
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
6 changes: 3 additions & 3 deletions lib/soap.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
30 changes: 20 additions & 10 deletions lib/soap/request.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,44 @@ defmodule Soap.Request do
@moduledoc """
Documentation for Soap.Request.
"""
require Logger

alias Soap.Request.{Headers, Params}

@doc """
Executing with parsed wsdl and headers with body map.

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
36 changes: 27 additions & 9 deletions lib/soap/request/headers.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,42 @@ 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()
defp extract_soap_action_by_operation(wsdl, operation) 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