1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 # HTTP request services: `AsyncHttpRequest` and `Text::http_get`
20 import json
::serialization
22 import linux
::http_request
is conditional
(linux
)
23 import android
::http_request
is conditional
(android
)
24 import ios
::http_request
is conditional
(ios
)
27 # Platform specific service to execute `task` on the main/UI thread
28 fun run_on_ui_thread
(task
: Task) is abstract
31 # Thread executing an HTTP request asynchronously
33 # The request is sent to `rest_server_uri / rest_action`.
35 # If `deserialize_json`, the default behavior, the response is deserialized from JSON
37 # If `delay > 0.0`, sending the reqest is delayed by the given `delay` in seconds.
38 # It can be used to delay resending a request on error.
40 # Four callback methods act on the main/UI thread,
41 # they should be implemented as needed in subclasses:
46 class AsyncHttpRequest
49 # Root URI of the remote server
50 fun rest_server_uri
: String is abstract
52 # Action, or path, for this request within the `rest_server_uri`
53 fun rest_action
: String is abstract
55 # Should the response content be deserialized from JSON?
56 var deserialize_json
= true is writable
58 # Delay in seconds before sending this request
59 var delay
= 0.0 is writable
70 if delay
> 0.0 then delay
.sleep
72 var uri
= rest_server_uri
/ rest_action
74 # Execute REST request
75 var rep
= uri
.http_get
77 app
.run_on_ui_thread
new RestRunnableOnFail(self, rep
.error
)
81 if not deserialize_json
then
82 app
.run_on_ui_thread
new RestRunnableOnLoad(self, rep
)
87 var deserializer
= new JsonDeserializer(rep
.value
)
88 var res
= deserializer
.deserialize
89 if deserializer
.errors
.not_empty
then
90 app
.run_on_ui_thread
new RestRunnableOnFail(self, deserializer
.errors
.first
)
93 app
.run_on_ui_thread
new RestRunnableOnLoad(self, res
)
97 # Prepare the UI or other parts of the program before executing the REST request
100 # Invoked when the HTTP request returned valid data
102 # If `deserialize_json`, the default behavior, this method is invoked only if deserialization was successful.
103 # In this case, `result` may be any deserialized object.
105 # Otherwise, if `not deserialize_json`, `result` contains the content of the response as a `String`.
106 fun on_load
(result
: nullable Object) do end
108 # Invoked when the HTTP request has failed and no data was received or deserialization failed
109 fun on_fail
(error
: Error) do print_error
"REST request '{rest_action}' failed with: {error}"
111 # Complete this request whether it was a success or not
116 # Execute an HTTP GET request synchronously at the URI `self`
119 # var response = "http://example.org/".http_get
120 # if response.is_error then
121 # print_error response.error
123 # print "HTTP status code: {response.code}"
124 # print response.value
127 private fun http_get
: HttpRequestResult is abstract
130 # Result of a call to `Text::http_get`
132 # Users should first check if `is_error` to use `error`.
133 # Otherwise they can use `value` to get the content of the response
134 # and `code` for the HTTP status code.
135 class HttpRequestResult
136 super MaybeError[String, Error]
138 # The HTTP status code, if any
139 var maybe_code
: nullable Int
142 # Require: `not is_error`
143 fun code
: Int do return maybe_code
.as(not null)
146 private abstract class HttpRequestTask
149 # `AsyncHttpRequest` to which send callbacks
150 var sender_thread
: AsyncHttpRequest
153 private class RestRunnableOnLoad
154 super HttpRequestTask
156 var res
: nullable Object
160 sender_thread
.on_load
(res
)
165 private class RestRunnableOnFail
166 super HttpRequestTask
172 sender_thread
.on_fail
(error
)