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
)
26 # Platform specific service to execute `task` on the main/UI thread
27 fun run_on_ui_thread
(task
: Task) is abstract
30 # Thread executing an HTTP request and deserializing JSON asynchronously
32 # This class defines four methods acting on the main/UI thread,
33 # they should be implemented as needed:
38 class AsyncHttpRequest
41 # Root URI of the remote server
42 fun rest_server_uri
: String is abstract
44 # Action, or path, for this request within the `rest_server_uri`
45 fun rest_action
: String is abstract
47 # Should the response content be deserialized from JSON?
48 var deserialize_json
= true is writable
58 var uri
= rest_server_uri
/ rest_action
60 # Execute REST request
61 var rep
= uri
.http_get
63 app
.run_on_ui_thread
new RestRunnableOnFail(self, rep
.error
)
67 if not deserialize_json
then
68 app
.run_on_ui_thread
new RestRunnableOnLoad(self, rep
)
73 var deserializer
= new JsonDeserializer(rep
.value
)
74 var res
= deserializer
.deserialize
75 if deserializer
.errors
.not_empty
then
76 app
.run_on_ui_thread
new RestRunnableOnFail(self, deserializer
.errors
.first
)
79 app
.run_on_ui_thread
new RestRunnableOnLoad(self, res
)
83 # Prepare the UI or other parts of the program before executing the REST request
86 # Invoked when the HTTP request returned valid data
88 # If `deserialize_json`, the default behavior, this method is invoked only if deserialization was successful.
89 # In this case, `result` may be any deserialized object.
91 # Otherwise, if `not deserialize_json`, `result` contains the content of the response as a `String`.
92 fun on_load
(result
: nullable Object) do end
94 # Invoked when the HTTP request has failed and no data was received or deserialization failed
95 fun on_fail
(error
: Error) do print_error
"REST request '{rest_action}' failed with: {error}"
97 # Complete this request whether it was a success or not
102 # Execute an HTTP GET request synchronously at the URI `self`
105 # var response = "http://example.org/".http_get
106 # if response.is_error then
107 # print_error response.error
109 # print "HTTP status code: {response.code}"
110 # print response.value
113 private fun http_get
: HttpRequestResult is abstract
116 # Result of a call to `Text::http_get`
118 # Users should first check if `is_error` to use `error`.
119 # Otherwise they can use `value` to get the content of the response
120 # and `code` for the HTTP status code.
121 class HttpRequestResult
122 super MaybeError[String, Error]
124 # The HTTP status code, if any
125 var maybe_code
: nullable Int
128 # Require: `not is_error`
129 fun code
: Int do return maybe_code
.as(not null)
132 private abstract class HttpRequestTask
135 # `AsyncHttpRequest` to which send callbacks
136 var sender_thread
: AsyncHttpRequest
139 private class RestRunnableOnLoad
140 super HttpRequestTask
142 var res
: nullable Object
146 sender_thread
.on_load
(res
)
151 private class RestRunnableOnFail
152 super HttpRequestTask
158 sender_thread
.on_fail
(error
)