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 # Base classes used by `nitweb`.
19 import popcorn
::pop_config
20 import popcorn
::pop_repos
21 import popcorn
::pop_json
23 import commands
::commands_http
24 import commands
::commands_json
25 import commands
::commands_html
31 redef fun default_db_name
do return "nitweb"
36 # MModule used to flatten model.
37 var mainmodule
: MModule
39 # Modelbuilder used to access sources.
40 var modelbuilder
: ModelBuilder
42 # The JSON API does not filter anything by default.
44 # So we can cache the model view.
47 # Catalog to pass to handlers.
48 var catalog
: Catalog is noinit
52 # This method should be called at nitweb startup.
55 var catalog
= new Catalog(modelbuilder
)
57 for p
in view
.mpackages
do
60 modelbuilder
.scan_group
(g
)
62 catalog
.deps
.add_node
(p
)
63 for gg
in p
.mgroups
do for m
in gg
.mmodules
do
64 for im
in m
.in_importation
.direct_greaters
do
66 if ip
== null or ip
== p
then continue
67 catalog
.deps
.add_edge
(p
, ip
)
72 for mpackage
in view
.mpackages
do
73 catalog
.package_page
(mpackage
)
74 catalog
.git_info
(mpackage
)
75 catalog
.mpackage_stats
(mpackage
)
77 self.catalog
= catalog
81 # Specific handler for the nitweb API.
82 abstract class APIHandler
86 var config
: NitwebConfig
88 # Find the MEntity ` with `full_name`.
89 fun find_mentity
(model
: ModelView, full_name
: nullable String): nullable MEntity do
90 if full_name
== null then return null
91 var mentity
= model
.mentity_by_full_name
(full_name
.from_percent_encoding
)
92 if mentity
== null then return null
93 if config
.view
.accept_mentity
(mentity
) then return mentity
97 # Try to load the mentity from uri with `/:id`.
99 # Send 400 if `:id` is null.
100 # Send 404 if no entity is found.
101 # Return null in both cases.
102 fun mentity_from_uri
(req
: HttpRequest, res
: HttpResponse): nullable MEntity do
103 var id
= req
.param
("id")
105 res
.api_error
(400, "Expected mentity full name")
108 var mentity
= find_mentity
(config
.view
, id
)
109 if mentity
== null then
110 res
.api_error
(404, "MEntity `{id}` not found")
115 # Paginate a json array
117 # Returns only a subset of `results` depending on the current `page` and the
118 # number of elements to return set by `limit`.
120 # Transforms the json array into an object:
130 fun paginate
(results
: JsonArray, count
: Int, page
, limit
: nullable Int): JsonObject do
131 if page
== null or page
<= 0 then page
= 1
132 if limit
== null or limit
<= 0 then limit
= 20
134 var max
= count
/ limit
138 else if page
> max
then
142 var lstart
= (page
- 1) * limit
144 if lstart
+ lend
> count
then lend
= count
- lstart
146 var res
= new JsonObject
149 res
["results"] = new JsonArray.from
(results
.subarray
(lstart
, lend
))
156 # A Rooter dedicated to APIHandlers.
161 var config
: NitwebConfig
164 redef class HttpResponse
166 # Return an HTTP error response with `status`
168 # Like the rest of the API, errors are formated as JSON:
170 # { "status": 404, "message": "Not found" }
172 fun api_error
(status
: Int, message
: String) do
173 json
(new APIError(status
, message
), status
)
176 # Return `serializable` as a json string
178 # Uses `req` to define serialization options.
179 fun api_json
(req
: HttpRequest, serializable
: nullable Serializable, status
: nullable Int, plain
, pretty
: nullable Bool) do
180 json
(serializable
, status
, plain
, req
.bool_arg
("pretty"))
184 # An error returned by the API.
186 # Can be serialized to json.
193 # Response error message
199 # URL to `self` within the web interface.
200 fun web_url
: String do return "/doc/" / full_name
202 # URL to `self` within the JSON api.
203 fun api_url
: String do return "/api/entity/" / full_name
205 redef fun core_serialize_to
(v
) do
207 v
.serialize_attribute
("web_url", web_url
)
208 v
.serialize_attribute
("api_url", api_url
)
212 redef class MEntityRef
213 redef fun core_serialize_to
(v
) do
215 v
.serialize_attribute
("web_url", mentity
.web_url
)
216 v
.serialize_attribute
("api_url", mentity
.api_url
)
220 redef class MClassDef
221 redef fun web_url
do return "{mclass.web_url}/lin#{full_name}"
225 redef fun web_url
do return "{mproperty.web_url}/lin#{full_name}"
229 redef fun core_serialize_to
(v
) do
231 v
.serialize_attribute
("web_url", web_url
)
232 v
.serialize_attribute
("api_url", api_url
)
236 redef class MClassType
237 redef var web_url
= mclass
.web_url
is lazy
238 redef var api_url
= mclass
.api_url
is lazy
241 redef class MNullableType
242 redef var web_url
= mtype
.web_url
is lazy
243 redef var api_url
= mtype
.api_url
is lazy
246 redef class MParameterType
247 redef var web_url
= mclass
.web_url
is lazy
248 redef var api_url
= mclass
.api_url
is lazy
251 redef class MVirtualType
252 redef var web_url
= mproperty
.web_url
is lazy
253 redef var api_url
= mproperty
.api_url
is lazy