X-Git-Url: http://nitlanguage.org diff --git a/lib/nitcorn/restful.nit b/lib/nitcorn/restful.nit index 158643a..a7580a4 100644 --- a/lib/nitcorn/restful.nit +++ b/lib/nitcorn/restful.nit @@ -13,10 +13,52 @@ # limitations under the License. # Support module for the `nitrestful` tool and the `restful` annotation +# +# The `restful` annotation is applied on a method to assign it to an HTTP resource. +# The `restful` method must be a property of a subclass of `RestfulAction` and +# return an `HTTPResponse`. +# Once an instance of the class is assigned to a route, the method +# can be invoked as a resource under that route. +# The returned `HTTPResponse` will be sent back to the client. +# +# The arguments of the method must be deserializable. +# So use simple data types like `String`, `Int`, `Float`, etc. +# or any other `Serializable` class. +# The method is invoked only if all the arguments are correctly passed +# in the JSON format by the HTTP client. +# There is one exception, `String` arguments are returned as is, +# they don't need the surrounding `""`. +# If an argument is missing or there a format error, the `answer` method responds to the request. +# Arguments that are `nullable` are optional, +# if they are missing `null` is passed to the `restful` method. +# +# The annotation accepts three kinds of arguments, in any order: +# +# * String literals rename or add an alias for the HTTP resource. +# By default, the name of the HTTP resource is the name of the `restful` method. +# The first string literal replaces the default name, +# while additional string literals add aliases. +# +# * Ids such as `GET`, `POST`, `PUT` and `DELETE` restrict which HTTP methods +# are accepted. By default, all HTTP methods are accepted. +# +# * The `async` keyword triggers executing calls to this service asynchronously +# by the `thread_pool` attribute of the `RestfulAction`. +# By default, each call are executed on the same thread in a FIFO order. +# +# See the example at `lib/nitcorn/examples/restful_annot.nit` or +# a real world use case at `contrib/benitlux/src/server/benitlux_controller.nit`. +# +# The `restful` annotation is implemented by then `nitrestful` tool. +# To compile a module (`my_module.nit`) that uses the `restful` annotation: +# +# * Run `nitrestful my_module.nit` to produce `my_module_rest.nit` +# * Link `my_module_rest.nit` at compilation: `nitc my_module.nit -m my_module_rest.nit`. module restful is new_annotation(restful) import nitcorn -import json::serialization +private import json +import pthreads::threadpool # Action with `restful` methods class RestfulAction @@ -24,18 +66,18 @@ class RestfulAction redef fun answer(request, truncated_uri) do return new HttpResponse(400) - # Service to deserialize arguments from JSON + # Deserialize `val` from JSON for a parameter typed by `static_type` # # Accepts `nullable String` for convenience, but returns `null` when `val == null`. # # This method is called by the code generated by `nitrestful`. # It can be specialized to customize its behavior. - protected fun deserialize_arg(val: nullable String): nullable Object + protected fun deserialize_arg(val: nullable String, static_type: String): nullable Object do if val == null then return null var deserializer = new JsonDeserializer(val) - var obj = deserializer.deserialize + var obj = deserializer.deserialize(static_type) if deserializer.errors.not_empty then print_error deserializer.errors.join("\n") @@ -44,4 +86,34 @@ class RestfulAction return obj end + + # Thread pool used by methods annotated with `restful(async)` + var thread_pool = new ThreadPool is writable +end + +# Thread dedicated to a single `request` +abstract class RestfulTask + super Task + + # Type of `action` + type A: RestfulAction + + # Receiver action + var action: A + + # Request that created this thread + var request: HttpRequest + + # Server handling the `request` + var http_server: HttpServer + + # Indirection to the real method in `action` + protected fun indirect_restful_method: HttpResponse is abstract + + redef fun main + do + var response = indirect_restful_method + http_server.respond response + http_server.close + end end