Skip to content

Commit

Permalink
Handle URL encoding automatically in query string. (#9823)
Browse files Browse the repository at this point in the history
  • Loading branch information
jdunkerley authored Apr 30, 2024
1 parent f87c75a commit 4d6d6f2
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -817,7 +817,7 @@ type Date
Format "2020-06-21" with French locale as "21. juin 2020"

example_format = Date.new 2020 6 21 . format (Date_Time_Formatter.from "d. MMMM yyyy" (Locale.new "fr"))
@format (value-> make_date_format_selector value)
@format make_date_format_selector
format : Date_Time_Formatter -> Text
format self format:Date_Time_Formatter=Date_Time_Formatter.iso_date =
format.format_date self
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,7 @@ type Date_Time

example_format =
Date_Time.parse "2020-06-21T16:41:13+03:00" . format "d. MMMM yyyy" (Locale.new "fr")
@format (value-> make_date_time_format_selector value)
@format make_date_time_format_selector
format : Date_Time_Formatter -> Text
format self format:Date_Time_Formatter =
format.format_date_time self
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ type Time_Of_Day
from Standard.Base import Time_Of_Day

example_format = Time_Of_Day.new 16 21 10 . format "'hour:'h"
@format (value-> make_time_format_selector value)
@format make_time_format_selector
format : Date_Time_Formatter -> Text
format self format:Date_Time_Formatter =
format.format_time self
Expand Down
32 changes: 26 additions & 6 deletions distribution/lib/Standard/Base/0.0.0-dev/src/Network/URI.enso
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import project.Data.Ordering.Comparable
import project.Data.Ordering.Ordering
import project.Data.Pair.Pair
import project.Data.Text.Text
import project.Data.Text.Extensions
import project.Data.Vector.No_Wrap
import project.Data.Vector.Vector
import project.Enso_Cloud.Enso_Secret.Enso_Secret
Expand All @@ -16,12 +17,14 @@ import project.Errors.Problem_Behavior.Problem_Behavior
import project.Meta
import project.Nothing.Nothing
import project.Panic.Panic
import project.Warning.Warning
from project.Data.Boolean.Boolean import False, True
from project.Data.Text.Extensions import all
from project.Enso_Cloud.Enso_Secret import as_hideable_value
from project.Widget_Helpers import make_text_secret_selector

polyglot java import java.net.URI as Java_URI
polyglot java import java.net.URLEncoder
polyglot java import java.net.URISyntaxException
polyglot java import org.enso.base.enso_cloud.EnsoSecretAccessDenied
polyglot java import org.enso.base.net.URITransformer
Expand All @@ -35,12 +38,13 @@ type URI
ICON convert

Parse a URI from text.
If the input text is not a valid URI, this function will separate the
query string and encode it. If it still cannot be parsed, it will throw
a `Syntax_Error`.

Arguments:
- uri: The text to parse as a URI.

Throws a Syntax_Error when the text cannot be parsed as a URI.

> Example
Parse URI text.

Expand All @@ -50,10 +54,17 @@ type URI
parse : Text -> URI ! Syntax_Error
parse uri:Text =
Panic.catch URISyntaxException (URI.Value (Java_URI.new uri) []) caught_panic->
message = caught_panic.payload.getMessage
truncated = if message.is_nothing || message.length > 100 then "Invalid URI '" + uri.to_display_text + "'" else
"URI syntax error: " + message
Error.throw (Syntax_Error.Error truncated)
query_index = uri.index_of '?'
result = if query_index.is_nothing then Nothing else
new_uri = (uri.take query_index+1) + (URITransformer.encodeQuery (uri.drop query_index+1))
warning = Invalid_Query_String.Warning (uri.drop query_index+1)
Panic.catch URISyntaxException (Warning.attach warning URI.Value (Java_URI.new new_uri) []) _->Nothing

if result.is_nothing.not then result else
message = caught_panic.payload.getMessage
truncated = if message.is_nothing || message.length > 100 then "Invalid URI '" + uri.to_display_text + "'" else
"URI syntax error: " + message
Error.throw (Syntax_Error.Error truncated)

## GROUP Metadata
ICON metadata
Expand Down Expand Up @@ -326,3 +337,12 @@ type URI_Comparator

## PRIVATE
Comparable.from (_:URI) = URI_Comparator

## PRIVATE
type Invalid_Query_String
## PRIVATE
Warning (query_string:Text)

## PRIVATE
to_display_text self =
"The query string contained invalid characters and has been URL-encoded ("+self.query_string+")."
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

/** Utilities for building and transforming URIs. */
public class URITransformer {

/** Removes query parameters from the given URI. */
public static URI removeQueryParameters(URI uri) {
return buildUriFromParts(
Expand Down Expand Up @@ -81,4 +80,21 @@ public static String encodeForQuery(String value) {
public static String encode(String value) {
return URLEncoder.encode(value, StandardCharsets.UTF_8).replace("+", "%20");
}

public static String encodeQuery(String rawQueryString) {
var parts = rawQueryString.split("&");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < parts.length; i++) {
if (i > 0) {
sb.append("&");
}
var keyValue = parts[i].split("=", 2);
sb.append(encodeForQuery(keyValue[0]));
if (keyValue.length > 1) {
sb.append("=");
sb.append(encodeForQuery(keyValue[1]));
}
}
return sb.toString();
}
}
10 changes: 10 additions & 0 deletions test/Base_Tests/src/Network/URI_Spec.enso
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Standard.Base.Enso_Cloud.Enso_Secret.Enso_Secret_Error
import Standard.Base.Errors.Common.Syntax_Error
import Standard.Base.Errors.Illegal_Argument.Illegal_Argument
import Standard.Base.Network.HTTP.Request.Request
import Standard.Base.Network.URI.Invalid_Query_String

from Standard.Test import all

Expand Down Expand Up @@ -66,6 +67,15 @@ add_specs suite_builder =
addr.raw_query.should_equal "%D0%9A%D0%BE%D0%B4"
addr.raw_fragment.should_equal Nothing

group_builder.specify "should automatically URI encode the query string if needed with a warning" <|
addr = URI.parse 'https://httpbin.org/get?foo=bar&baz="a&c=d"%20?'
addr.to_text . should_equal "https://httpbin.org/get?foo=bar&baz=%22a&c=d%22%2520%3F"
w1 = Problems.expect_only_warning Invalid_Query_String addr
w1.query_string . should_equal 'foo=bar&baz="a&c=d"%20?'

addr2 = URI.parse 'https://httpbin.org/get?c=d d=e=f&g=h'
addr2.to_text . should_equal 'https://httpbin.org/get?c=d+d%3De%3Df&g=h'

group_builder.specify "should return Syntax_Error when parsing invalid URI" <|
r = URI.parse "a b c"
r.should_fail_with Syntax_Error
Expand Down

0 comments on commit 4d6d6f2

Please sign in to comment.