Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge URI_With_Query into URI, extend API of URI #8591

Merged
merged 28 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
fc88c1d
remove URI_With_Query from types
radeusgd Dec 15, 2023
28be69f
checkpoint
radeusgd Dec 15, 2023
d982c3d
report skipped whole groups of tests
radeusgd Dec 15, 2023
3bfc7e8
WIP
radeusgd Dec 15, 2023
3b6a0eb
WIP...
radeusgd Dec 15, 2023
0a92444
checkpoint
radeusgd Dec 16, 2023
1b56436
Java side of secret resolution, building an URI
radeusgd Dec 18, 2023
1efb0f8
updating how metadata is fetched to be more robust
radeusgd Dec 18, 2023
489182b
fixes, comaprator, removed old URI_With_Query.enso
radeusgd Dec 18, 2023
ca9c0ef
fixing comparator
radeusgd Dec 18, 2023
6e5b01a
fixes
radeusgd Dec 19, 2023
148205b
more edge cases
radeusgd Dec 19, 2023
4d3df47
tests for user info handling, fixing some edge cases
radeusgd Dec 19, 2023
c17f81c
move test, add edge case
radeusgd Dec 19, 2023
f7bedb5
add tests for /, reset_query_arguments, set_fragment
radeusgd Dec 19, 2023
86bc671
checkpoint
radeusgd Dec 19, 2023
4aca9df
implementing URI transformation - extend path, reset query
radeusgd Dec 19, 2023
cccf198
fixing edge cases
radeusgd Dec 19, 2023
c64a22a
more edge cases!
radeusgd Dec 19, 2023
6c51f9e
split test
radeusgd Dec 19, 2023
ccde4c6
docs
radeusgd Dec 19, 2023
0f5e3d6
javafmt
radeusgd Dec 19, 2023
d853c14
remove file after rebase
radeusgd Dec 20, 2023
2f4566b
Merge branch 'develop' into wip/radeusgd/8544-merge-uri-with-query
radeusgd Dec 21, 2023
065c601
CR: newline
radeusgd Dec 21, 2023
447747c
docs
radeusgd Dec 21, 2023
4d5b2f6
CR: suggestions - refactor: rename Enso_Secret.to_java_value and move…
radeusgd Dec 21, 2023
b276703
better split of test groups
radeusgd Dec 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions distribution/lib/Standard/Base/0.0.0-dev/src/Data.enso
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import project.Network.HTTP.Request.Request
import project.Network.HTTP.Request_Body.Request_Body
import project.Network.HTTP.Request_Error
import project.Network.URI.URI
import project.Network.URI_With_Query.URI_With_Query
import project.Nothing.Nothing
import project.System.File.File
from project.Data.Boolean import Boolean, False, True
Expand Down Expand Up @@ -177,8 +176,8 @@ list_directory directory name_filter=Nothing recursive=False =
import Standard.Base.Data
file = enso_project.data / "spreadsheet.xls"
Data.fetch URL . body . to_file file
fetch : (URI | URI_With_Query | Text) -> HTTP_Method -> Vector (Header | Pair Text Text) -> Boolean -> Any ! Request_Error | HTTP_Error
fetch (uri:(URI | URI_With_Query | Text)) (method:HTTP_Method=HTTP_Method.Get) (headers:(Vector (Header | Pair Text Text))=[]) (try_auto_parse_response:Boolean=True) =
fetch : (URI | Text) -> HTTP_Method -> Vector (Header | Pair Text Text) -> Boolean -> Any ! Request_Error | HTTP_Error
fetch (uri:(URI | Text)) (method:HTTP_Method=HTTP_Method.Get) (headers:(Vector (Header | Pair Text Text))=[]) (try_auto_parse_response:Boolean=True) =
response = HTTP.fetch uri method headers
if try_auto_parse_response.not then response.with_materialized_body else
## We cannot catch decoding errors here and fall-back to the raw response
Expand Down Expand Up @@ -305,8 +304,8 @@ fetch (uri:(URI | URI_With_Query | Text)) (method:HTTP_Method=HTTP_Method.Get) (
test_file = enso_project.data / "sample.txt"
form_data = Map.from_vector [["key", "val"], ["a_file", test_file]]
response = Data.post url_post (Request_Body.Form_Data form_data url_encoded=True)
post : (URI | URI_With_Query | Text) -> Request_Body -> HTTP_Method -> Vector (Header | Pair Text Text) -> Boolean -> Any ! Request_Error | HTTP_Error
post (uri:(URI | URI_With_Query | Text)) (body:Request_Body=Request_Body.Empty) (method:HTTP_Method=HTTP_Method.Post) (headers:(Vector (Header | Pair Text Text))=[]) (try_auto_parse_response:Boolean=True) =
post : (URI | Text) -> Request_Body -> HTTP_Method -> Vector (Header | Pair Text Text) -> Boolean -> Any ! Request_Error | HTTP_Error
post (uri:(URI | Text)) (body:Request_Body=Request_Body.Empty) (method:HTTP_Method=HTTP_Method.Post) (headers:(Vector (Header | Pair Text Text))=[]) (try_auto_parse_response:Boolean=True) =
response = HTTP.post uri body method headers
if try_auto_parse_response.not then response.with_materialized_body else
response.decode if_unsupported=response.with_materialized_body
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import project.Data.Enso_Cloud.Enso_Secret.Enso_Secret
import project.Data.Pair.Pair
import project.Data.Text.Text
import project.Error.Error
Expand All @@ -8,6 +9,7 @@ import project.System.Environment
import project.System.File.File

polyglot java import org.enso.base.enso_cloud.AuthenticationProvider
polyglot java import org.enso.base.enso_cloud.HideableValue

## PRIVATE
cloud_root_uri = "" + AuthenticationProvider.getAPIRootURI
Expand Down Expand Up @@ -50,3 +52,9 @@ type Not_Logged_In
## PRIVATE
to_display_text : Text
to_display_text self = "Not logged into Enso cloud. Please log in and restart."

## PRIVATE
as_hideable_value : Text | Enso_Secret | Nothing -> HideableValue
as_hideable_value (value : Text | Enso_Secret) = case value of
text : Text -> HideableValue.PlainValue.new text
secret : Enso_Secret -> HideableValue.SecretValue.new secret.id
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import project.Network.HTTP.Header.Header
import project.Network.HTTP.HTTP_Method.HTTP_Method
import project.Network.HTTP.Request_Body.Request_Body
import project.Network.URI.URI
import project.Network.URI_With_Query.URI_With_Query
from project.Data.Boolean import Boolean, False, True

## ALIAS parse_uri, uri from text
Expand Down Expand Up @@ -43,23 +42,6 @@ URI.fetch : HTTP_Method -> Vector (Header | Pair Text Text) -> Boolean -> Any
URI.fetch self (method:HTTP_Method=HTTP_Method.Get) headers=[] try_auto_parse_response=True =
Data.fetch self method headers try_auto_parse_response

## ALIAS download, http get
GROUP Input
Fetches from the URI and returns the response, parsing the body if the
content-type is recognised. Returns an error if the status code does not
represent a successful response.

Arguments:
- method: The HTTP method to use. Must be one of `HTTP_Method.Get`,
`HTTP_Method.Head`, `HTTP_Method.Delete`, `HTTP_Method.Options`.
Defaults to `HTTP_Method.Get`.
- headers: The headers to send with the request. Defaults to an empty vector.
- try_auto_parse_response: If successful should the body be attempted to be
parsed to an Enso native object.
URI_With_Query.fetch : HTTP_Method -> Vector (Header | Pair Text Text) -> Boolean -> Any
URI_With_Query.fetch self (method:HTTP_Method=HTTP_Method.Get) headers=[] try_auto_parse_response=True =
Data.fetch self method headers try_auto_parse_response

## ALIAS upload, http post
GROUP Input
Writes the provided data to the provided URI. Returns the response,
Expand Down Expand Up @@ -99,43 +81,3 @@ URI_With_Query.fetch self (method:HTTP_Method=HTTP_Method.Get) headers=[] try_au
URI.post : Request_Body -> HTTP_Method -> Vector (Header | Pair Text Text) -> Boolean -> Any
URI.post self (body:Request_Body=Request_Body.Empty) (method:HTTP_Method=HTTP_Method.Post) (headers:(Vector (Header | Pair Text Text))=[]) (try_auto_parse_response:Boolean=True) =
Data.post self body method headers try_auto_parse_response

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a simplification.

## ALIAS upload, http post
GROUP Input
Writes the provided data to the provided URI. Returns the response,
parsing the body if the content-type is recognised. Returns an error if the
status code does not represent a successful response.

Arguments:
- body: The data to write. See `Supported Body Types` below.
- method: The HTTP method to use. Must be one of `HTTP_Method.Post`,
`HTTP_Method.Put`, `HTTP_Method.Patch`. Defaults to `HTTP_Method.Post`.
- headers: The headers to send with the request. Defaults to an empty vector.
- try_auto_parse_response: If successful should the body be attempted to be
parsed to an Enso native object.

! Specifying Content Types

If the `body` parameter specifies an explicit content type, then it is an
error to also specify additional `Content-Type` headers in the `headers`
parameter. (It is not an error to specify multiple `Content-Type` values in
`headers`, however.)

! Supported Body Types

- Request_Body.Text: Sends a text string, with optional encoding and content
type.
- Request_Body.Json: Sends an Enso object, after converting it to JSON.
- Request_Body.Binary: Sends a file.
- Request_Body.Form_Data: Sends a form encoded as key/value pairs. The keys
must be `Text`, and the values must be `Text` or `File`.
- Request_Body.Empty: Sends an empty body.

Additionally, the following types are allowed as the `body` parameter:

- Text: shorthand for `Request_Body.Text that_text`.
- File: shorthand for `Request_Body.Binary that_file`.
- Any other Enso object: shorthand for `Request_Body.Json that_object`.
URI_With_Query.post : Request_Body -> HTTP_Method -> Vector (Header | Pair Text Text) -> Boolean -> Any
URI_With_Query.post self (body:Request_Body=Request_Body.Empty) (method:HTTP_Method=HTTP_Method.Post) (headers:(Vector (Header | Pair Text Text))=[]) (try_auto_parse_response:Boolean=True) =
Data.post self body method headers try_auto_parse_response
29 changes: 7 additions & 22 deletions distribution/lib/Standard/Base/0.0.0-dev/src/Network/HTTP.enso
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import project.Network.HTTP.Request_Body.Request_Body
import project.Network.HTTP.Response.Response
import project.Network.Proxy.Proxy
import project.Network.URI.URI
import project.Network.URI_With_Query.URI_With_Query
import project.Nothing.Nothing
import project.Panic.Panic
import project.Runtime.Context
Expand All @@ -36,7 +35,6 @@ polyglot java import java.net.http.HttpRequest.BodyPublisher
polyglot java import java.net.InetSocketAddress
polyglot java import java.net.ProxySelector
polyglot java import java.nio.file.Path
polyglot java import org.enso.base.enso_cloud.EnsoKeyValuePair
polyglot java import org.enso.base.enso_cloud.EnsoSecretHelper
polyglot java import org.enso.base.net.http.MultipartBodyBuilder
polyglot java import org.enso.base.net.http.UrlencodedBodyBuilder
Expand Down Expand Up @@ -118,39 +116,26 @@ type HTTP
boundary = body_publisher_and_boundary.second
boundary_header_list = if boundary.is_nothing then [] else [Header.multipart_form_data boundary]
all_headers = headers + boundary_header_list
mapped_headers = all_headers.map on_problems=No_Wrap.Value h-> case h.value of
_ : Enso_Secret -> EnsoKeyValuePair.ofSecret h.name h.value.id
_ -> EnsoKeyValuePair.ofText h.name h.value

# Get uri and resolve query arguments
uri_args = case req.uri of
_ : Text -> [req.uri.to_uri, []]
_ : URI -> [req.uri, []]
_ : URI_With_Query ->
mapped_arguments = req.uri.parameters.map arg-> case arg.second of
_ : Enso_Secret -> EnsoKeyValuePair.ofSecret arg.first arg.second.id
_ : Text -> EnsoKeyValuePair.ofText arg.first arg.second
_ -> Error.throw (Illegal_Argument.Error "Invalid query argument type - all values must be Vector or Pair.")
[req.uri.uri, mapped_arguments]

response = Response.Value (EnsoSecretHelper.makeRequest self.internal_http_client builder uri_args.first.internal_uri uri_args.second mapped_headers)
mapped_headers = all_headers.map on_problems=No_Wrap.Value .to_java_pair

response = Response.Value (EnsoSecretHelper.makeRequest self.internal_http_client builder req.uri.to_java_representation mapped_headers)
if error_on_failure_code.not || response.code.is_success then response else
body = response.body.decode_as_text.catch Any _-> ""
message = if body.is_empty then Nothing else body
Error.throw (HTTP_Error.Status_Error response.code message response.uri)

## PRIVATE
Static helper for get-like methods
fetch : (URI | URI_With_Query | Text) -> HTTP_Method -> Vector (Header | Pair Text Text) -> Response ! Request_Error | HTTP_Error
fetch (uri:(URI | URI_With_Query | Text)) (method:HTTP_Method=HTTP_Method.Get) (headers:(Vector (Header | Pair Text Text))=[]) =
fetch : (URI | Text) -> HTTP_Method -> Vector (Header | Pair Text Text) -> Response ! Request_Error | HTTP_Error
fetch (uri:(URI | Text)) (method:HTTP_Method=HTTP_Method.Get) (headers:(Vector (Header | Pair Text Text))=[]) =
check_method fetch_methods method <|
request = Request.new method uri (parse_headers headers) Request_Body.Empty
HTTP.new.request request

## PRIVATE
Static helper for post-like methods
post : (URI | URI_With_Query | Text) -> Request_Body -> HTTP_Method -> Vector (Header | Pair Text Text) -> Response ! Request_Error | HTTP_Error
post (uri:(URI | URI_With_Query | Text)) (body:Request_Body=Request_Body.Empty) (method:HTTP_Method=HTTP_Method.Post) (headers:(Vector (Header | Pair Text Text))=[]) =
post : (URI | Text) -> Request_Body -> HTTP_Method -> Vector (Header | Pair Text Text) -> Response ! Request_Error | HTTP_Error
post (uri:(URI | Text)) (body:Request_Body=Request_Body.Empty) (method:HTTP_Method=HTTP_Method.Post) (headers:(Vector (Header | Pair Text Text))=[]) =
check_method post_methods method <|
request = Request.new method uri (parse_headers headers) body
HTTP.new.request request
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import project.Any.Any
import project.Data.Text.Text
import project.Network.HTTP.HTTP_Status_Code.HTTP_Status_Code
import project.Network.URI.URI
import project.Network.URI_With_Query.URI_With_Query
import project.Nothing.Nothing
import project.Panic.Panic

Expand All @@ -15,15 +14,15 @@ type HTTP_Error
Arguments:
- uri: The uri that couldn't be read.
- message: The message for the error.
IO_Error (uri:URI|URI_With_Query) (message:Text)
IO_Error (uri:URI) (message:Text)

## An error indicating that a non-200 status code was returned.

Arguments:
- status_code: The status code that was returned.
- message: The message for the error, if it was able to be read.
- uri: The uri that couldn't be read.
Status_Error (status_code:HTTP_Status_Code) (message:Text|Nothing) (uri:URI|URI_With_Query)
Status_Error (status_code:HTTP_Status_Code) (message:Text|Nothing) (uri:URI)

## PRIVATE
Convert the HTTP_Error to a human-readable format.
Expand All @@ -39,6 +38,6 @@ type HTTP_Error

## PRIVATE
Utility method for running an action with Java exceptions mapping.
handle_java_exceptions (uri:URI|URI_With_Query) ~action =
handle_java_exceptions (uri:URI) ~action =
Panic.catch IOException action caught_panic->
HTTP_Error.IO_Error uri ("An IO error has occurred: " + caught_panic.payload.to_text)
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import project.Data.Enso_Cloud.Enso_Secret.Enso_Secret
import project.Data.Enso_Cloud.Utils as Cloud_Utils
import project.Data.Numbers.Integer
import project.Data.Text.Encoding.Encoding
import project.Data.Text.Text
Expand All @@ -8,6 +9,7 @@ from project.Data.Ordering import all
from project.Data.Text.Extensions import all

polyglot java import java.util.Base64
polyglot java import org.graalvm.collections.Pair as Java_Pair

type Header
## PRIVATE
Expand Down Expand Up @@ -191,6 +193,11 @@ type Header
content_type_header_name : Text
content_type_header_name = "Content-Type"

## PRIVATE
to_java_pair : Java_Pair
to_java_pair self =
Java_Pair.create self.name (Cloud_Utils.as_hideable_value self.value)

## PRIVATE
type Header_Comparator
## PRIVATE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import project.Network.HTTP.Header.Header
import project.Network.HTTP.HTTP_Method.HTTP_Method
import project.Network.HTTP.Request_Body.Request_Body
import project.Network.URI.URI
import project.Network.URI_With_Query.URI_With_Query
import project.Nothing.Nothing
import project.Panic.Panic
from project.Data.Boolean import Boolean, False, True
Expand All @@ -33,8 +32,8 @@ type Request
import Standard.Base.Network.URI.URI

example_new = Request.new Method.Post (URI.parse "http://example.com")
new : HTTP_Method -> (URI | URI_With_Query) -> Vector Header -> Request_Body -> Request
new (method:HTTP_Method) (url:(URI | URI_With_Query)) (headers:(Vector Header)=[]) (body:Request_Body=Request_Body.Empty) =
new : HTTP_Method -> URI -> Vector Header -> Request_Body -> Request
new (method:HTTP_Method) (url:URI) (headers:(Vector Header)=[]) (body:Request_Body=Request_Body.Empty) =
Request.Value method url headers body

## Create an Options request.
Expand All @@ -48,7 +47,7 @@ type Request
import Standard.Base.Network.URI.URI

example_options = Request.options (URI.parse "http://example.com")
options : (Text | URI | URI_With_Query) -> Vector -> Request
options : (Text | URI) -> Vector -> Request
options url (headers = []) = Request.new HTTP_Method.Options url headers

## Create a Get request.
Expand All @@ -64,7 +63,7 @@ type Request
import Standard.Base.Network.URI.URI

example_get = Request.get (URI.parse "http://example.com")
get : (Text | URI | URI_With_Query) -> Vector -> Request
get : (Text | URI) -> Vector -> Request
get url (headers = []) = Request.new HTTP_Method.Get url headers

## Create a Head request.
Expand All @@ -80,7 +79,7 @@ type Request
import Standard.Base.Network.URI.URI

example_head = Request.head (URI.parse "http://example.com")
head : (Text | URI | URI_With_Query) -> Vector -> Request
head : (Text | URI) -> Vector -> Request
head url (headers = []) = Request.new HTTP_Method.Head url headers

## Create a Post request.
Expand All @@ -98,7 +97,7 @@ type Request
import Standard.Base.Network.URI.URI

example_post = Request.post (URI.parse "http://example.com") Request_Body.Empty
post : (Text | URI | URI_With_Query) -> Request_Body -> Vector -> Request
post : (Text | URI) -> Request_Body -> Vector -> Request
post url body (headers = []) = Request.new HTTP_Method.Post url headers body

## Create a Put request.
Expand All @@ -116,7 +115,7 @@ type Request
import Standard.Base.Network.URI.URI

example_put = Request.put (URI.parse "http://example.com") Request_Body.Empty
put : (Text | URI | URI_With_Query) -> Request_Body -> Vector -> Request
put : (Text | URI) -> Request_Body -> Vector -> Request
put url body (headers = []) = Request.new HTTP_Method.Put url headers body

## Create a Delete request.
Expand All @@ -132,7 +131,7 @@ type Request
import Standard.Base.Network.URI.URI

example_delete = Request.delete (URI.parse "http://example.com")
delete : (Text | URI | URI_With_Query) -> Vector -> Request
delete : (Text | URI) -> Vector -> Request
delete url (headers = []) = Request.new HTTP_Method.Delete url headers

## PRIVATE
Expand All @@ -144,7 +143,7 @@ type Request
- uri: The URI for the request.
- headers: A vector containing headers for the request.
- body: The body of the request.
Value method uri headers body
Value (method : HTTP_Method) (uri : URI) (headers : Vector) (body : Request_Body)

## Sets the header for the request.

Expand Down
Loading
Loading