Elixir - problems with https URLs - erlang

I'm new to Elixir and Erlang and having some issues with accessing https URLs. I've tried the Elixir-specific HTTPotion and Erlang's :inets module.
So from the iex console (Interactive Elixir):
With HTTPotion:
HTTPotion.start
HTTPotion.get("https://api.github.com")
With :inets:
:inets.start
:ssl.start
:httpc.request('https://api.github.com')
In both cases I get a giant stacktrace that essential says there is a bad match somewhere and that a state machine is terminating. I don't get this when accessing http URLs. What am I missing? Thanks.
Edit - here is the error message from HTTPotion:
iex(40)> HTTPotion.get("https://api.github.com")
** (Protocol.UndefinedError) protocol String.Chars not implemented for {:EXIT, {{{{:badmatch, ""}, [{:ssl_handshake, :dec_hello_extensions, 2, [file: 'ssl_handshake.erl', line: 1737]}, {:ssl_handshake, :decode_handshake, 3, [file: 'ssl_handshake.erl', line: 926]}, {:tls_handshake, :get_tls_handshake_aux, 3, [file: 'tls_handshake.erl', line: 155]}, {:tls_connection, :next_state, 4, [file: 'tls_connection.erl', line: 433]}, {:gen_fsm, :handle_msg, 7, [file: 'gen_fsm.erl', line: 503]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 237]}]}, {:gen_fsm, :sync_send_all_state_event, [#PID<0.227.0>, {:start, 5000}, :infinity]}}, {:gen_server, :call, [#PID<0.226.0>, {:send_req, {{:url, 'https://api.github.com', 'api.github.com', 443, :undefined, :undefined, '/', :https, :hostname}, [], :get, "", [], 5000}}, 5000]}}}
(elixir) lib/string/chars.ex:3: String.Chars.impl_for!/1
(elixir) lib/string/chars.ex:17: String.Chars.to_string/1
(httpotion) lib/httpotion.ex:157: HTTPotion.request/5
iex(40)>
16:50:10.640 [error] ** State machine #PID<0.227.0> terminating
** Last message in was {:tcp, #Port<0.7454>,
<<22, 3, 3, 0, 93, 2, 0, 0, 89, 3, 3, 84, 40, 158, 178, 2, 216, 45, 226, 183, 79, 42, 199, 205, 19, 31, 63, 223, 138, 208, 132, 186, 28, 129, 123, 235, 1, 142, 90, 243, 25, 70, 210, 32, 199, 56, 251, 131, ...>>}
** When State == :hello
** Data == [data: [{'StateData',
{:state, :client, {#Reference<0.0.0.1360>, #PID<0.226.0>}, :gen_tcp,
:tls_connection, :tcp, :tcp_closed, :tcp_error, 'api.github.com', 443,
#Port<0.7454>,
{:ssl_options, :tls, [{3, 3}, {3, 2}, {3, 1}, {3, 0}], :verify_none,
{#Function<7.50551058/3 in :ssl.handle_verify_options/2>, []},
#Function<8.50551058/1 in :ssl.handle_verify_options/2>, false, false,
:undefined, 1, "", '***', "", '***', '***', '***', "", '***', :undefined,
:undefined, '***', '***',
[<<192, 36>>, <<192, 40>>, <<192, 38>>, <<192, 42>>, <<0, 107>>,
<<0, 106>>, <<0, 61>>, <<192, 35>>, <<192, 39>>, <<192, 37>>, <<192, 41>>,
<<0, 103>>, <<0, ...>>, <<...>>, ...],
#Function<1.50551058/4 in :ssl.handle_options/1>, true, 268435456, false,
:undefined, false, :undefined, :undefined, true, :undefined, false},
{:socket_options, :binary, 0, 0, 0, false}, '***', '***', '***', 49168,
'***', 61463, :ssl_session_cache, {3, 3}, false, :undefined,
{:undefined, :undefined}, :undefined, :undefined, '***', '***', '***',
:undefined, '***', '***', '***', 53269, #Reference<0.0.0.1363>, :undefined,
'***', {false, :first}, {#PID<0.226.0>, #Reference<0.0.0.1361>},
#Reference<0.0.0.1364>, {[], []}, false, true, false, false, :undefined,
:undefined, :undefined}}]]
** Reason for termination =
** {{:badmatch, ""},
[{:ssl_handshake, :dec_hello_extensions, 2,
[file: 'ssl_handshake.erl', line: 1737]},
{:ssl_handshake, :decode_handshake, 3,
[file: 'ssl_handshake.erl', line: 926]},
{:tls_handshake, :get_tls_handshake_aux, 3,
[file: 'tls_handshake.erl', line: 155]},
{:tls_connection, :next_state, 4, [file: 'tls_connection.erl', line: 433]},
{:gen_fsm, :handle_msg, 7, [file: 'gen_fsm.erl', line: 503]},
{:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 237]}]}
16:50:10.642 [error] GenServer #PID<0.226.0> terminating
Last message: {:send_req, {{:url, 'https://api.github.com', 'api.github.com', 443, :undefined, :undefined, '/', :https, :hostname}, [], :get, "", [], 5000}}
State: {:state, 'api.github.com', 443, :undefined, #Reference<0.0.0.1352>, false, :undefined, [], true, :undefined, false, [], {[], []}, :undefined, :idle, :undefined, "", 0, 0, [], :undefined, :undefined, :undefined, :undefined, false, :undefined, :undefined, "", :undefined, false, 188446, 0, :undefined}
** (exit) exited in: :gen_fsm.sync_send_all_state_event(#PID<0.227.0>, {:start, 5000}, :infinity)
** (EXIT) an exception was raised:
** (MatchError) no match of right hand side value: ""
(ssl) ssl_handshake.erl:1737: :ssl_handshake.dec_hello_extensions/2
(ssl) ssl_handshake.erl:926: :ssl_handshake.decode_handshake/3
(ssl) tls_handshake.erl:155: :tls_handshake.get_tls_handshake_aux/3
(ssl) tls_connection.erl:433: :tls_connection.next_state/4
(stdlib) gen_fsm.erl:503: :gen_fsm.handle_msg/7
(stdlib) proc_lib.erl:237: :proc_lib.init_p_do_apply/3
nil
iex(41)>

Mystery solved. I posted this question to the Elixir-lang group and this is a known bug in Erlang OTP 17.3. The solution is to apply a patch, wait for the next version, or downgrade to OTP 17.1.
Details here:
https://groups.google.com/forum/#!topic/elixir-lang-talk/xsAEzCfmRoQ

Either downgrade to Erlang 17.1 or use the latest release tag "OTP-17.3.4" from GitHub - https://github.com/erlang/otp/releases
Incase you choose to use the "OTP-17.3.4" release tag from GitHub, then once you download the source and untar/unzip it, run ./otp_build autoconf, before you run the usual build instructions (./configure, make, make install).
17.3.4 is an internal release and hence no releases are available on the official Erlang site. [source: https://twitter.com/brucify/status/537240367239016448]. Although, I do see that Erlang Solutions site has builds called 17.3 rev2.

Related

IPv6 Resolution in gen_tcp connect when called from Elixir

When using the connect method of gen_tcp, IPv4 domains are resolved automatically, i.e.:
:gen_tcp.connect('google.com', 443, [:binary, active: false])
{:ok, #Port<0.116>}
However, if resolving an IPv6 domain, it will not resolve correctly
iex(production#b7726c04)3> :gen_tcp.connect('ipv6.google.com', 443, [:binary, active: false])
{:error, :nxdomain}
Am I missing an option with the socket options of :gen_tcp.connect that would enable IPv6 resolution or do I have manually resolve the domain myself before usage? i.e. something like:
:inet_res.resolve('ipv6.google.com', :in, :aaaa)
{:ok,
{:dns_rec, {:dns_header, 1, true, :query, false, false, true, true, false, 0},
[{:dns_query, 'ipv6.google.com', :aaaa, :in, false}],
[
{:dns_rr, 'ipv6.google.com', :cname, :in, 0, 604606, 'ipv6.l.google.com',
:undefined, [], false},
{:dns_rr, 'ipv6.l.google.com', :aaaa, :in, 0, 300,
{9220, 26624, 16387, 3072, 0, 0, 0, 101}, :undefined, [], false},
{:dns_rr, 'ipv6.l.google.com', :aaaa, :in, 0, 300,
{9220, 26624, 16387, 3072, 0, 0, 0, 102}, :undefined, [], false},
{:dns_rr, 'ipv6.l.google.com', :aaaa, :in, 0, 300,
{9220, 26624, 16387, 3072, 0, 0, 0, 113}, :undefined, [], false},
{:dns_rr, 'ipv6.l.google.com', :aaaa, :in, 0, 300,
{9220, 26624, 16387, 3072, 0, 0, 0, 100}, :undefined, [], false}
], [], []}}
Then using the IPv6 tuple directly:
:gen_tcp.connect({9220, 26624, 16387, 3072, 0, 0, 0, 101}, 443, [:binary, active: false])
{:ok, #Port<0.138>}
You can use inet6:
{ok, P} = gen_tcp:connect("ipv6.google.com", 80, [inet6]).
{ok,#Port<0.14>}

Positioning a popup keyboard

I found a plugin from github that pops out a virtual keyboard as you click a textbox/textarea. The problem is, if you have other elements, the keyboard appears at the bottom. I want it to show adjacent the textbox clicked. I tried appending ".position({
my: "left top",
at: "left top",
of: "#targetElement"
});" at the end of the keyboard initializer(last line) but it's not taking effect. Here's the script.
<script type="text/javascript">
$(function(){
var keyboard = {
'layout': [
// alphanumeric keyboard type
// text displayed on keyboard button, keyboard value, keycode, column span, new row
[
[
['`', '`', 192, 0, true], ['1', '1', 49, 0, false], ['2', '2', 50, 0, false], ['3', '3', 51, 0, false], ['4', '4', 52, 0, false], ['5', '5', 53, 0, false], ['6', '6', 54, 0, false],
['7', '7', 55, 0, false], ['8', '8', 56, 0, false], ['9', '9', 57, 0, false], ['0', '0', 48, 0, false], ['-', '-', 189, 0, false], ['=', '=', 187, 0, false],
['q', 'q', 81, 0, true], ['w', 'w', 87, 0, false], ['e', 'e', 69, 0, false], ['r', 'r', 82, 0, false], ['t', 't', 84, 0, false], ['y', 'y', 89, 0, false], ['u', 'u', 85, 0, false],
['i', 'i', 73, 0, false], ['o', 'o', 79, 0, false], ['p', 'p', 80, 0, false], ['[', '[', 219, 0, false], [']', ']', 221, 0, false], ['\', '\\', 220, 0, false],
['a', 'a', 65, 0, true], ['s', 's', 83, 0, false], ['d', 'd', 68, 0, false], ['f', 'f', 70, 0, false], ['g', 'g', 71, 0, false], ['h', 'h', 72, 0, false], ['j', 'j', 74, 0, false],
['k', 'k', 75, 0, false], ['l', 'l', 76, 0, false], [';', ';', 186, 0, false], [''', '\'', 222, 0, false], ['Enter', '13', 13, 3, false],
['Shift', '16', 16, 2, true], ['z', 'z', 90, 0, false], ['x', 'x', 88, 0, false], ['c', 'c', 67, 0, false], ['v', 'v', 86, 0, false], ['b', 'b', 66, 0, false], ['n', 'n', 78, 0, false],
['m', 'm', 77, 0, false], [',', ',', 188, 0, false], ['.', '.', 190, 0, false], ['/', '/', 191, 0, false], ['Shift', '16', 16, 2, false],
['Bksp', '8', 8, 3, true], ['Space', '32', 32, 12, false], ['Clear', '46', 46, 3, false], ['Cancel', '27', 27, 3, false]
]
]
]
}
$('#name.jQKeyboard').initKeypad({'keyboardLayout': keyboard});
});
</script>
If we're talking about: https://github.com/poiyee/jQKeyboard then I would suggest:
$('#name.jQKeyboard').initKeypad({'keyboardLayout': keyboard});
$('#jQKeyboardContainer').position({
my: "left top",
at: "left top",
of: $('#name.jQKeyboard')
});
The plugin is written in an older fashion and I would suggest or consider using $.widget() to write you're own that allows you to set the position as an option.
If you wanted a modern working widget, it would look like this: https://jsfiddle.net/Twisty/mzj9w2yb/4/

Connection closed - strange error, unable to connect from erlang VM to certain host

IMPORTANT Proved that migration from 18.3 to 18.3.4 causes this issue, and migration back to 18.3 removes it.
Everything worked until one moment. Then it just stoped to work.
def work do
HTTPotion.get("https://ssl-third-party.com",
ibrowse: [
is_ssl: true,
ssl_options: [
certfile: Path.join(File.cwd!, "cert_dev.pem"),
password: "pass" |> to_charlist,
]
])
end
Which responds with:
%HTTPotion.ErrorResponse{message: "closed"}
I tried several erlang libs without elixir wrapping(hackney + ibrowse) from iex shell:
iex(5)> url = <<"https://ssl-third-party.com">>
iex(6)> headers = []
[]
iex(8)> payload = <<>>
""
iex(9)> options=[:insecure]
[:insecure]
iex(10)> :hackney.request(m, url, headers, payload, options)
{:error, :closed}
###
iex(1)> a = "https://ssl-third-party.com" |> to_char_list
iex(2)> :ibrowse.send_req(a, [], :get)
{:error, {:conn_failed, {:error, :closed}}}
While I can connect to other hosts.
Applications are started, I can make request from same session.
Connection works with simple curl request.
Erlang tested - 18.3.4/19.0.2
OS X El Capitan.
UPD1
also I noted this report during reinstalling all erlang-related packages:
20:25:01.535 [error] Failed updating session:
ProfileName: :httpc_mix
SessionId: {{'repo.hex.pm', 443}, #PID<0.163.0>}
Pos: 7
Value: 0
when
Session (db) info: :undefined
Session (db): {:session, {{'repo.hex.pm', 443}, #PID<0.163.0>}, false, :https,
{:sslsocket, {:gen_tcp, #Port<0.5536>, :tls_connection, :undefined},
#PID<0.164.0>}, {:essl, []}, 1, :keep_alive, true}
Session (record): {:EXIT,
{:badarg,
[{:ets, :lookup,
[:httpc_mix__session_db, {{'repo.hex.pm', 443}, #PID<0.163.0>}], []},
{:httpc_manager, :lookup_session, 2, [file: 'httpc_manager.erl', line: 189]},
{:httpc_handler, :update_session, 4,
[file: 'httpc_handler.erl', line: 1909]},
{:httpc_handler, :handle_empty_queue, 4,
[file: 'httpc_handler.erl', line: 1368]},
{:httpc_handler, :handle_info, 2, [file: 'httpc_handler.erl', line: 471]},
{:gen_server, :try_dispatch, 4, [file: 'gen_server.erl', line: 601]},
{:gen_server, :handle_msg, 5, [file: 'gen_server.erl', line: 667]},
{:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 247]}]}}
T: :error
E: :badarg
20:25:01.536 [error] Failed updating session:
ProfileName: :httpc_mix
SessionId: {{'repo.hex.pm', 443}, #PID<0.163.0>}
Pos: 9
Value: true
when
Session (db) info: :undefined
Session (db): {:session, {{'repo.hex.pm', 443}, #PID<0.163.0>}, false, :https,
{:sslsocket, {:gen_tcp, #Port<0.5536>, :tls_connection, :undefined},
#PID<0.164.0>}, {:essl, []}, 1, :keep_alive, false}
Session (record): {:EXIT,
{:badarg,
[{:ets, :lookup,
[:httpc_mix__session_db, {{'repo.hex.pm', 443}, #PID<0.163.0>}], []},
{:httpc_manager, :lookup_session, 2, [file: 'httpc_manager.erl', line: 189]},
{:httpc_handler, :update_session, 4,
[file: 'httpc_handler.erl', line: 1909]},
{:httpc_handler, :maybe_make_session_available, 2,
[file: 'httpc_handler.erl', line: 1516]},
{:httpc_handler, :answer_request, 3,
[file: 'httpc_handler.erl', line: 1507]},
{:httpc_handler, :terminate, 2, [file: 'httpc_handler.erl', line: 759]},
{:gen_server, :try_terminate, 3, [file: 'gen_server.erl', line: 629]},
{:gen_server, :terminate, 7, [file: 'gen_server.erl', line: 795]}]}}
T: :error
E: :badarg
20:25:01.541 [error] GenServer #PID<0.163.0> terminating
** (stop) {:failed_updating_session, [profile: :httpc_mix, session_id: {{'repo.hex.pm', 443}, #PID<0.163.0>}, pos: 9, value: true, etype: :error, error: :badarg, stacktrace: [{:ets, :update_element, [:httpc_mix__session_db, {{'repo.hex.pm', 443}, #PID<0.163.0>}, {9, true}], []}, {:httpc_manager, :update_session, 4, [file: 'httpc_manager.erl', line: 210]}, {:httpc_handler, :update_session, 4, [file: 'httpc_handler.erl', line: 1887]}, {:httpc_handler, :maybe_make_session_available, 2, [file: 'httpc_handler.erl', line: 1516]}, {:httpc_handler, :answer_request, 3, [file: 'httpc_handler.erl', line: 1507]}, {:httpc_handler, :terminate, 2, [file: 'httpc_handler.erl', line: 759]}, {:gen_server, :try_terminate, 3, [file: 'gen_server.erl', line: 629]}, {:gen_server, :terminate, 7, [file: 'gen_server.erl', line: 795]}]]}
(inets) httpc_handler.erl:1911: :httpc_handler.update_session/4
(inets) httpc_handler.erl:1516: :httpc_handler.maybe_make_session_available/2
(inets) httpc_handler.erl:1507: :httpc_handler.answer_request/3
(inets) httpc_handler.erl:759: :httpc_handler.terminate/2
(stdlib) gen_server.erl:629: :gen_server.try_terminate/3
(stdlib) gen_server.erl:795: :gen_server.terminate/7
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
Last message: {:ssl, {:sslsocket, {:gen_tcp, #Port<0.5536>, :tls_connection, :undefined}, #PID<0.164.0>}, "HTTP/1.1 200 OK\r\nx-amz-id-2: FGpS/bqXLPTNYV4oMTTIvqekRgbExlvO83ZoTR6deiB02Hsm4uqtctPYvP5lqryk/ZYK12/DCuM=\r\nx-amz-request-id: 346087C27C829E83\r\nx-amz-replication-status: COMPLETED\r\nCache-Control: public, max-age=604800\r\nx-amz-meta-surrogate-key: installs\r\nx-amz-version-id: IzHO194FIe8NSS4oev.5dtp2BgBltonw\r\nLast-Modified: Wed, 29 Jun 2016 00:00:27 GMT\r\nETag: \"e8a325a6ca33736d137e5b6f57fe4259\"\r\nContent-Type: binary/octet-stream\r\nServer: AmazonS3\r\nVia: 1.1 varnish\r\nFastly-Debug-Digest: 864530c58fa2f5e6f7b455ba1b8a8fd668c94f688c98b6cdc85319515ff6f6b1\r\nContent-Length: 350\r\nAccept-Ranges: bytes\r\nDate: Fri, 29 Jul 2016 17:25:01 GMT\r\nVia: 1.1 varnish\r\nAge: 235183\r\nConnection: keep-alive\r\nX-Served-By: cache-iad2144-IAD, cache-bma7023-BMA\r\nX-Cache: HIT, HIT\r\nX-Cache-Hits: 1, 1\r\nX-Timer: S1469813101.087231,VS0,VE0\r\n\r\njM3an/yCuclmNcCX0wzS9QhCHsJl+Xf6/FS5bAaQ5O9AAFMlkCnJt4vW08LNU6eL\nkfOsK+mVZ1n8Dk/+I8ThzpO1NZlH3UNYt/8OgK+ZfhFlrT0D1UZ/QEIR1/8TIC4v\nC25ibCcvxTK9zG93mAdrLLCLA6/o4NXeaMV6DOOZ31ZcMWjpCNjDLU1B20UsVSBN\nKzsLkI4QfgrtSt5Iquhs0wovJlpz/lZh7jEf58BTMWa/Z9Yl2EmEVsyO8Fie5RiF\np+KTkDILxY/QkKwSPE+0AcS5BR3dpJSsp8m5RVLUb/44b0KUKko+uPBmN8g6TSYP\nGSIG5Ay9BjXE0uAi2RTFEw==\n"}
State: {:state, {:request, #Reference<0.0.3.498>, #PID<0.70.0>, 0, :https, {'repo.hex.pm', 443}, '/installs/rebar3-1.x.csv.signed', [], :get, {:http_request_h, :undefined, 'keep-alive', :undefined, :undefined, :undefined, :undefined, :undefined, :undefined, :undefined, :undefined, :undefined, :undefined, :undefined, :undefined, :undefined, :undefined, 'repo.hex.pm', :undefined, :undefined, :undefined, :undefined, :undefined, :undefined, :undefined, :undefined, :undefined, [], 'Mix/1.3.2', :undefined, :undefined, :undefined, '0', :undefined, :undefined, :undefined, :undefined, :undefined, ...}, {[], []}, {:http_options, 'HTTP/1.1', :infinity, true, {:essl, []}, :undefined, true, :infinity, false}, 'https://repo.hex.pm/installs/rebar3-1.x.csv.signed', [], :none, [], 1469813101026, :undefined, :undefined, false}, {:session, {{'repo.hex.pm', 443}, #PID<0.163.0>}, false, :https, {:sslsocket, {:gen_tcp, #Port<0.5536>, :tls_connection, :undefined}, #PID<0.164.0>}, {:essl, []}, 1, :keep_alive, false}, :undefined, :undefined, :undefined, {:httpc_response, :parse, [:nolimit, true]}, {[], []}, {[], []}, :new, [], :nolimit, :nolimit, {:options, {:undefined, []}, {:undefined, []}, 0, 2, 5, 120000, 2, :disabled, false, :inet, :default, :default, []}, {:timers, [], :undefined}, :httpc_mix, :inactive}
UPD2
Probably must be OSX or >18.3 OTP bug: just made it on the other ubuntu computer Erlang version 18.3 and it worked fine, this one returns (Erlang shell):
httpc:request(get, {"https://ssl-third-party.com", []}, [], []).
{error,{failed_connect,[{to_address,{"https://ssl-third-party.com",
443}},
{inet,[inet],closed}]}}
Sounds like you're running in to the same problem discussed in this erlang-questions mail thread recently.
Apparently the SSL application changed cipher suite configurations between 18.3 patch versions which can lead to this problem.
In the mail thread I referenced the solution was to configure SSL to use TLS 1.2, i.e. setting
{versions, ['tlsv1.2']}
for the SSL application.

TCPDF alignment rendering issue

I'm getting weird alignment issues with TCPDF.
Here's a chunk of my looping code:
$pdf->setColor('text', 255, 255, 255);
$pdf->SetFontSize(20);
$pdf->Cell( 180, 25, $post->post_title, 0, 1, 'R', false, '', 3);
$pdf->Ln(1);
$pdf->setColor('text', 0, 0, 0);
$pdf->SetFontSize(14);
$pdf->Cell( 180, 8, $product->get_sku(), 0, 1, 'R', false);
$pdf->Ln(4);
$pdf->Image( $product->post->thumbnail, 15, 50, 80, 0, 'JPG', '', '', true, 150, '', false, false, 0, false, false, false);
$pdf->SetFontSize(10);
$pdf->MultiCell(90, 0, '', 1, 'C', 1, 0, '', '', true, 0, false, true, 0, 'T');
$pdf->setCellHeightRatio(1.65);
$pdf->MultiCell(90, 0, ($post->post_excerpt ? $post->post_excerpt : 'No description found.'), 1, 'C', 1, 1, '', '', true, 0, true, true, 0);
$pdf->setCellHeightRatio(0);
And here are the results which vary from first line centering for description to the more obvious title alignment even though it is from the same loop :
What gives?
Makes me wonder if I should have just stuck with FPDF...

Has anyone seen this Elixir/Erlang error? [duplicate]

I'm new to Elixir and Erlang and having some issues with accessing https URLs. I've tried the Elixir-specific HTTPotion and Erlang's :inets module.
So from the iex console (Interactive Elixir):
With HTTPotion:
HTTPotion.start
HTTPotion.get("https://api.github.com")
With :inets:
:inets.start
:ssl.start
:httpc.request('https://api.github.com')
In both cases I get a giant stacktrace that essential says there is a bad match somewhere and that a state machine is terminating. I don't get this when accessing http URLs. What am I missing? Thanks.
Edit - here is the error message from HTTPotion:
iex(40)> HTTPotion.get("https://api.github.com")
** (Protocol.UndefinedError) protocol String.Chars not implemented for {:EXIT, {{{{:badmatch, ""}, [{:ssl_handshake, :dec_hello_extensions, 2, [file: 'ssl_handshake.erl', line: 1737]}, {:ssl_handshake, :decode_handshake, 3, [file: 'ssl_handshake.erl', line: 926]}, {:tls_handshake, :get_tls_handshake_aux, 3, [file: 'tls_handshake.erl', line: 155]}, {:tls_connection, :next_state, 4, [file: 'tls_connection.erl', line: 433]}, {:gen_fsm, :handle_msg, 7, [file: 'gen_fsm.erl', line: 503]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 237]}]}, {:gen_fsm, :sync_send_all_state_event, [#PID<0.227.0>, {:start, 5000}, :infinity]}}, {:gen_server, :call, [#PID<0.226.0>, {:send_req, {{:url, 'https://api.github.com', 'api.github.com', 443, :undefined, :undefined, '/', :https, :hostname}, [], :get, "", [], 5000}}, 5000]}}}
(elixir) lib/string/chars.ex:3: String.Chars.impl_for!/1
(elixir) lib/string/chars.ex:17: String.Chars.to_string/1
(httpotion) lib/httpotion.ex:157: HTTPotion.request/5
iex(40)>
16:50:10.640 [error] ** State machine #PID<0.227.0> terminating
** Last message in was {:tcp, #Port<0.7454>,
<<22, 3, 3, 0, 93, 2, 0, 0, 89, 3, 3, 84, 40, 158, 178, 2, 216, 45, 226, 183, 79, 42, 199, 205, 19, 31, 63, 223, 138, 208, 132, 186, 28, 129, 123, 235, 1, 142, 90, 243, 25, 70, 210, 32, 199, 56, 251, 131, ...>>}
** When State == :hello
** Data == [data: [{'StateData',
{:state, :client, {#Reference<0.0.0.1360>, #PID<0.226.0>}, :gen_tcp,
:tls_connection, :tcp, :tcp_closed, :tcp_error, 'api.github.com', 443,
#Port<0.7454>,
{:ssl_options, :tls, [{3, 3}, {3, 2}, {3, 1}, {3, 0}], :verify_none,
{#Function<7.50551058/3 in :ssl.handle_verify_options/2>, []},
#Function<8.50551058/1 in :ssl.handle_verify_options/2>, false, false,
:undefined, 1, "", '***', "", '***', '***', '***', "", '***', :undefined,
:undefined, '***', '***',
[<<192, 36>>, <<192, 40>>, <<192, 38>>, <<192, 42>>, <<0, 107>>,
<<0, 106>>, <<0, 61>>, <<192, 35>>, <<192, 39>>, <<192, 37>>, <<192, 41>>,
<<0, 103>>, <<0, ...>>, <<...>>, ...],
#Function<1.50551058/4 in :ssl.handle_options/1>, true, 268435456, false,
:undefined, false, :undefined, :undefined, true, :undefined, false},
{:socket_options, :binary, 0, 0, 0, false}, '***', '***', '***', 49168,
'***', 61463, :ssl_session_cache, {3, 3}, false, :undefined,
{:undefined, :undefined}, :undefined, :undefined, '***', '***', '***',
:undefined, '***', '***', '***', 53269, #Reference<0.0.0.1363>, :undefined,
'***', {false, :first}, {#PID<0.226.0>, #Reference<0.0.0.1361>},
#Reference<0.0.0.1364>, {[], []}, false, true, false, false, :undefined,
:undefined, :undefined}}]]
** Reason for termination =
** {{:badmatch, ""},
[{:ssl_handshake, :dec_hello_extensions, 2,
[file: 'ssl_handshake.erl', line: 1737]},
{:ssl_handshake, :decode_handshake, 3,
[file: 'ssl_handshake.erl', line: 926]},
{:tls_handshake, :get_tls_handshake_aux, 3,
[file: 'tls_handshake.erl', line: 155]},
{:tls_connection, :next_state, 4, [file: 'tls_connection.erl', line: 433]},
{:gen_fsm, :handle_msg, 7, [file: 'gen_fsm.erl', line: 503]},
{:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 237]}]}
16:50:10.642 [error] GenServer #PID<0.226.0> terminating
Last message: {:send_req, {{:url, 'https://api.github.com', 'api.github.com', 443, :undefined, :undefined, '/', :https, :hostname}, [], :get, "", [], 5000}}
State: {:state, 'api.github.com', 443, :undefined, #Reference<0.0.0.1352>, false, :undefined, [], true, :undefined, false, [], {[], []}, :undefined, :idle, :undefined, "", 0, 0, [], :undefined, :undefined, :undefined, :undefined, false, :undefined, :undefined, "", :undefined, false, 188446, 0, :undefined}
** (exit) exited in: :gen_fsm.sync_send_all_state_event(#PID<0.227.0>, {:start, 5000}, :infinity)
** (EXIT) an exception was raised:
** (MatchError) no match of right hand side value: ""
(ssl) ssl_handshake.erl:1737: :ssl_handshake.dec_hello_extensions/2
(ssl) ssl_handshake.erl:926: :ssl_handshake.decode_handshake/3
(ssl) tls_handshake.erl:155: :tls_handshake.get_tls_handshake_aux/3
(ssl) tls_connection.erl:433: :tls_connection.next_state/4
(stdlib) gen_fsm.erl:503: :gen_fsm.handle_msg/7
(stdlib) proc_lib.erl:237: :proc_lib.init_p_do_apply/3
nil
iex(41)>
Mystery solved. I posted this question to the Elixir-lang group and this is a known bug in Erlang OTP 17.3. The solution is to apply a patch, wait for the next version, or downgrade to OTP 17.1.
Details here:
https://groups.google.com/forum/#!topic/elixir-lang-talk/xsAEzCfmRoQ
Either downgrade to Erlang 17.1 or use the latest release tag "OTP-17.3.4" from GitHub - https://github.com/erlang/otp/releases
Incase you choose to use the "OTP-17.3.4" release tag from GitHub, then once you download the source and untar/unzip it, run ./otp_build autoconf, before you run the usual build instructions (./configure, make, make install).
17.3.4 is an internal release and hence no releases are available on the official Erlang site. [source: https://twitter.com/brucify/status/537240367239016448]. Although, I do see that Erlang Solutions site has builds called 17.3 rev2.

Resources