f37bdb403a05b08344df25371326735e10a83563
[nit.git] / src / web / web_base.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
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
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
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.
14
15 # Base classes used by `nitweb`.
16 module web_base
17
18 import model::model_views
19 import model::model_json
20 import nitcorn
21
22 # Nitcorn server runned by `nitweb`.
23 #
24 # Usage:
25 #
26 # ~~~nitish
27 # var srv = new NitServer("localhost", 3000)
28 # srv.routes.add new Route("/", new MyAction)
29 # src.listen
30 # ~~~
31 class NitServer
32
33 # Host to bind.
34 var host: String
35
36 # Port to use.
37 var port: Int
38
39 # Routes knwon by the server.
40 var routes = new Array[Route]
41
42 # Start listen on `host:port`.
43 fun listen do
44 var iface = "{host}:{port}"
45 print "Launching server on http://{iface}/"
46
47 var vh = new VirtualHost(iface)
48 for route in routes do vh.routes.add route
49
50 var fac = new HttpFactory.and_libevent
51 fac.config.virtual_hosts.add vh
52 fac.run
53 end
54 end
55
56 # Specific nitcorn Action for nitweb.
57 class NitAction
58 super Action
59
60 # Link to the NitServer that runs this action.
61 var srv: NitServer
62
63 # Build a custom http response for errors.
64 fun render_error(code: Int, message: String): HttpResponse do
65 var response = new HttpResponse(code)
66 var tpl = new Template
67 tpl.add "<h1>Error {code}</h1>"
68 tpl.add "<pre><code>{message.html_escape}</code></pre>"
69 response.body = tpl.write_to_string
70 return response
71 end
72
73 # Render a view as a HttpResponse 200.
74 fun render_view(view: NitView): HttpResponse do
75 var response = new HttpResponse(200)
76 response.body = view.render(srv).write_to_string
77 return response
78 end
79
80 # Return a HttpResponse containing `json`.
81 fun render_json(json: Jsonable): HttpResponse do
82 var response = new HttpResponse(200)
83 response.body = json.to_json
84 return response
85 end
86 end
87
88 # Specific nitcorn Action that uses a Model
89 class ModelAction
90 super NitAction
91
92 # Model to use.
93 var model: Model
94
95 # Find the MEntity ` with `full_name`.
96 fun find_mentity(model: ModelView, full_name: nullable String): nullable MEntity do
97 if full_name == null then return null
98 return model.mentity_by_full_name(full_name.from_percent_encoding)
99 end
100
101 # Init the model view from the `req` uri parameters.
102 fun init_model_view(req: HttpRequest): ModelView do
103 var view = new ModelView(model)
104 var show_private = req.bool_arg("private") or else false
105 if not show_private then view.min_visibility = protected_visibility
106
107 view.include_fictive = req.bool_arg("fictive") or else false
108 view.include_empty_doc = req.bool_arg("empty-doc") or else true
109 view.include_test_suite = req.bool_arg("test-suite") or else false
110 view.include_attribute = req.bool_arg("attributes") or else true
111
112 return view
113 end
114 end
115
116 # A NitView is rendered by an action.
117 interface NitView
118 # Renders this view and returns something that can be written to a HTTP response.
119 fun render(srv: NitServer): Writable is abstract
120 end
121
122 redef class HttpRequest
123 # Does the client asked for a json formatted response?
124 #
125 # Checks the URL get parameter `?json=true`.
126 fun is_json_asked: Bool do return bool_arg("json") or else false
127 end