Jim

Jim

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

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"}
)
10
Post #3
Aetherus

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

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 :slight_smile:

Last Post!

Jim

Jim OP

Thanks very much, I’ll study this over the weekend.

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
kszambelanczyk
Hello! Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app. I creat...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews