X-Git-Url: http://nitlanguage.org diff --git a/lib/app/http_request.nit b/lib/app/http_request.nit index 9289f2b..07d4bf3 100644 --- a/lib/app/http_request.nit +++ b/lib/app/http_request.nit @@ -13,11 +13,28 @@ # limitations under the License. # HTTP request services: `AsyncHttpRequest` and `Text::http_get` +# +# ~~~nitish +# import app::http_request +# +# class MyHttpRequest +# super AsyncHttpRequest +# +# redef fun uri do return "http://example.com/" +# +# redef fun on_load(data, status) do print "Received: {data or else "null"}" +# +# redef fun on_fail(error) do print "Connection error: {error}" +# end +# +# var req = new MyHttpRequest +# req.start +# ~~~ module http_request import app_base import pthreads -import json::serialization +import json import linux::http_request is conditional(linux) import android::http_request is conditional(android) @@ -44,6 +61,8 @@ end # * `on_load` # * `on_fail` # * `after` +# +# See full example at `examples/http_request_example.nit`. abstract class AsyncHttpRequest super Thread @@ -82,19 +101,23 @@ abstract class AsyncHttpRequest return null end - if not deserialize_json then - app.run_on_ui_thread new RestRunnableOnLoad(self, rep) + if deserialize_json then + # Deserialize + var deserializer = new JsonDeserializer(rep.value) + var res = deserializer.deserialize + if deserializer.errors.not_empty then + app.run_on_ui_thread new RestRunnableOnFail(self, deserializer.errors.first) + else + app.run_on_ui_thread new RestRunnableOnLoad(self, res, rep.code) + end + else + # Return text data + app.run_on_ui_thread new RestRunnableOnLoad(self, rep.value, rep.code) return null end - # Deserialize - var deserializer = new JsonDeserializer(rep.value) - var res = deserializer.deserialize - if deserializer.errors.not_empty then - app.run_on_ui_thread new RestRunnableOnFail(self, deserializer.errors.first) - end + app.run_on_ui_thread new RestRunnableJoin(self) - app.run_on_ui_thread new RestRunnableOnLoad(self, res) return null end @@ -107,7 +130,7 @@ abstract class AsyncHttpRequest # In this case, `result` may be any deserialized object. # # Otherwise, if `not deserialize_json`, `result` contains the content of the response as a `String`. - fun on_load(result: nullable Object) do end + fun on_load(result: nullable Object, http_status_code: Int) do end # Invoked when the HTTP request has failed and no data was received or deserialization failed fun on_fail(error: Error) do print_error "HTTP request '{uri}' failed with: {error}" @@ -116,6 +139,28 @@ abstract class AsyncHttpRequest fun after do end end +# Simple `AsyncHttpRequest` where `uri` is an attribute +# +# Prints on communication errors and when the remote server returns an +# HTTP status code not in the 200s. +# +# This class can be instantiated to execute a request where the response is +# ignored by the application. Alternatively, it can be subclassed to implement +# `on_load`. +# +# ~~~nitish +# var request = new SimpleAsyncHttpRequest("http://example.com") +# request.start +# ~~~ +class SimpleAsyncHttpRequest + super AsyncHttpRequest + + redef var uri + + redef fun on_load(data, status) do if status < 200 or status >= 299 + then print_error "HTTP request '{uri}' received HTTP status code: {status}" +end + redef class Text # Execute an HTTP GET request synchronously at the URI `self` # @@ -143,6 +188,7 @@ class HttpRequestResult var maybe_code: nullable Int # The status code + # # Require: `not is_error` fun code: Int do return maybe_code.as(not null) end @@ -159,9 +205,11 @@ private class RestRunnableOnLoad var res: nullable Object + var code: Int + redef fun main do - sender_thread.on_load(res) + sender_thread.on_load(res, code) sender_thread.after end end @@ -177,3 +225,9 @@ private class RestRunnableOnFail sender_thread.after end end + +private class RestRunnableJoin + super HttpRequestTask + + redef fun main do sender_thread.join +end