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 and deserializing JSON asynchronously
33 # This class defines four methods acting on the main/UI thread,
34 # they should be implemented as needed:
39 class AsyncHttpRequest
42 # Root URI of the remote server
43 fun rest_server_uri
: String is abstract
45 # Action, or path, for this request within the `rest_server_uri`
46 fun rest_action
: String is abstract
48 # Should the response content be deserialized from JSON?
49 var deserialize_json
= true is writable
51 # Delay in seconds before sending this request
52 var delay
= 0.0 is writable
63 if delay
> 0.0 then delay
.sleep
65 var uri
= rest_server_uri
/ rest_action
67 # Execute REST request
68 var rep
= uri
.http_get
70 app
.run_on_ui_thread
new RestRunnableOnFail(self, rep
.error
)
74 if not deserialize_json
then
75 app
.run_on_ui_thread
new RestRunnableOnLoad(self, rep
)
80 var deserializer
= new JsonDeserializer(rep
.value
)
81 var res
= deserializer
.deserialize
82 if deserializer
.errors
.not_empty
then
83 app
.run_on_ui_thread
new RestRunnableOnFail(self, deserializer
.errors
.first
)
86 app
.run_on_ui_thread
new RestRunnableOnLoad(self, res
)
90 # Prepare the UI or other parts of the program before executing the REST request
93 # Invoked when the HTTP request returned valid data
95 # If `deserialize_json`, the default behavior, this method is invoked only if deserialization was successful.
96 # In this case, `result` may be any deserialized object.
98 # Otherwise, if `not deserialize_json`, `result` contains the content of the response as a `String`.
99 fun on_load
(result
: nullable Object) do end
101 # Invoked when the HTTP request has failed and no data was received or deserialization failed
102 fun on_fail
(error
: Error) do print_error
"REST request '{rest_action}' failed with: {error}"
104 # Complete this request whether it was a success or not
109 # Execute an HTTP GET request synchronously at the URI `self`
112 # var response = "http://example.org/".http_get
113 # if response.is_error then
114 # print_error response.error
116 # print "HTTP status code: {response.code}"
117 # print response.value
120 private fun http_get
: HttpRequestResult is abstract
123 # Result of a call to `Text::http_get`
125 # Users should first check if `is_error` to use `error`.
126 # Otherwise they can use `value` to get the content of the response
127 # and `code` for the HTTP status code.
128 class HttpRequestResult
129 super MaybeError[String, Error]
131 # The HTTP status code, if any
132 var maybe_code
: nullable Int
135 # Require: `not is_error`
136 fun code
: Int do return maybe_code
.as(not null)
139 private abstract class HttpRequestTask
142 # `AsyncHttpRequest` to which send callbacks
143 var sender_thread
: AsyncHttpRequest
146 private class RestRunnableOnLoad
147 super HttpRequestTask
149 var res
: nullable Object
153 sender_thread
.on_load
(res
)
158 private class RestRunnableOnFail
159 super HttpRequestTask
165 sender_thread
.on_fail
(error
)