Jim
Help with HTTPoison POST
As a follow up to my earlier question:
I have the code compiling and running but not getting a successful login from the rest server. If I use cURL all is good, but my code reports a success code of 200, so the call executed correctly, but a failed login.
It seems to me that the parameters are the same, so I can’t figure out what is wrong. A successful login returns:
{
“return_code”: 1,
“session”: “nlvpneu7jgk2t4nvrus9hi4bp6”,
“uid”: “804276”,
“username”: “me@example.com”
}
But I get the return for a failed login:
{“return_code”:0}
I’ll paste the cURL and my code, if someone sees the issue and can help me I would greatly appreciate the help.
Here is the cURL:
curl -X POST
‘SimpliSafe Control Panel’
-H ‘Cache-Control: no-cache’
-H ‘Content-Type: application/x-www-form-urlencoded’
-d ‘name=user%example.com&pass=mypass&device_name=my_iphone&device_uuid=51644e80-1b62-11e3-b773-0800200c9a66&version=1200&no_persist=1&XDEBUG_SESSION_START=session_name’
Here is my code:
defmodule Simplisafe.SsFreeze do
@user_agent [ { “User-agent”, “Elixir” } ]
def fetch(user, password) do
ss_url()
|> ss_login(user, password)
|> handle_response
end
defp ss_url do
“SimpliSafe Control Panel”
end
defp handle_response({ :ok, %{status_code: 200, body: body}}) do
{ :ok, body }
end
defp handle_response({ :error, %{status_code: sc, body: body}}) do
{ :error, sc, body }
end
defp handle_response({ ec, %{status_code: sc, body: body}}) do
{ ec, sc, body }
end
def post_body(user, password) do
%{“name” => user,
“pass” => password,
“device_name” => “my_iphone”,
“device_uuid” => “51644e80-1b62-11e3-b773-0800200c9a66”,
“version” => “1200”,
“no_persist” => “1”,
“XDEBUG_SESSION_START” => “session_name”,
} |> Poison.encode!
end
def ss_login(user, password) do
HTTPoison.post(ss_url(), post_body(user, password),
%{“Content-Type” => “application/x-www-form-urlencoded”, “Cache-Control” => “no-cache”})
end
def ss_login(url, user, password) do
HTTPoison.post(url, post_body(user, password), %{“Content-Type” => “application/x-www-form-urlencoded”, “Cache-Control” => “no-cache”})
end
end
Most Liked
Aetherus
According to your curl example, the request should be sent with “application/x-www-form-urlencoded” format. You can try URI.encode_query/1 to encode a map or a keyword list to that format, for example,
req_body = URI.encode_query(%{"name" => "who am i", "pass" => "$3cret"})
HTTPoison.post(
"http://www.example.com/login",
req_body,
%{"Content-Type" => "application/x-www-form-urlencoded"}
)
Aetherus
No, it doesn’t. Here is the HTTP client module I wrote for a scraper, with HTTPoison for sending requests, and Floki for HTML parsing:
defmodule EkangScraper.HttpClient do
alias EkangScraper.CookieStore
def request_raw(method, url, params) do
payload = URI.encode_query(params)
cookies = Agent.get(CookieStore, &(&1)) || []
try do
response = case method do
method when method in [:get, :delete] ->
real_url = url <> "?" <> payload
apply(HTTPoison, :"#{method}!", [
real_url,
%{},
[hackney: [cookie: cookies]]])
_ ->
apply(HTTPoison, :"#{method}!", [
url,
payload,
%{"Content-Type" => "application/x-www-form-urlencoded; charset=utf-8"},
[hackney: [cookie: cookies]]])
end
case response.status_code do
code when code >= 200 and code < 400 ->
Agent.update(CookieStore, &(cookies(response) || &1))
response.body
code -> raise """
Oops! #{code}
URL: #{url}
Method: #{method}
Params: #{inspect params}
Cookies: #{inspect cookies}
"""
end
rescue
e in HTTPoison.Error ->
raise """
Oops! #{e.reason}!
URL: #{url}
Method: #{method}
Params: #{inspect params}
Cookies: #{inspect cookies}
"""
end
end
def request(method, url, params) do
request_raw(method, url, params)
|> Floki.parse()
end
for method <- [:get, :post, :patch, :put, :delete] do
def unquote(:"#{method}_raw")(url, params \\ %{}) do
request_raw(unquote(method), url, params)
end
def unquote(method)(url, params \\ %{}) do
request(unquote(method), url, params)
end
end
defp cookies(%HTTPoison.Response{} = resp) do
resp.headers
|> Enum.filter(fn
{"Set-Cookie", _} -> true
_ -> false
end)
|> Enum.map(fn{_, cookie} -> cookie end)
end
end
The CookieStore is just a name for an Agent process
# in application.ex
children = [
worker(Agent, [fn -> nil end, [name: EkangScraper.CookieStore]])
]
How to use
# GET request.
# Params are appended to URL as query string.
# Cookies are automatically handled
doc = EkangScraper.HttpClient.get("http://www.example.com/path", %{foo: "bar", baz: "qux"})
# POST request.
# Params are encoded as application/x-www-form-urlencoded and put to request body.
# Cookies are automatically handled.
doc = EkangScraper.HttpClient.post("http://www.example.com/path", %{foo: "bar", baz: "qux"})
# If you just want a raw response body as a string
body_string = EkangScraper.HttpClient.get_raw("http://www.example.com/path", %{foo: "bar", baz: "qux"})
There are patch, put, delete and their _raw counterpart as well.
aseigo
You are creating a json object but then saying that the Content-Type is "Content-Type" => "application/x-www-form-urlencoded" … that should be application/json or else you can pass a {:form, [{K, V}, ...]} tuple to HTTPoison.post as the body to send a urlencoded form. One or the other .. hth ![]()








