Skip to content

Commit 3920ca7

Browse files
srishtea-22RicardoTrindadeedgurgel
authored
fix: return a descriptive error for relative URLs instead of a CaseClauseError (#504)
--------- Co-authored-by: Ricardo Trindade <ricardo.trindade743@gmail.com> Co-authored-by: Eduardo Gurgel Pinho <eduardo@gurgel.me>
1 parent 64ca963 commit 3920ca7

File tree

3 files changed

+82
-37
lines changed

3 files changed

+82
-37
lines changed

lib/httpoison/base.ex

Lines changed: 60 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,24 @@ defmodule HTTPoison.Base do
707707
end
708708
end
709709

710+
@doc false
711+
defp validate_request_url(url) do
712+
url = to_string(url)
713+
714+
%{scheme: scheme, host: host} = URI.parse(url)
715+
716+
cond do
717+
is_nil(scheme) ->
718+
{:error, "Invalid URL: #{url} (missing scheme e.g. http:// or https:// or http+unix://)"}
719+
720+
is_nil(host) or host == "" ->
721+
{:error, "Invalid URL: #{url} (missing host)"}
722+
723+
true ->
724+
:ok
725+
end
726+
end
727+
710728
@doc false
711729
def default_process_request_url(url) do
712730
case url |> String.slice(0, 12) |> String.downcase() do
@@ -877,59 +895,65 @@ defmodule HTTPoison.Base do
877895
process_response_body,
878896
process_response
879897
) do
880-
hn_proxy_options = build_hackney_proxy_options(request)
881-
hn_options = hn_proxy_options ++ build_hackney_options(module, request)
882-
883-
case do_request(request, hn_options) do
884-
{:ok, status_code, headers} ->
885-
response(
886-
process_response_status_code,
887-
process_response_headers,
888-
process_response_body,
889-
process_response,
890-
status_code,
891-
headers,
892-
"",
893-
request
894-
)
898+
case validate_request_url(request.url) do
899+
:ok ->
900+
hn_proxy_options = build_hackney_proxy_options(request)
901+
hn_options = hn_proxy_options ++ build_hackney_options(module, request)
895902

896-
{:ok, status_code, headers, client} ->
897-
max_length = Keyword.get(request.options, :max_body_length, :infinity)
898-
899-
case :hackney.body(client, max_length) do
900-
{:ok, body} ->
903+
case do_request(request, hn_options) do
904+
{:ok, status_code, headers} ->
901905
response(
902906
process_response_status_code,
903907
process_response_headers,
904908
process_response_body,
905909
process_response,
906910
status_code,
907911
headers,
908-
body,
912+
"",
913+
request
914+
)
915+
916+
{:ok, status_code, headers, client} ->
917+
max_length = Keyword.get(request.options, :max_body_length, :infinity)
918+
919+
case :hackney.body(client, max_length) do
920+
{:ok, body} ->
921+
response(
922+
process_response_status_code,
923+
process_response_headers,
924+
process_response_body,
925+
process_response,
926+
status_code,
927+
headers,
928+
body,
929+
request
930+
)
931+
932+
{:error, reason} ->
933+
{:error, %Error{reason: reason}}
934+
end
935+
936+
{:ok, {:maybe_redirect, status_code, headers, _client}} ->
937+
maybe_redirect(
938+
process_response_status_code,
939+
process_response_headers,
940+
status_code,
941+
headers,
909942
request
910943
)
911944

945+
{:ok, id} ->
946+
{:ok, %HTTPoison.AsyncResponse{id: id}}
947+
912948
{:error, reason} ->
913949
{:error, %Error{reason: reason}}
914-
end
915950

916-
{:ok, {:maybe_redirect, status_code, headers, _client}} ->
917-
maybe_redirect(
918-
process_response_status_code,
919-
process_response_headers,
920-
status_code,
921-
headers,
922-
request
923-
)
924-
925-
{:ok, id} ->
926-
{:ok, %HTTPoison.AsyncResponse{id: id}}
951+
{:connect_error, {:error, reason}} ->
952+
{:error, %Error{reason: reason}}
953+
end
927954

928955
{:error, reason} ->
929956
{:error, %Error{reason: reason}}
930-
931-
{:connect_error, {:error, reason}} ->
932-
{:error, %Error{reason: reason}}
933957
end
934958
end
935959

mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ defmodule HTTPoison.Mixfile do
77
def project do
88
[
99
app: :httpoison,
10-
version: "2.2.3",
10+
version: "2.3.0",
1111
elixir: "~> 1.11",
1212
name: "HTTPoison",
1313
description: @description,

test/httpoison_base_test.exs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,4 +749,25 @@ defmodule HTTPoisonBaseTest do
749749
assert HTTPoison.request(:get, "http://localhost") ==
750750
{:error, %HTTPoison.Error{reason: reason}}
751751
end
752+
753+
test "invalid url raises error for missing or empty host" do
754+
invalid_urls = ["http://", "http:///path"]
755+
756+
for url <- invalid_urls do
757+
assert_raise HTTPoison.Error, "\"Invalid URL: #{url} (missing host)\"", fn ->
758+
HTTPoison.get!(url)
759+
end
760+
end
761+
end
762+
763+
test "invalid url returns error for missing or empty host" do
764+
invalid_urls = ["http://", "http:///path"]
765+
766+
for url <- invalid_urls do
767+
# assert_raise HTTPoison.Error, "\"Invalid URL: #{url} (missing host)\"", fn ->
768+
assert {:error, %HTTPoison.Error{reason: error}} = HTTPoison.get(url)
769+
assert error =~ "Invalid URL:"
770+
# end
771+
end
772+
end
752773
end

0 commit comments

Comments
 (0)