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 # Support module for the `nitrestful` tool and the `restful` annotation
17 # The `restful` annotation is applied on a method to assign it to an HTTP resource.
18 # The `restful` method must be a property of a subclass of `RestfulAction` and
19 # return an `HTTPResponse`.
20 # Once an instance of the class is assigned to a route, the method
21 # can be invoked as a resource under that route.
22 # The returned `HTTPResponse` will be sent back to the client.
24 # The arguments of the method must be deserializable.
25 # So use simple data types like `String`, `Int`, `Float`, etc.
26 # or any other `Serializable` class.
27 # The method is invoked only if all the arguments are correctly passed
28 # in the JSON format by the HTTP client.
29 # There is one exception, `String` arguments are returned as is,
30 # they don't need the surrounding `""`.
31 # If an argument is missing or there a format error, the `answer` method responds to the request.
32 # Arguments that are `nullable` are optional,
33 # if they are missing `null` is passed to the `restful` method.
35 # The annotation accepts three kinds of arguments, in any order:
37 # * String literals rename or add an alias for the HTTP resource.
38 # By default, the name of the HTTP resource is the name of the `restful` method.
39 # The first string literal replaces the default name,
40 # while additional string literals add aliases.
42 # * Ids such as `GET`, `POST`, `PUT` and `DELETE` restrict which HTTP methods
43 # are accepted. By default, all HTTP methods are accepted.
45 # * The `async` keyword triggers executing calls to this service asynchronously
46 # by the `thread_pool` attribute of the `RestfulAction`.
47 # By default, each call are executed on the same thread in a FIFO order.
49 # See the example at `lib/nitcorn/examples/restful_annot.nit` or
50 # a real world use case at `contrib/benitlux/src/server/benitlux_controller.nit`.
52 # The `restful` annotation is implemented by then `nitrestful` tool.
53 # To compile a module (`my_module.nit`) that uses the `restful` annotation:
55 # * Run `nitrestful my_module.nit` to produce `my_module_rest.nit`
56 # * Link `my_module_rest.nit` at compilation: `nitc my_module.nit -m my_module_rest.nit`.
57 module restful
is new_annotation
(restful
)
61 import pthreads
::threadpool
63 # Action with `restful` methods
67 redef fun answer
(request
, truncated_uri
) do return new HttpResponse(400)
69 # Deserialize `val` from JSON for a parameter typed by `static_type`
71 # Accepts `nullable String` for convenience, but returns `null` when `val == null`.
73 # This method is called by the code generated by `nitrestful`.
74 # It can be specialized to customize its behavior.
75 protected fun deserialize_arg
(val
: nullable String, static_type
: String): nullable Object
77 if val
== null then return null
79 var deserializer
= new JsonDeserializer(val
)
80 var obj
= deserializer
.deserialize
(static_type
)
82 if deserializer
.errors
.not_empty
then
83 print_error deserializer
.errors
.join
("\n")
90 # Thread pool used by methods annotated with `restful(async)`
91 var thread_pool
= new ThreadPool is writable
94 # Thread dedicated to a single `request`
95 abstract class RestfulTask
104 # Request that created this thread
105 var request
: HttpRequest
107 # Server handling the `request`
108 var http_server
: HttpServer
110 # Indirection to the real method in `action`
111 protected fun indirect_restful_method
: HttpResponse is abstract
115 var response
= indirect_restful_method
116 http_server
.respond response