Skip to content

Commit b3c04f4

Browse files
jdunkerleyfarmaazon
authored andcommitted
Handle empty text in URI.parse (#12786)
More graceful error when an empty URI is passed. Default to https if no scheme passed. ![image](https://github.com/user-attachments/assets/30596442-363b-483b-a458-fbb89cdafcac)
1 parent d1e05d3 commit b3c04f4

File tree

3 files changed

+29
-10
lines changed

3 files changed

+29
-10
lines changed

distribution/lib/Standard/Base/0.0.0-dev/src/Network/URI.enso

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ type URI
5151

5252
example_parse = URI.parse "http://example.com"
5353
parse : Text -> URI ! Syntax_Error
54-
parse uri:Text =
55-
Panic.catch URISyntaxException (URI.Value (Java_URI.new uri) []) caught_panic->
54+
parse uri:Text = if uri == "" then Error.throw (Syntax_Error.Error "URI cannot be empty.") else
55+
raw_uri = Panic.catch URISyntaxException (URI.Value (Java_URI.new uri) []) caught_panic->
5656
query_index = uri.index_of '?'
5757
result = if query_index.is_nothing then Nothing else
5858
new_uri = (uri.take query_index+1) + (URITransformer.encodeQuery (uri.drop query_index+1))
@@ -64,6 +64,8 @@ type URI
6464
truncated = if message.is_nothing || message.length > 100 then "Invalid URI '" + uri.to_display_text + "'" else
6565
"URI syntax error: " + message
6666
Error.throw (Syntax_Error.Error truncated)
67+
if raw_uri.scheme == Nothing && (uri.starts_with "/" . not) then URI.parse ("https://" + uri) else
68+
raw_uri
6769

6870
## GROUP Metadata
6971
ICON metadata

test/Base_Tests/src/Network/Http_Spec.enso

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ add_specs suite_builder =
181181

182182
group_builder.specify "Fails on a bad URL scheme" <|
183183
Data.fetch "zxcv://bad.scheme" . should_fail_with Illegal_Argument
184-
Data.fetch "" . should_fail_with Illegal_Argument
184+
Data.fetch "" . should_fail_with Syntax_Error
185185

186186
group_builder.specify "can select the version" <| Test.with_retries <|
187187
req = Request.get url_get
@@ -578,30 +578,30 @@ add_specs suite_builder =
578578
suite_builder.group "Header resolution" group_builder->
579579
group_builder.specify "Default content type and encoding" <|
580580
expected = [Header.content_type "text/plain; charset=UTF-8"]
581-
_resolve_headers (Request.new HTTP_Method.Get "" [] (Request_Body.Text "")) . should_equal_ignoring_order expected
581+
_resolve_headers (Request.new HTTP_Method.Get "www.enso.org" [] (Request_Body.Text "")) . should_equal_ignoring_order expected
582582

583583
group_builder.specify "Content type specified in body" <|
584584
expected = [Header.content_type "application/json; charset=UTF-8"]
585-
_resolve_headers (Request.new HTTP_Method.Get "" [] (Request_Body.Text "" content_type="application/json")) . should_equal_ignoring_order expected
585+
_resolve_headers (Request.new HTTP_Method.Get "www.enso.org" [] (Request_Body.Text "" content_type="application/json")) . should_equal_ignoring_order expected
586586

587587
group_builder.specify "Content type specified in header list" <|
588588
expected = [Header.content_type "application/json"]
589-
_resolve_headers (Request.new HTTP_Method.Get "" [Header.content_type "application/json"] (Request_Body.Text "")) . should_equal_ignoring_order expected
589+
_resolve_headers (Request.new HTTP_Method.Get "www.enso.org" [Header.content_type "application/json"] (Request_Body.Text "")) . should_equal_ignoring_order expected
590590

591591
group_builder.specify "Text encoding specified in body" <|
592592
expected = [Header.content_type "text/plain; charset=UTF-16LE"]
593-
_resolve_headers (Request.new HTTP_Method.Get "" [] (Request_Body.Text "" encoding=Encoding.utf_16_le)) . should_equal_ignoring_order expected
593+
_resolve_headers (Request.new HTTP_Method.Get "www.enso.org" [] (Request_Body.Text "" encoding=Encoding.utf_16_le)) . should_equal_ignoring_order expected
594594

595595
group_builder.specify "Can't specify content type in both places" <|
596-
_resolve_headers (Request.new HTTP_Method.Get "" [Header.content_type "application/json"] (Request_Body.Text "" content_type="text/plain")) . should_fail_with Illegal_Argument
596+
_resolve_headers (Request.new HTTP_Method.Get "www.enso.org" [Header.content_type "application/json"] (Request_Body.Text "" content_type="text/plain")) . should_fail_with Illegal_Argument
597597

598598
group_builder.specify "Custom header" <|
599599
expected = [Header.new "some" "header", Header.content_type "application/json; charset=UTF-8"]
600-
_resolve_headers (Request.new HTTP_Method.Get "" [Header.new "some" "header"] (Request_Body.Text "" content_type="application/json")) . should_equal_ignoring_order expected
600+
_resolve_headers (Request.new HTTP_Method.Get "www.enso.org" [Header.new "some" "header"] (Request_Body.Text "" content_type="application/json")) . should_equal_ignoring_order expected
601601

602602
group_builder.specify "Multiple content types in header list are ok" <|
603603
expected = [Header.content_type "application/json", Header.content_type "text/plain"]
604-
_resolve_headers (Request.new HTTP_Method.Get "" [Header.content_type "application/json", Header.content_type "text/plain"] (Request_Body.Text "")) . should_equal_ignoring_order expected
604+
_resolve_headers (Request.new HTTP_Method.Get "www.enso.org" [Header.content_type "application/json", Header.content_type "text/plain"] (Request_Body.Text "")) . should_equal_ignoring_order expected
605605

606606
suite_builder.group "Http Error handling" group_builder->
607607
group_builder.specify "should be able to handle request errors" <|

test/Base_Tests/src/Network/URI_Spec.enso

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,17 @@ add_specs suite_builder =
3333
addr.query.should_equal "key=val"
3434
addr.fragment.should_equal Nothing
3535

36+
group_builder.specify "should assume https:// if no scheme" <|
37+
addr = URI.parse "example.com/foo/bar?key=val"
38+
addr.scheme.should_equal "https"
39+
addr.user_info.should_equal Nothing
40+
addr.host.should_equal "example.com"
41+
addr.authority.should_equal "example.com"
42+
addr.port.should_equal Nothing
43+
addr.path.should_equal "/foo/bar"
44+
addr.query.should_equal "key=val"
45+
addr.fragment.should_equal Nothing
46+
3647
group_builder.specify "should allow to convert a text to URI" <|
3748
addr2 = URI.from "https://example.org:1234/?a=b&c=d+e#line=10,20"
3849
addr2.should_be_a URI
@@ -84,6 +95,12 @@ add_specs suite_builder =
8495
r.catch.to_display_text . should_contain "a b c"
8596
URI.from "a b c" . should_fail_with Syntax_Error
8697

98+
group_builder.specify "should return Syntax_Error when parsing empty URI" <|
99+
r = URI.parse ""
100+
r.should_fail_with Syntax_Error
101+
r.catch.to_display_text . should_contain "empty"
102+
URI.from "" . should_fail_with Syntax_Error
103+
87104
group_builder.specify "should allow a URI without scheme or authority" <|
88105
uri = URI.parse "//a/b/c"
89106
uri.scheme.should_equal Nothing

0 commit comments

Comments
 (0)