Mercurial > libervia-web
annotate src/server/pages.py @ 1049:6b1e1f13a299
pages: do not log error if there is not template and render method, but redirect is used
author | Goffi <goffi@goffi.org> |
---|---|
date | Thu, 25 Jan 2018 07:54:27 +0100 |
parents | 688b52897ba0 |
children | cdf0ebed9db7 |
rev | line source |
---|---|
331
06a48d805547
server side: make Libervia a Twisted plugin, and add it the --port argument + add a config file for the port.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
330
diff
changeset
|
1 #!/usr/bin/python |
06a48d805547
server side: make Libervia a Twisted plugin, and add it the --port argument + add a config file for the port.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
330
diff
changeset
|
2 # -*- coding: utf-8 -*- |
06a48d805547
server side: make Libervia a Twisted plugin, and add it the --port argument + add a config file for the port.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
330
diff
changeset
|
3 |
339
2067d6241927
fixed docstrings wrong usage for licence informations
Goffi <goffi@goffi.org>
parents:
336
diff
changeset
|
4 # Libervia: a Salut à Toi frontend |
964
fd4eae654182
misc: date update (yes it's a bit late :p )
Goffi <goffi@goffi.org>
parents:
962
diff
changeset
|
5 # Copyright (C) 2011-2017 Jérôme Poisson <goffi@goffi.org> |
331
06a48d805547
server side: make Libervia a Twisted plugin, and add it the --port argument + add a config file for the port.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
330
diff
changeset
|
6 |
339
2067d6241927
fixed docstrings wrong usage for licence informations
Goffi <goffi@goffi.org>
parents:
336
diff
changeset
|
7 # This program is free software: you can redistribute it and/or modify |
2067d6241927
fixed docstrings wrong usage for licence informations
Goffi <goffi@goffi.org>
parents:
336
diff
changeset
|
8 # it under the terms of the GNU Affero General Public License as published by |
2067d6241927
fixed docstrings wrong usage for licence informations
Goffi <goffi@goffi.org>
parents:
336
diff
changeset
|
9 # the Free Software Foundation, either version 3 of the License, or |
2067d6241927
fixed docstrings wrong usage for licence informations
Goffi <goffi@goffi.org>
parents:
336
diff
changeset
|
10 # (at your option) any later version. |
331
06a48d805547
server side: make Libervia a Twisted plugin, and add it the --port argument + add a config file for the port.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
330
diff
changeset
|
11 |
339
2067d6241927
fixed docstrings wrong usage for licence informations
Goffi <goffi@goffi.org>
parents:
336
diff
changeset
|
12 # This program is distributed in the hope that it will be useful, |
2067d6241927
fixed docstrings wrong usage for licence informations
Goffi <goffi@goffi.org>
parents:
336
diff
changeset
|
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of |
2067d6241927
fixed docstrings wrong usage for licence informations
Goffi <goffi@goffi.org>
parents:
336
diff
changeset
|
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2067d6241927
fixed docstrings wrong usage for licence informations
Goffi <goffi@goffi.org>
parents:
336
diff
changeset
|
15 # GNU Affero General Public License for more details. |
331
06a48d805547
server side: make Libervia a Twisted plugin, and add it the --port argument + add a config file for the port.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
330
diff
changeset
|
16 |
339
2067d6241927
fixed docstrings wrong usage for licence informations
Goffi <goffi@goffi.org>
parents:
336
diff
changeset
|
17 # You should have received a copy of the GNU Affero General Public License |
2067d6241927
fixed docstrings wrong usage for licence informations
Goffi <goffi@goffi.org>
parents:
336
diff
changeset
|
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
331
06a48d805547
server side: make Libervia a Twisted plugin, and add it the --port argument + add a config file for the port.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
330
diff
changeset
|
19 from twisted.web import server |
858 | 20 from twisted.web import resource as web_resource |
21 from twisted.web import util as web_util | |
984
f0fc28b3bd1e
server: moved LiberviaPage code in its own module
Goffi <goffi@goffi.org>
parents:
980
diff
changeset
|
22 from twisted.internet import defer |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
23 from twisted.words.protocols.jabber import jid |
917 | 24 from twisted.python import failure |
449
981ed669d3b3
/!\ reorganize all the file hierarchy, move the code and launching script to src:
souliane <souliane@mailoo.org>
parents:
448
diff
changeset
|
25 |
984
f0fc28b3bd1e
server: moved LiberviaPage code in its own module
Goffi <goffi@goffi.org>
parents:
980
diff
changeset
|
26 from sat.core.i18n import _ |
f0fc28b3bd1e
server: moved LiberviaPage code in its own module
Goffi <goffi@goffi.org>
parents:
980
diff
changeset
|
27 from sat.core import exceptions |
f0fc28b3bd1e
server: moved LiberviaPage code in its own module
Goffi <goffi@goffi.org>
parents:
980
diff
changeset
|
28 from sat.tools.common import uri as common_uri |
1019
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
29 from sat.tools import utils |
438
582c435dab6b
server side: new log system is used
Goffi <goffi@goffi.org>
parents:
435
diff
changeset
|
30 from sat.core.log import getLogger |
582c435dab6b
server side: new log system is used
Goffi <goffi@goffi.org>
parents:
435
diff
changeset
|
31 log = getLogger(__name__) |
984
f0fc28b3bd1e
server: moved LiberviaPage code in its own module
Goffi <goffi@goffi.org>
parents:
980
diff
changeset
|
32 from libervia.server.constants import Const as C |
f0fc28b3bd1e
server: moved LiberviaPage code in its own module
Goffi <goffi@goffi.org>
parents:
980
diff
changeset
|
33 from libervia.server import session_iface |
f0fc28b3bd1e
server: moved LiberviaPage code in its own module
Goffi <goffi@goffi.org>
parents:
980
diff
changeset
|
34 from libervia.server.utils import quote |
682
e6bb64bd6b4d
server side: implemented methods to get SàT and Libervia versions
Goffi <goffi@goffi.org>
parents:
679
diff
changeset
|
35 import libervia |
331
06a48d805547
server side: make Libervia a Twisted plugin, and add it the --port argument + add a config file for the port.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
330
diff
changeset
|
36 |
995 | 37 from collections import namedtuple |
38 import uuid | |
984
f0fc28b3bd1e
server: moved LiberviaPage code in its own module
Goffi <goffi@goffi.org>
parents:
980
diff
changeset
|
39 import os.path |
f0fc28b3bd1e
server: moved LiberviaPage code in its own module
Goffi <goffi@goffi.org>
parents:
980
diff
changeset
|
40 import urllib |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
41 import time |
1019
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
42 import hashlib |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
43 |
995 | 44 WebsocketMeta = namedtuple("WebsocketMeta", ('url', 'token', 'debug')) |
45 | |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
46 |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
47 |
1018 | 48 class CacheBase(object): |
49 | |
50 def __init__(self): | |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
51 self._created = time.time() |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
52 self._last_access = self._created |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
53 |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
54 @property |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
55 def created(self): |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
56 return self._created |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
57 |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
58 @property |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
59 def last_access(self): |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
60 return self._last_access |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
61 |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
62 @last_access.setter |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
63 def last_access(self, timestamp): |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
64 self._last_access = timestamp |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
65 |
1018 | 66 |
67 class CachePage(CacheBase): | |
68 | |
69 def __init__(self, rendered): | |
70 super(CachePage, self).__init__() | |
71 self._created = time.time() | |
72 self._last_access = self._created | |
73 self._rendered = rendered | |
1019
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
74 self._hash = hashlib.sha256(rendered).hexdigest() |
1018 | 75 |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
76 @property |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
77 def rendered(self): |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
78 return self._rendered |
331
06a48d805547
server side: make Libervia a Twisted plugin, and add it the --port argument + add a config file for the port.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
330
diff
changeset
|
79 |
1019
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
80 @property |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
81 def hash(self): |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
82 return self._hash |
331
06a48d805547
server side: make Libervia a Twisted plugin, and add it the --port argument + add a config file for the port.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
330
diff
changeset
|
83 |
1018 | 84 |
85 class CacheURL(CacheBase): | |
86 | |
87 def __init__(self, request): | |
88 super(CacheURL, self).__init__() | |
89 try: | |
90 self._data = request.data.copy() | |
91 except AttributeError: | |
92 self._data = {} | |
93 self._template_data = request.template_data.copy() | |
94 self._prepath = request.prepath[:] | |
95 self._postpath = request.postpath[:] | |
96 del self._template_data['csrf_token'] | |
97 | |
98 def use(self, request): | |
99 self.last_access = time.time() | |
100 request.data = self._data.copy() | |
101 request.template_data.update(self._template_data) | |
102 request.prepath = self._prepath[:] | |
103 request.postpath = self._postpath[:] | |
104 | |
105 | |
917 | 106 class LiberviaPage(web_resource.Resource): |
107 isLeaf = True # we handle subpages ourself | |
108 named_pages = {} | |
925 | 109 uri_callbacks = {} |
995 | 110 signals_handlers = {} |
980
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
111 pages_redirects = {} |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
112 cache = {} |
1018 | 113 cached_urls = {} |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
114 # Set of tuples (service/node/sub_id) of nodes subscribed for caching |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
115 # sub_id can be empty string if not handled by service |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
116 cache_pubsub_sub = set() |
990
6daa59d44ee2
pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents:
985
diff
changeset
|
117 main_menu = None |
917 | 118 |
995 | 119 def __init__(self, host, root_dir, url, name=None, redirect=None, access=None, dynamic=False, parse_url=None, |
120 prepare_render=None, render=None, template=None, | |
1018 | 121 on_data_post=None, on_data=None, on_signal=None, |
122 url_cache=False): | |
917 | 123 """initiate LiberviaPages |
124 | |
125 LiberviaPages are the main resources of Libervia, using easy to set python files | |
126 The arguments are the variables found in page_meta.py | |
127 @param host(Libervia): the running instance of Libervia | |
962 | 128 @param root_dir(unicode): aboslute file path of the page |
129 @param url(unicode): relative URL to the page | |
130 this URL may not be valid, as pages may require path arguments | |
917 | 131 @param name(unicode, None): if not None, a unique name to identify the page |
132 can then be used for e.g. redirection | |
923
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
133 "/" is not allowed in names (as it can be used to construct URL paths) |
962 | 134 @param redirect(unicode, None): if not None, this page will be redirected. A redirected |
923
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
135 parameter is used as in self.pageRedirect. parse_url will not be skipped |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
136 using this redirect parameter is called "full redirection" |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
137 using self.pageRedirect is called "partial redirection" (because some rendering method |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
138 can still be used, e.g. parse_url) |
917 | 139 @param access(unicode, None): permission needed to access the page |
140 None means public access. | |
141 Pages inherit from parent pages: e.g. if a "settings" page is restricted to admins, | |
142 and if "settings/blog" is public, it still can only be accessed by admins. | |
143 see C.PAGES_ACCESS_* for details | |
995 | 144 @param dynamic(bool): if True, activate websocket for bidirectional communication |
917 | 145 @param parse_url(callable, None): if set it will be called to handle the URL path |
146 after this method, the page will be rendered if noting is left in path (request.postpath) | |
147 else a the request will be transmitted to a subpage | |
148 @param prepare_render(callable, None): if set, will be used to prepare the rendering | |
149 that often means gathering data using the bridge | |
150 @param render(callable, None): if not template is set, this method will be called and | |
151 what it returns will be rendered. | |
152 This method is mutually exclusive with template and must return a unicode string. | |
153 @param template(unicode, None): path to the template to render. | |
154 This method is mutually exclusive with render | |
931
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
155 @param on_data_post(callable, None): method to call when data is posted |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
156 None if not post is handled |
962 | 157 on_data_post can return a string with following value: |
158 - C.POST_NO_CONFIRM: confirm flag will not be set | |
995 | 159 @param on_data(callable, None): method to call when dynamic data is sent |
160 this method is used with Libervia's websocket mechanism | |
161 @param on_signal(callable, None): method to call when a registered signal is received | |
162 this method is used with Libervia's websocket mechanism | |
917 | 163 """ |
164 | |
165 web_resource.Resource.__init__(self) | |
166 self.host = host | |
167 self.root_dir = root_dir | |
962 | 168 self.url = url |
980
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
169 self.name = name |
917 | 170 if name is not None: |
171 if name in self.named_pages: | |
172 raise exceptions.ConflictError(_(u'a Libervia page named "{}" already exists'.format(name))) | |
923
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
173 if u'/' in name: |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
174 raise ValueError(_(u'"/" is not allowed in page names')) |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
175 if not name: |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
176 raise ValueError(_(u"a page name can't be empty")) |
917 | 177 self.named_pages[name] = self |
178 if access is None: | |
179 access = C.PAGES_ACCESS_PUBLIC | |
922
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
180 if access not in (C.PAGES_ACCESS_PUBLIC, C.PAGES_ACCESS_PROFILE, C.PAGES_ACCESS_NONE): |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
181 raise NotImplementedError(_(u"{} access is not implemented yet").format(access)) |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
182 self.access = access |
995 | 183 self.dynamic = dynamic |
923
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
184 if redirect is not None: |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
185 # only page access and name make sense in case of full redirection |
980
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
186 # so we check that rendering methods/values are not set |
923
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
187 if not all(lambda x: x is not None |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
188 for x in (parse_url, prepare_render, render, template)): |
980
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
189 raise ValueError(_(u"you can't use full page redirection with other rendering method," |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
190 u"check self.pageRedirect if you need to use them")) |
923
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
191 self.redirect = redirect |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
192 else: |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
193 self.redirect = None |
917 | 194 self.parse_url = parse_url |
195 self.prepare_render = prepare_render | |
196 self.template = template | |
197 self.render_method = render | |
931
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
198 self.on_data_post = on_data_post |
995 | 199 self.on_data = on_data |
200 self.on_signal = on_signal | |
1018 | 201 self.url_cache = url_cache |
922
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
202 if access == C.PAGES_ACCESS_NONE: |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
203 # none pages just return a 404, no further check is needed |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
204 return |
917 | 205 if template is None: |
1049
6b1e1f13a299
pages: do not log error if there is not template and render method, but redirect is used
Goffi <goffi@goffi.org>
parents:
1041
diff
changeset
|
206 if self.redirect is None and not callable(render): |
917 | 207 log.error(_(u"render must be implemented and callable if template is not set")) |
208 else: | |
209 if render is not None: | |
210 log.error(_(u"render can't be used at the same time as template")) | |
211 if parse_url is not None and not callable(parse_url): | |
212 log.error(_(u"parse_url must be a callable")) | |
213 | |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
214 # if not None, next rendering will be cached |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
215 # it must then contain a list of the the keys to use (without the page instance) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
216 # e.g. [C.SERVICE_PROFILE, "pubsub", server@example.tld, pubsub_node] |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
217 self._do_cache = None |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
218 |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
219 def __unicode__(self): |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
220 return u'LiberviaPage {name} at {url}'.format( |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
221 name = self.name or u'<anonymous>', |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
222 url = self.url) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
223 |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
224 def __str__(self): |
1013
841a595bee5a
pages: fixed str representation of LiberviaPage
Goffi <goffi@goffi.org>
parents:
1010
diff
changeset
|
225 return self.__unicode__().encode('utf-8') |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
226 |
925 | 227 @classmethod |
228 def importPages(cls, host, parent=None, path=None): | |
937
00236973e138
server (pages): an HTTP internal error is raised if an error is uncatched during page workflow
Goffi <goffi@goffi.org>
parents:
936
diff
changeset
|
229 """Recursively import Libervia pages""" |
917 | 230 if path is None: |
231 path = [] | |
232 if parent is None: | |
233 root_dir = os.path.join(os.path.dirname(libervia.__file__), C.PAGES_DIR) | |
234 parent = host | |
235 else: | |
236 root_dir = parent.root_dir | |
237 for d in os.listdir(root_dir): | |
238 dir_path = os.path.join(root_dir, d) | |
239 if not os.path.isdir(dir_path): | |
240 continue | |
241 meta_path = os.path.join(dir_path, C.PAGES_META_FILE) | |
242 if os.path.isfile(meta_path): | |
243 page_data = {} | |
962 | 244 new_path = path + [d] |
917 | 245 # we don't want to force the presence of __init__.py |
246 # so we use execfile instead of import. | |
247 # TODO: when moved to Python 3, __init__.py is not mandatory anymore | |
248 # so we can switch to import | |
249 execfile(meta_path, page_data) | |
250 resource = LiberviaPage( | |
251 host, | |
252 dir_path, | |
962 | 253 u'/' + u'/'.join(new_path), |
917 | 254 name=page_data.get('name'), |
923
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
255 redirect=page_data.get('redirect'), |
917 | 256 access=page_data.get('access'), |
995 | 257 dynamic=page_data.get('dynamic', False), |
917 | 258 parse_url=page_data.get('parse_url'), |
259 prepare_render=page_data.get('prepare_render'), | |
260 render=page_data.get('render'), | |
931
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
261 template=page_data.get('template'), |
995 | 262 on_data_post=page_data.get('on_data_post'), |
263 on_data=page_data.get('on_data'), | |
264 on_signal=page_data.get('on_signal'), | |
1018 | 265 url_cache=page_data.get('url_cache', False), |
995 | 266 ) |
917 | 267 parent.putChild(d, resource) |
268 log.info(u"Added /{path} page".format(path=u'[...]/'.join(new_path))) | |
925 | 269 if 'uri_handlers' in page_data: |
270 if not isinstance(page_data, dict): | |
271 log.error(_(u'uri_handlers must be a dict')) | |
272 else: | |
273 for uri_tuple, cb_name in page_data['uri_handlers'].iteritems(): | |
274 if len(uri_tuple) != 2 or not isinstance(cb_name, basestring): | |
275 log.error(_(u"invalid uri_tuple")) | |
276 continue | |
277 log.info(_(u'setting {}/{} URIs handler').format(*uri_tuple)) | |
278 try: | |
279 cb = page_data[cb_name] | |
280 except KeyError: | |
281 log.error(_(u'missing {name} method to handle {1}/{2}').format( | |
282 name = cb_name, *uri_tuple)) | |
283 continue | |
284 else: | |
1038 | 285 resource.registerURI(uri_tuple, cb) |
925 | 286 |
917 | 287 LiberviaPage.importPages(host, resource, new_path) |
288 | |
925 | 289 @classmethod |
990
6daa59d44ee2
pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents:
985
diff
changeset
|
290 def setMenu(cls, menus): |
6daa59d44ee2
pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents:
985
diff
changeset
|
291 main_menu = [] |
6daa59d44ee2
pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents:
985
diff
changeset
|
292 for menu in menus: |
6daa59d44ee2
pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents:
985
diff
changeset
|
293 if not menu: |
1003
05cc33d8e328
server: better error message on init issue / menu_json trouble + stop reactor in this case.
Goffi <goffi@goffi.org>
parents:
998
diff
changeset
|
294 msg = _(u"menu item can't be empty") |
05cc33d8e328
server: better error message on init issue / menu_json trouble + stop reactor in this case.
Goffi <goffi@goffi.org>
parents:
998
diff
changeset
|
295 log.error(msg) |
05cc33d8e328
server: better error message on init issue / menu_json trouble + stop reactor in this case.
Goffi <goffi@goffi.org>
parents:
998
diff
changeset
|
296 raise ValueError(msg) |
990
6daa59d44ee2
pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents:
985
diff
changeset
|
297 elif isinstance(menu, list): |
6daa59d44ee2
pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents:
985
diff
changeset
|
298 if len(menu) != 2: |
1003
05cc33d8e328
server: better error message on init issue / menu_json trouble + stop reactor in this case.
Goffi <goffi@goffi.org>
parents:
998
diff
changeset
|
299 msg = _(u"menu item as list must be in the form [page_name, absolue URL]") |
05cc33d8e328
server: better error message on init issue / menu_json trouble + stop reactor in this case.
Goffi <goffi@goffi.org>
parents:
998
diff
changeset
|
300 log.error(msg) |
05cc33d8e328
server: better error message on init issue / menu_json trouble + stop reactor in this case.
Goffi <goffi@goffi.org>
parents:
998
diff
changeset
|
301 raise ValueError(msg) |
990
6daa59d44ee2
pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents:
985
diff
changeset
|
302 page_name, url = menu |
6daa59d44ee2
pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents:
985
diff
changeset
|
303 else: |
6daa59d44ee2
pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents:
985
diff
changeset
|
304 page_name = menu |
1003
05cc33d8e328
server: better error message on init issue / menu_json trouble + stop reactor in this case.
Goffi <goffi@goffi.org>
parents:
998
diff
changeset
|
305 try: |
05cc33d8e328
server: better error message on init issue / menu_json trouble + stop reactor in this case.
Goffi <goffi@goffi.org>
parents:
998
diff
changeset
|
306 url = cls.getPageByName(page_name).url |
05cc33d8e328
server: better error message on init issue / menu_json trouble + stop reactor in this case.
Goffi <goffi@goffi.org>
parents:
998
diff
changeset
|
307 except KeyError as e: |
05cc33d8e328
server: better error message on init issue / menu_json trouble + stop reactor in this case.
Goffi <goffi@goffi.org>
parents:
998
diff
changeset
|
308 log.error(_(u"Can'find a named page ({msg}), please check menu_json in configuration.").format(msg=e)) |
05cc33d8e328
server: better error message on init issue / menu_json trouble + stop reactor in this case.
Goffi <goffi@goffi.org>
parents:
998
diff
changeset
|
309 raise e |
990
6daa59d44ee2
pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents:
985
diff
changeset
|
310 main_menu.append((page_name, url)) |
6daa59d44ee2
pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents:
985
diff
changeset
|
311 cls.main_menu = main_menu |
6daa59d44ee2
pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents:
985
diff
changeset
|
312 |
1038 | 313 def registerURI(self, uri_tuple, get_uri_cb): |
925 | 314 """register a URI handler |
315 | |
316 @param uri_tuple(tuple[unicode, unicode]): type or URIs handler | |
317 type/subtype as returned by tools/common/parseXMPPUri | |
1038 | 318 or type/None to handle all subtypes |
925 | 319 @param get_uri_cb(callable): method which take uri_data dict as only argument |
1038 | 320 and return absolute path with correct arguments or None if the page |
321 can't handle this URL | |
925 | 322 """ |
1038 | 323 if uri_tuple in self.uri_callbacks: |
925 | 324 log.info(_(u"{}/{} URIs are already handled, replacing by the new handler").format(*uri_tuple)) |
1038 | 325 self.uri_callbacks[uri_tuple] = (self, get_uri_cb) |
925 | 326 |
995 | 327 def registerSignal(self, request, signal, check_profile=True): |
328 r"""register a signal handler | |
329 | |
330 the page must be dynamic | |
331 when signal is received, self.on_signal will be called with: | |
332 - request | |
333 - signal name | |
334 - signal arguments | |
335 signal handler will be removed when connection with dynamic page will be lost | |
336 @param signal(unicode): name of the signal | |
337 last arg of signal must be profile, as it will be checked to filter signals | |
338 @param check_profile(bool): if True, signal profile (which MUST be last arg) will be | |
339 checked against session profile. | |
340 /!\ if False, profile will not be checked/filtered, be sure to know what you are doing | |
341 if you unset this option /!\ | |
342 """ | |
343 # FIXME: add a timeout, if socket is not opened before it, signal handler must be removed | |
344 if not self.dynamic: | |
345 log.error(_(u"You can't register signal if page is not dynamic")) | |
346 return | |
347 LiberviaPage.signals_handlers.setdefault(signal, {})[id(request)] = (self, request, check_profile) | |
348 request._signals_registered.append(signal) | |
349 | |
1038 | 350 @classmethod |
351 def getPagePathFromURI(cls, uri): | |
927
bb4dfc2802c0
server (pages): added getPagePathFromURI method to retrieve page handling an URI
Goffi <goffi@goffi.org>
parents:
926
diff
changeset
|
352 """Retrieve page URL from xmpp: URI |
bb4dfc2802c0
server (pages): added getPagePathFromURI method to retrieve page handling an URI
Goffi <goffi@goffi.org>
parents:
926
diff
changeset
|
353 |
bb4dfc2802c0
server (pages): added getPagePathFromURI method to retrieve page handling an URI
Goffi <goffi@goffi.org>
parents:
926
diff
changeset
|
354 @param uri(unicode): URI with a xmpp: scheme |
bb4dfc2802c0
server (pages): added getPagePathFromURI method to retrieve page handling an URI
Goffi <goffi@goffi.org>
parents:
926
diff
changeset
|
355 @return (unicode,None): absolute path (starting from root "/") to page handling the URI |
1038 | 356 None is returned if no page has been registered for this URI |
927
bb4dfc2802c0
server (pages): added getPagePathFromURI method to retrieve page handling an URI
Goffi <goffi@goffi.org>
parents:
926
diff
changeset
|
357 """ |
bb4dfc2802c0
server (pages): added getPagePathFromURI method to retrieve page handling an URI
Goffi <goffi@goffi.org>
parents:
926
diff
changeset
|
358 uri_data = common_uri.parseXMPPUri(uri) |
bb4dfc2802c0
server (pages): added getPagePathFromURI method to retrieve page handling an URI
Goffi <goffi@goffi.org>
parents:
926
diff
changeset
|
359 try: |
1038 | 360 page, cb = cls.uri_callbacks[uri_data['type'], uri_data['sub_type']] |
927
bb4dfc2802c0
server (pages): added getPagePathFromURI method to retrieve page handling an URI
Goffi <goffi@goffi.org>
parents:
926
diff
changeset
|
361 except KeyError: |
1038 | 362 url = None |
927
bb4dfc2802c0
server (pages): added getPagePathFromURI method to retrieve page handling an URI
Goffi <goffi@goffi.org>
parents:
926
diff
changeset
|
363 else: |
1038 | 364 url = cb(page, uri_data) |
365 if url is None: | |
366 # no handler found | |
367 # we try to find a more generic one | |
368 try: | |
369 page, cb = cls.uri_callbacks[uri_data['type'], None] | |
370 except KeyError: | |
371 pass | |
372 else: | |
373 url = cb(page, uri_data) | |
927
bb4dfc2802c0
server (pages): added getPagePathFromURI method to retrieve page handling an URI
Goffi <goffi@goffi.org>
parents:
926
diff
changeset
|
374 return url |
bb4dfc2802c0
server (pages): added getPagePathFromURI method to retrieve page handling an URI
Goffi <goffi@goffi.org>
parents:
926
diff
changeset
|
375 |
979 | 376 @classmethod |
377 def getPageByName(cls, name): | |
936
78692d47340d
server (pages): added getPageByName
Goffi <goffi@goffi.org>
parents:
935
diff
changeset
|
378 """retrieve page instance from its name |
78692d47340d
server (pages): added getPageByName
Goffi <goffi@goffi.org>
parents:
935
diff
changeset
|
379 |
78692d47340d
server (pages): added getPageByName
Goffi <goffi@goffi.org>
parents:
935
diff
changeset
|
380 @param name(unicode): name of the page |
78692d47340d
server (pages): added getPageByName
Goffi <goffi@goffi.org>
parents:
935
diff
changeset
|
381 @return (LiberviaPage): page instance |
78692d47340d
server (pages): added getPageByName
Goffi <goffi@goffi.org>
parents:
935
diff
changeset
|
382 @raise KeyError: the page doesn't exist |
78692d47340d
server (pages): added getPageByName
Goffi <goffi@goffi.org>
parents:
935
diff
changeset
|
383 """ |
979 | 384 return cls.named_pages[name] |
936
78692d47340d
server (pages): added getPageByName
Goffi <goffi@goffi.org>
parents:
935
diff
changeset
|
385 |
962 | 386 def getPageRedirectURL(self, request, page_name=u'login', url=None): |
387 """generate URL for a page with redirect_url parameter set | |
388 | |
389 mainly used for login page with redirection to current page | |
390 @param request(server.Request): current HTTP request | |
391 @param page_name(unicode): name of the page to go | |
392 @param url(None, unicode): url to redirect to | |
393 None to use request path (i.e. current page) | |
394 @return (unicode): URL to use | |
395 """ | |
396 return u'{root_url}?redirect_url={redirect_url}'.format( | |
397 root_url = self.getPageByName(page_name).url, | |
398 redirect_url=urllib.quote_plus(request.uri) if url is None else url.encode('utf-8')) | |
399 | |
972
c4e58c4dba75
server: getURL + minor improvments:
Goffi <goffi@goffi.org>
parents:
968
diff
changeset
|
400 def getURL(self, *args): |
c4e58c4dba75
server: getURL + minor improvments:
Goffi <goffi@goffi.org>
parents:
968
diff
changeset
|
401 """retrieve URL of the page set arguments |
c4e58c4dba75
server: getURL + minor improvments:
Goffi <goffi@goffi.org>
parents:
968
diff
changeset
|
402 |
c4e58c4dba75
server: getURL + minor improvments:
Goffi <goffi@goffi.org>
parents:
968
diff
changeset
|
403 *args(list[unicode]): argument to add to the URL as path elements |
1014
dfced7992460
pages: ignore empty or unset arguments in getURL
Goffi <goffi@goffi.org>
parents:
1013
diff
changeset
|
404 empty or None arguments will be ignored |
972
c4e58c4dba75
server: getURL + minor improvments:
Goffi <goffi@goffi.org>
parents:
968
diff
changeset
|
405 """ |
1014
dfced7992460
pages: ignore empty or unset arguments in getURL
Goffi <goffi@goffi.org>
parents:
1013
diff
changeset
|
406 url_args = [quote(a) for a in args if a] |
980
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
407 |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
408 if self.name is not None and self.name in self.pages_redirects: |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
409 # we check for redirection |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
410 redirect_data = self.pages_redirects[self.name] |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
411 args_hash = tuple(args) |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
412 for limit in xrange(len(args)+1): |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
413 current_hash = args_hash[:limit] |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
414 if current_hash in redirect_data: |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
415 url_base = redirect_data[current_hash] |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
416 remaining = args[limit:] |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
417 remaining_url = '/'.join(remaining) |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
418 return os.path.join('/', url_base, remaining_url) |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
419 |
972
c4e58c4dba75
server: getURL + minor improvments:
Goffi <goffi@goffi.org>
parents:
968
diff
changeset
|
420 return os.path.join(self.url, *url_args) |
c4e58c4dba75
server: getURL + minor improvments:
Goffi <goffi@goffi.org>
parents:
968
diff
changeset
|
421 |
1010
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
422 def getCurrentURL(self, request): |
1015 | 423 """retrieve URL used to access this page |
1010
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
424 |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
425 @return(unicode): current URL |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
426 """ |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
427 # we get url in the following way (splitting request.path instead of using |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
428 # request.prepath) because request.prepath may have been modified by |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
429 # redirection (if redirection args have been specified), while path reflect |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
430 # the real request |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
431 |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
432 # we ignore empty path elements (i.e. double '/' or '/' at the end) |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
433 path_elts = [p for p in request.path.split('/') if p] |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
434 |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
435 if request.postpath: |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
436 if not request.postpath[-1]: |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
437 # we remove trailing slash |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
438 request.postpath = request.postpath[:-1] |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
439 if request.postpath: |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
440 # getSubPageURL must return subpage from the point where |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
441 # the it is called, so we have to remove remanining |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
442 # path elements |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
443 path_elts = path_elts[:-len(request.postpath)] |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
444 |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
445 return u'/' + '/'.join(path_elts).decode('utf-8') |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
446 |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
447 def getParamURL(self, request, **kwargs): |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
448 """use URL of current request but modify the parameters in query part |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
449 |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
450 **kwargs(dict[str, unicode]): argument to use as query parameters |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
451 @return (unicode): constructed URL |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
452 """ |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
453 current_url = self.getCurrentURL(request) |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
454 if kwargs: |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
455 encoded = urllib.urlencode({k:v.encode('utf-8') for k,v in kwargs.iteritems()}).decode('utf-8') |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
456 current_url = current_url + u'?' + encoded |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
457 return current_url |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
458 |
1030
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
459 def getSubPageByName(self, page, subpage_name): |
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
460 """retrieve a subpage and its path using its name |
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
461 |
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
462 @param request(server.Request): current HTTP request |
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
463 @param page_name(unicode): name of the page to retrieve |
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
464 it must be a direct children of current page |
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
465 @return (tuple[str, LiberviaPage]): page subpath and instance |
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
466 @raise exceptions.NotFound: no page has been found |
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
467 """ |
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
468 for path, child in page.children.iteritems(): |
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
469 try: |
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
470 child_name = child.name |
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
471 except AttributeError: |
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
472 # LiberviaPages have a name, but maybe this is an other Resource |
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
473 continue |
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
474 if child_name == subpage_name: |
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
475 return path, child |
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
476 raise exceptions.NotFound(_(u'requested sub page has not been found')) |
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
477 |
980
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
478 def getSubPageURL(self, request, page_name, *args): |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
479 """retrieve a page in direct children and build its URL according to request |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
480 |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
481 request's current path is used as base (at current parsing point, |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
482 i.e. it's more prepath than path). |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
483 Requested page is checked in children and an absolute URL is then built |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
484 by the resulting combination. |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
485 This method is useful to construct absolute URLs for children instead of |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
486 using relative path, which may not work in subpages, and are linked to the |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
487 names of directories (i.e. relative URL will break if subdirectory is renamed |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
488 while getSubPageURL won't as long as page_name is consistent). |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
489 Also, request.path is used, keeping real path used by user, |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
490 and potential redirections. |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
491 @param request(server.Request): current HTTP request |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
492 @param page_name(unicode): name of the page to retrieve |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
493 it must be a direct children of current page |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
494 @param *args(list[unicode]): arguments to add as path elements |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
495 @return unicode: absolute URL to the sub page |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
496 """ |
1010
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
497 current_url = self.getCurrentURL(request) |
1030
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
498 path, child = self.getSubPageByName(self, page_name) |
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
499 return os.path.join(u'/', current_url, path, *[quote(a) for a in args]) |
980
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
500 |
1031
4ba7df23b976
pages: new method getURLByNames to retrieve URL from list of page names/path arguments
Goffi <goffi@goffi.org>
parents:
1030
diff
changeset
|
501 def getURLByNames(self, named_path): |
4ba7df23b976
pages: new method getURLByNames to retrieve URL from list of page names/path arguments
Goffi <goffi@goffi.org>
parents:
1030
diff
changeset
|
502 """retrieve URL from pages names and arguments |
4ba7df23b976
pages: new method getURLByNames to retrieve URL from list of page names/path arguments
Goffi <goffi@goffi.org>
parents:
1030
diff
changeset
|
503 |
4ba7df23b976
pages: new method getURLByNames to retrieve URL from list of page names/path arguments
Goffi <goffi@goffi.org>
parents:
1030
diff
changeset
|
504 @param named_path(list[tuple[unicode, list[unicode]]]): path to the page as a list |
4ba7df23b976
pages: new method getURLByNames to retrieve URL from list of page names/path arguments
Goffi <goffi@goffi.org>
parents:
1030
diff
changeset
|
505 of tuples of 2 items: |
4ba7df23b976
pages: new method getURLByNames to retrieve URL from list of page names/path arguments
Goffi <goffi@goffi.org>
parents:
1030
diff
changeset
|
506 - first item is page name |
4ba7df23b976
pages: new method getURLByNames to retrieve URL from list of page names/path arguments
Goffi <goffi@goffi.org>
parents:
1030
diff
changeset
|
507 - second item is list of path arguments of this page |
4ba7df23b976
pages: new method getURLByNames to retrieve URL from list of page names/path arguments
Goffi <goffi@goffi.org>
parents:
1030
diff
changeset
|
508 @return (unicode): URL to the requested page with given path arguments |
4ba7df23b976
pages: new method getURLByNames to retrieve URL from list of page names/path arguments
Goffi <goffi@goffi.org>
parents:
1030
diff
changeset
|
509 @raise exceptions.NotFound: one of the page was not found |
4ba7df23b976
pages: new method getURLByNames to retrieve URL from list of page names/path arguments
Goffi <goffi@goffi.org>
parents:
1030
diff
changeset
|
510 """ |
4ba7df23b976
pages: new method getURLByNames to retrieve URL from list of page names/path arguments
Goffi <goffi@goffi.org>
parents:
1030
diff
changeset
|
511 current_page = None |
4ba7df23b976
pages: new method getURLByNames to retrieve URL from list of page names/path arguments
Goffi <goffi@goffi.org>
parents:
1030
diff
changeset
|
512 path = [] |
4ba7df23b976
pages: new method getURLByNames to retrieve URL from list of page names/path arguments
Goffi <goffi@goffi.org>
parents:
1030
diff
changeset
|
513 for page_name, page_args in named_path: |
4ba7df23b976
pages: new method getURLByNames to retrieve URL from list of page names/path arguments
Goffi <goffi@goffi.org>
parents:
1030
diff
changeset
|
514 if current_page is None: |
4ba7df23b976
pages: new method getURLByNames to retrieve URL from list of page names/path arguments
Goffi <goffi@goffi.org>
parents:
1030
diff
changeset
|
515 current_page = self.getPageByName(page_name) |
4ba7df23b976
pages: new method getURLByNames to retrieve URL from list of page names/path arguments
Goffi <goffi@goffi.org>
parents:
1030
diff
changeset
|
516 path.append(current_page.getURL(*page_args)) |
4ba7df23b976
pages: new method getURLByNames to retrieve URL from list of page names/path arguments
Goffi <goffi@goffi.org>
parents:
1030
diff
changeset
|
517 else: |
4ba7df23b976
pages: new method getURLByNames to retrieve URL from list of page names/path arguments
Goffi <goffi@goffi.org>
parents:
1030
diff
changeset
|
518 sub_path, current_page = self.getSubPageByName(current_page, page_name) |
4ba7df23b976
pages: new method getURLByNames to retrieve URL from list of page names/path arguments
Goffi <goffi@goffi.org>
parents:
1030
diff
changeset
|
519 path.append(sub_path) |
4ba7df23b976
pages: new method getURLByNames to retrieve URL from list of page names/path arguments
Goffi <goffi@goffi.org>
parents:
1030
diff
changeset
|
520 if page_args: |
4ba7df23b976
pages: new method getURLByNames to retrieve URL from list of page names/path arguments
Goffi <goffi@goffi.org>
parents:
1030
diff
changeset
|
521 path.extend([quote(a) for a in page_args]) |
1041
688b52897ba0
pages: check redirections on getURLByNames
Goffi <goffi@goffi.org>
parents:
1038
diff
changeset
|
522 return self.host.checkRedirection(u'/'.join(path)) |
980
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
523 |
917 | 524 def getChildWithDefault(self, path, request): |
525 # we handle children ourselves | |
526 raise exceptions.InternalError(u"this method should not be used with LiberviaPage") | |
527 | |
528 def nextPath(self, request): | |
529 """get next URL path segment, and update request accordingly | |
530 | |
531 will move first segment of postpath in prepath | |
532 @param request(server.Request): current HTTP request | |
533 @return (unicode): unquoted segment | |
534 @raise IndexError: there is no segment left | |
535 """ | |
536 pathElement = request.postpath.pop(0) | |
537 request.prepath.append(pathElement) | |
538 return urllib.unquote(pathElement).decode('utf-8') | |
539 | |
1019
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
540 ## Cache handling ## |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
541 |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
542 def _setCacheHeaders(self, request, cache): |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
543 """Set ETag and Last-Modified HTTP headers, used for caching""" |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
544 request.setHeader('ETag', cache.hash) |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
545 last_modified = self.host.getHTTPDate(cache.created) |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
546 request.setHeader('Last-Modified', last_modified) |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
547 |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
548 def _checkCacheHeaders(self, request, cache): |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
549 """Check if a cache condition is set on the request |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
550 |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
551 if condition is valid, C.HTTP_NOT_MODIFIED is returned |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
552 """ |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
553 etag_match = request.getHeader('If-None-Match') |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
554 if etag_match is not None: |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
555 if cache.hash == etag_match: |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
556 self.pageError(request, C.HTTP_NOT_MODIFIED, no_body=True) |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
557 else: |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
558 modified_match = request.getHeader('If-Modified-Since') |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
559 if modified_match is not None: |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
560 modified = utils.date_parse(modified_match) |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
561 if modified >= int(cache.created): |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
562 self.pageError(request, C.HTTP_NOT_MODIFIED, no_body=True) |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
563 |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
564 def checkCacheSubscribeCb(self, sub_id, service, node): |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
565 self.cache_pubsub_sub.add((service, node, sub_id)) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
566 |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
567 def checkCacheSubscribeEb(self, failure_, service, node): |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
568 log.warning(_(u"Can't subscribe to node: {msg}").format(msg=failure_)) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
569 # FIXME: cache must be marked as unusable here |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
570 |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
571 def psNodeWatchAddEb(self, failure_, service, node): |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
572 log.warning(_(u"Can't add node watched: {msg}").format(msg=failure_)) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
573 |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
574 def checkCache(self, request, cache_type, **kwargs): |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
575 """check if a page is in cache and return cached version if suitable |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
576 |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
577 this method may perform extra operation to handle cache (e.g. subscribing to a |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
578 pubsub node) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
579 @param request(server.Request): current HTTP request |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
580 @param cache_type(int): on of C.CACHE_* const. |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
581 @param **kwargs: args according to cache_type: |
1010
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
582 C.CACHE_PUBSUB: |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
583 service: pubsub service |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
584 node: pubsub node |
1019
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
585 short: short name of feature (needed if node is empty to find namespace) |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
586 |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
587 """ |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
588 if request.postpath: |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
589 # we are not on the final page, no need to go further |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
590 return |
1033
c34f08e05cdf
pages: cache is now working even after pageRedirect
Goffi <goffi@goffi.org>
parents:
1032
diff
changeset
|
591 |
c34f08e05cdf
pages: cache is now working even after pageRedirect
Goffi <goffi@goffi.org>
parents:
1032
diff
changeset
|
592 if request.args: |
c34f08e05cdf
pages: cache is now working even after pageRedirect
Goffi <goffi@goffi.org>
parents:
1032
diff
changeset
|
593 # TODO: requests with args are not cached for now |
c34f08e05cdf
pages: cache is now working even after pageRedirect
Goffi <goffi@goffi.org>
parents:
1032
diff
changeset
|
594 return |
c34f08e05cdf
pages: cache is now working even after pageRedirect
Goffi <goffi@goffi.org>
parents:
1032
diff
changeset
|
595 |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
596 profile = self.getProfile(request) or C.SERVICE_PROFILE |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
597 |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
598 if cache_type == C.CACHE_PUBSUB: |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
599 service, node = kwargs['service'], kwargs['node'] |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
600 if not node: |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
601 try: |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
602 short = kwargs['short'] |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
603 node = self.host.ns_map[short] |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
604 except KeyError: |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
605 log.warning(_(u"Can't use cache for empty node without namespace set, please ensure to set \"short\" and that it is registered")) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
606 return |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
607 if profile != C.SERVICE_PROFILE: |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
608 # only service profile is cache for now |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
609 return |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
610 try: |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
611 cache = self.cache[profile][cache_type][service][node][self] |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
612 except KeyError: |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
613 # no cache yet, let's subscribe to the pubsub node |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
614 d1 = self.host.bridgeCall('psSubscribe', service.full(), node, {}, profile) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
615 d1.addCallback(self.checkCacheSubscribeCb, service, node) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
616 d1.addErrback(self.checkCacheSubscribeEb, service, node) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
617 d2 = self.host.bridgeCall('psNodeWatchAdd', service.full(), node, profile) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
618 d2.addErrback(self.psNodeWatchAddEb, service, node) |
1033
c34f08e05cdf
pages: cache is now working even after pageRedirect
Goffi <goffi@goffi.org>
parents:
1032
diff
changeset
|
619 self._do_cache = [self, profile, cache_type, service, node] |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
620 # we don't return the Deferreds as it is not needed to wait for |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
621 # the subscription to continue with page rendering |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
622 return |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
623 |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
624 else: |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
625 raise exceptions.InternalError(u'Unknown cache_type') |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
626 log.debug(u'using cache for {page}'.format(page=self)) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
627 cache.last_access = time.time() |
1019
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
628 self._setCacheHeaders(request, cache) |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
629 self._checkCacheHeaders(request, cache) |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
630 request.write(cache.rendered) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
631 request.finish() |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
632 raise failure.Failure(exceptions.CancelError(u'cache is used')) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
633 |
1018 | 634 def _cacheURL(self, dummy, request, profile): |
635 self.cached_urls.setdefault(profile, {})[request.uri] = CacheURL(request) | |
636 | |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
637 @classmethod |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
638 def onNodeEvent(cls, host, service, node, event_type, items, profile): |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
639 """Invalidate cache for all pages linked to this node""" |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
640 try: |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
641 cache = cls.cache[profile][C.CACHE_PUBSUB][jid.JID(service)][node] |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
642 except KeyError: |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
643 log.info(_(u'Removing subscription for {service}/{node}: ' |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
644 u'the page is not cached').format(service=service, node=node)) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
645 d1 = host.bridgeCall('psUnsubscribe', service, node, profile) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
646 d1.addErrback(lambda failure_: |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
647 log.warning(_(u"Can't unsubscribe from {service}/{node}: {msg}").format( |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
648 service=service, node=node, msg=failure_))) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
649 d2 = host.bridgeCall('psNodeWatchAdd', service, node, profile) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
650 # TODO: check why the page is not in cache, remove subscription? |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
651 d2.addErrback(lambda failure_: |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
652 log.warning(_(u"Can't remove watch for {service}/{node}: {msg}").format( |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
653 service=service, node=node, msg=failure_))) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
654 else: |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
655 cache.clear() |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
656 |
995 | 657 @classmethod |
658 def onSignal(cls, host, signal, *args): | |
659 """Generic method which receive registered signals | |
660 | |
661 if a callback is registered for this signal, call it | |
662 @param host: Libervia instance | |
663 @param signal(unicode): name of the signal | |
664 @param *args: args of the signals | |
665 """ | |
666 for page, request, check_profile in cls.signals_handlers.get(signal, {}).itervalues(): | |
667 if check_profile: | |
668 signal_profile = args[-1] | |
669 request_profile = page.getProfile(request) | |
670 if not request_profile: | |
671 # if you want to use signal without session, unset check_profile | |
672 # (be sure to know what you are doing) | |
673 log.error(_(u"no session started, signal can't be checked")) | |
674 continue | |
675 if signal_profile != request_profile: | |
676 # we ignore the signal, it's not for our profile | |
677 continue | |
678 if request._signals_cache is not None: | |
679 # socket is not yet opened, we cache the signal | |
680 request._signals_cache.append((request, signal, args)) | |
681 log.debug(u"signal [{signal}] cached: {args}".format( | |
682 signal = signal, | |
683 args = args)) | |
684 else: | |
685 page.on_signal(page, request, signal, *args) | |
686 | |
687 def onSocketOpen(self, request): | |
688 """Called for dynamic pages when socket has just been opened | |
689 | |
690 we send all cached signals | |
691 """ | |
692 assert request._signals_cache is not None | |
693 cache = request._signals_cache | |
694 request._signals_cache = None | |
695 for request, signal, args in cache: | |
696 self.on_signal(self, request, signal, *args) | |
697 | |
698 def onSocketClose(self, request): | |
699 """Called for dynamic pages when socket has just been closed | |
700 | |
701 we remove signal handler | |
702 """ | |
703 for signal in request._signals_registered: | |
704 try: | |
705 del LiberviaPage.signals_handlers[signal][id(request)] | |
706 except KeyError: | |
707 log.error(_(u"Can't find signal handler for [{signal}], this should not happen").format( | |
708 signal = signal)) | |
709 else: | |
710 log.debug(_(u"Removed signal handler")) | |
711 | |
962 | 712 def HTTPRedirect(self, request, url): |
713 """redirect to an URL using HTTP redirection | |
714 | |
715 @param request(server.Request): current HTTP request | |
716 @param url(unicode): url to redirect to | |
717 """ | |
718 | |
719 web_util.redirectTo(url.encode('utf-8'), request) | |
720 request.finish() | |
721 raise failure.Failure(exceptions.CancelError(u'HTTP redirection is used')) | |
722 | |
723 def redirectOrContinue(self, request, redirect_arg=u'redirect_url'): | |
724 """helper method to redirect a page to an url given as arg | |
725 | |
726 if the arg is not present, the page will continue normal workflow | |
727 @param request(server.Request): current HTTP request | |
728 @param redirect_arg(unicode): argument to use to get redirection URL | |
729 @interrupt: redirect the page to requested URL | |
730 @interrupt pageError(C.HTTP_BAD_REQUEST): empty or non local URL is used | |
731 """ | |
732 try: | |
733 url = self.getPostedData(request, 'redirect_url') | |
734 except KeyError: | |
735 pass | |
736 else: | |
737 # a redirection is requested | |
738 if not url or url[0] != u'/': | |
739 # we only want local urls | |
740 self.pageError(request, C.HTTP_BAD_REQUEST) | |
741 else: | |
742 self.HTTPRedirect(request, url) | |
743 | |
1032
863cc6f97068
pages: path arguments can now be specified in pageRedirect
Goffi <goffi@goffi.org>
parents:
1031
diff
changeset
|
744 def pageRedirect(self, page_path, request, skip_parse_url=True, path_args=None): |
923
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
745 """redirect a page to a named page |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
746 |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
747 the workflow will continue with the workflow of the named page, |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
748 skipping named page's parse_url method if it exist. |
962 | 749 If you want to do a HTTP redirection, use HTTPRedirect |
923
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
750 @param page_path(unicode): path to page (elements are separated by "/"): |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
751 if path starts with a "/": |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
752 path is a full path starting from root |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
753 else: |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
754 - first element is name as registered in name variable |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
755 - following element are subpages path |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
756 e.g.: "blog" redirect to page named "blog" |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
757 "blog/atom.xml" redirect to atom.xml subpage of "blog" |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
758 "/common/blog/atom.xml" redirect to the page at the fiven full path |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
759 @param request(server.Request): current HTTP request |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
760 @param skip_parse_url(bool): if True, parse_url method on redirect page will be skipped |
1032
863cc6f97068
pages: path arguments can now be specified in pageRedirect
Goffi <goffi@goffi.org>
parents:
1031
diff
changeset
|
761 @param path_args(list[unicode], None): path arguments to use in redirected page |
923
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
762 @raise KeyError: there is no known page with this name |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
763 """ |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
764 # FIXME: render non LiberviaPage resources |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
765 path = page_path.rstrip(u'/').split(u'/') |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
766 if not path[0]: |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
767 redirect_page = self.host.root |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
768 else: |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
769 redirect_page = self.named_pages[path[0]] |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
770 |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
771 for subpage in path[1:]: |
962 | 772 if redirect_page is self.host.root: |
773 redirect_page = redirect_page.children[subpage] | |
774 else: | |
775 redirect_page = redirect_page.original.children[subpage] | |
923
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
776 |
1032
863cc6f97068
pages: path arguments can now be specified in pageRedirect
Goffi <goffi@goffi.org>
parents:
1031
diff
changeset
|
777 if path_args is not None: |
863cc6f97068
pages: path arguments can now be specified in pageRedirect
Goffi <goffi@goffi.org>
parents:
1031
diff
changeset
|
778 args = [quote(a) for a in path_args] |
863cc6f97068
pages: path arguments can now be specified in pageRedirect
Goffi <goffi@goffi.org>
parents:
1031
diff
changeset
|
779 request.postpath = args + request.postpath |
863cc6f97068
pages: path arguments can now be specified in pageRedirect
Goffi <goffi@goffi.org>
parents:
1031
diff
changeset
|
780 |
1033
c34f08e05cdf
pages: cache is now working even after pageRedirect
Goffi <goffi@goffi.org>
parents:
1032
diff
changeset
|
781 if self._do_cache: |
c34f08e05cdf
pages: cache is now working even after pageRedirect
Goffi <goffi@goffi.org>
parents:
1032
diff
changeset
|
782 # if cache is needed, it will be handled by final page |
c34f08e05cdf
pages: cache is now working even after pageRedirect
Goffi <goffi@goffi.org>
parents:
1032
diff
changeset
|
783 redirect_page._do_cache = self._do_cache |
c34f08e05cdf
pages: cache is now working even after pageRedirect
Goffi <goffi@goffi.org>
parents:
1032
diff
changeset
|
784 self._do_cache = None |
c34f08e05cdf
pages: cache is now working even after pageRedirect
Goffi <goffi@goffi.org>
parents:
1032
diff
changeset
|
785 |
1015 | 786 redirect_page.renderPage(request, skip_parse_url=skip_parse_url) |
923
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
787 raise failure.Failure(exceptions.CancelError(u'page redirection is used')) |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
788 |
1019
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
789 def pageError(self, request, code=C.HTTP_NOT_FOUND, no_body=False): |
917 | 790 """generate an error page and terminate the request |
791 | |
792 @param request(server.Request): HTTP request | |
793 @param core(int): error code to use | |
1019
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
794 @param no_body: don't write body if True |
917 | 795 """ |
796 request.setResponseCode(code) | |
1019
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
797 if no_body: |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
798 request.finish() |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
799 else: |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
800 template = u'error/' + unicode(code) + '.html' |
917 | 801 |
1019
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
802 rendered = self.host.renderer.render( |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
803 template, |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
804 root_path = '/templates/', |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
805 error_code = code, |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
806 **request.template_data) |
917 | 807 |
1019
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
808 self.writeData(rendered, request) |
917 | 809 raise failure.Failure(exceptions.CancelError(u'error page is used')) |
810 | |
811 def writeData(self, data, request): | |
937
00236973e138
server (pages): an HTTP internal error is raised if an error is uncatched during page workflow
Goffi <goffi@goffi.org>
parents:
936
diff
changeset
|
812 """write data to transport and finish the request""" |
917 | 813 if data is None: |
814 self.pageError(request) | |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
815 data_encoded = data.encode('utf-8') |
1019
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
816 |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
817 if self._do_cache is not None: |
1033
c34f08e05cdf
pages: cache is now working even after pageRedirect
Goffi <goffi@goffi.org>
parents:
1032
diff
changeset
|
818 redirected_page = self._do_cache.pop(0) |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
819 cache = reduce(lambda d, k: d.setdefault(k, {}), self._do_cache, self.cache) |
1033
c34f08e05cdf
pages: cache is now working even after pageRedirect
Goffi <goffi@goffi.org>
parents:
1032
diff
changeset
|
820 page_cache = cache[redirected_page] = CachePage(data_encoded) |
1019
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
821 self._setCacheHeaders(request, page_cache) |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
822 log.debug(_(u'{page} put in cache for [{profile}]').format( |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
823 page=self, |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
824 profile=self._do_cache[0])) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
825 self._do_cache = None |
1019
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
826 self._checkCacheHeaders(request, page_cache) |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
827 |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
828 request.write(data_encoded) |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
829 request.finish() |
917 | 830 |
831 def _subpagesHandler(self, dummy, request): | |
832 """render subpage if suitable | |
833 | |
834 this method checks if there is still an unmanaged part of the path | |
835 and check if it corresponds to a subpage. If so, it render the subpage | |
836 else it render a NoResource. | |
837 If there is no unmanaged part of the segment, current page workflow is pursued | |
838 """ | |
839 if request.postpath: | |
840 subpage = self.nextPath(request) | |
841 try: | |
842 child = self.children[subpage] | |
843 except KeyError: | |
844 self.pageError(request) | |
845 else: | |
846 child.render(request) | |
847 raise failure.Failure(exceptions.CancelError(u'subpage page is used')) | |
848 | |
998
0848b8b0188d
pages: dynamic set up is now done just before prepare_render call:
Goffi <goffi@goffi.org>
parents:
995
diff
changeset
|
849 def _prepare_dynamic(self, dummy, request): |
0848b8b0188d
pages: dynamic set up is now done just before prepare_render call:
Goffi <goffi@goffi.org>
parents:
995
diff
changeset
|
850 # we need to activate dynamic page |
0848b8b0188d
pages: dynamic set up is now done just before prepare_render call:
Goffi <goffi@goffi.org>
parents:
995
diff
changeset
|
851 # we set data for template, and create/register token |
0848b8b0188d
pages: dynamic set up is now done just before prepare_render call:
Goffi <goffi@goffi.org>
parents:
995
diff
changeset
|
852 socket_token = unicode(uuid.uuid4()) |
0848b8b0188d
pages: dynamic set up is now done just before prepare_render call:
Goffi <goffi@goffi.org>
parents:
995
diff
changeset
|
853 socket_url = self.host.getWebsocketURL(request) |
0848b8b0188d
pages: dynamic set up is now done just before prepare_render call:
Goffi <goffi@goffi.org>
parents:
995
diff
changeset
|
854 socket_debug = C.boolConst(self.host.debug) |
0848b8b0188d
pages: dynamic set up is now done just before prepare_render call:
Goffi <goffi@goffi.org>
parents:
995
diff
changeset
|
855 request.template_data['websocket'] = WebsocketMeta(socket_url, socket_token, socket_debug) |
0848b8b0188d
pages: dynamic set up is now done just before prepare_render call:
Goffi <goffi@goffi.org>
parents:
995
diff
changeset
|
856 self.host.registerWSToken(socket_token, self, request) |
0848b8b0188d
pages: dynamic set up is now done just before prepare_render call:
Goffi <goffi@goffi.org>
parents:
995
diff
changeset
|
857 # we will keep track of handlers to remove |
0848b8b0188d
pages: dynamic set up is now done just before prepare_render call:
Goffi <goffi@goffi.org>
parents:
995
diff
changeset
|
858 request._signals_registered = [] |
0848b8b0188d
pages: dynamic set up is now done just before prepare_render call:
Goffi <goffi@goffi.org>
parents:
995
diff
changeset
|
859 # we will cache registered signals until socket is opened |
0848b8b0188d
pages: dynamic set up is now done just before prepare_render call:
Goffi <goffi@goffi.org>
parents:
995
diff
changeset
|
860 request._signals_cache = [] |
0848b8b0188d
pages: dynamic set up is now done just before prepare_render call:
Goffi <goffi@goffi.org>
parents:
995
diff
changeset
|
861 |
917 | 862 def _prepare_render(self, dummy, request): |
926
612e33fd32a8
server (pages): fixed _prepare_render handling
Goffi <goffi@goffi.org>
parents:
925
diff
changeset
|
863 return defer.maybeDeferred(self.prepare_render, self, request) |
917 | 864 |
865 def _render_method(self, dummy, request): | |
866 return defer.maybeDeferred(self.render_method, self, request) | |
867 | |
962 | 868 def _render_template(self, dummy, request): |
869 template_data = request.template_data | |
870 | |
871 # if confirm variable is set in case of successfuly data post | |
872 session_data = self.host.getSessionData(request, session_iface.ISATSession) | |
873 if session_data.popPageFlag(self, C.FLAG_CONFIRM): | |
874 template_data[u'confirm'] = True | |
875 | |
917 | 876 return self.host.renderer.render( |
877 self.template, | |
878 root_path = '/templates/', | |
962 | 879 media_path = '/' + C.MEDIA_DIR, |
995 | 880 cache_path = session_data.cache_dir, |
990
6daa59d44ee2
pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents:
985
diff
changeset
|
881 main_menu = LiberviaPage.main_menu, |
917 | 882 **template_data) |
883 | |
884 def _renderEb(self, failure_, request): | |
885 """don't raise error on CancelError""" | |
886 failure_.trap(exceptions.CancelError) | |
887 | |
937
00236973e138
server (pages): an HTTP internal error is raised if an error is uncatched during page workflow
Goffi <goffi@goffi.org>
parents:
936
diff
changeset
|
888 def _internalError(self, failure_, request): |
00236973e138
server (pages): an HTTP internal error is raised if an error is uncatched during page workflow
Goffi <goffi@goffi.org>
parents:
936
diff
changeset
|
889 """called if an error is not catched""" |
00236973e138
server (pages): an HTTP internal error is raised if an error is uncatched during page workflow
Goffi <goffi@goffi.org>
parents:
936
diff
changeset
|
890 log.error(_(u"Uncatched error for HTTP request on {url}: {msg}").format( |
00236973e138
server (pages): an HTTP internal error is raised if an error is uncatched during page workflow
Goffi <goffi@goffi.org>
parents:
936
diff
changeset
|
891 url = request.URLPath(), |
00236973e138
server (pages): an HTTP internal error is raised if an error is uncatched during page workflow
Goffi <goffi@goffi.org>
parents:
936
diff
changeset
|
892 msg = failure_)) |
00236973e138
server (pages): an HTTP internal error is raised if an error is uncatched during page workflow
Goffi <goffi@goffi.org>
parents:
936
diff
changeset
|
893 self.pageError(request, C.HTTP_INTERNAL_ERROR) |
00236973e138
server (pages): an HTTP internal error is raised if an error is uncatched during page workflow
Goffi <goffi@goffi.org>
parents:
936
diff
changeset
|
894 |
956
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
895 def _on_data_post_redirect(self, ret, request): |
968
4d37b23777c3
pages (core, tickets/new): replaced post_redirect_uri mechanism by post_redirect_page:
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
896 """called when page's on_data_post has been done successfuly |
956
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
897 |
968
4d37b23777c3
pages (core, tickets/new): replaced post_redirect_uri mechanism by post_redirect_page:
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
898 This will do a Post/Redirect/Get pattern. |
4d37b23777c3
pages (core, tickets/new): replaced post_redirect_uri mechanism by post_redirect_page:
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
899 this method redirect to the same page or to request.data['post_redirect_page'] |
4d37b23777c3
pages (core, tickets/new): replaced post_redirect_uri mechanism by post_redirect_page:
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
900 post_redirect_page can be either a page or a tuple with page as first item, then a list of unicode arguments to append to the url. |
4d37b23777c3
pages (core, tickets/new): replaced post_redirect_uri mechanism by post_redirect_page:
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
901 if post_redirect_page is not used, initial request.uri (i.e. the same page as where the data have been posted) will be used for redirection. |
4d37b23777c3
pages (core, tickets/new): replaced post_redirect_uri mechanism by post_redirect_page:
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
902 HTTP status code "See Other" (303) is used as it is the recommanded code in this case. |
962 | 903 @param ret(None, unicode, iterable): on_data_post return value |
904 see LiberviaPage.__init__ on_data_post docstring | |
956
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
905 """ |
962 | 906 if ret is None: |
907 ret = () | |
908 elif isinstance(ret, basestring): | |
909 ret = (ret,) | |
910 else: | |
911 ret = tuple(ret) | |
912 raise NotImplementedError(_(u'iterable in on_data_post return value is not used yet')) | |
957
67bf14c91d5c
server (pages): added a confirm flag on successful post:
Goffi <goffi@goffi.org>
parents:
956
diff
changeset
|
913 session_data = self.host.getSessionData(request, session_iface.ISATSession) |
974
4aa38c49bff7
pages: fixed use of request data in _on_data_post_redirect
Goffi <goffi@goffi.org>
parents:
972
diff
changeset
|
914 request_data = self.getRData(request) |
4aa38c49bff7
pages: fixed use of request data in _on_data_post_redirect
Goffi <goffi@goffi.org>
parents:
972
diff
changeset
|
915 if 'post_redirect_page' in request_data: |
4aa38c49bff7
pages: fixed use of request data in _on_data_post_redirect
Goffi <goffi@goffi.org>
parents:
972
diff
changeset
|
916 redirect_page_data = request_data['post_redirect_page'] |
968
4d37b23777c3
pages (core, tickets/new): replaced post_redirect_uri mechanism by post_redirect_page:
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
917 if isinstance(redirect_page_data, tuple): |
4d37b23777c3
pages (core, tickets/new): replaced post_redirect_uri mechanism by post_redirect_page:
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
918 redirect_page = redirect_page_data[0] |
972
c4e58c4dba75
server: getURL + minor improvments:
Goffi <goffi@goffi.org>
parents:
968
diff
changeset
|
919 redirect_page_args = redirect_page_data[1:] |
c4e58c4dba75
server: getURL + minor improvments:
Goffi <goffi@goffi.org>
parents:
968
diff
changeset
|
920 redirect_uri = redirect_page.getURL(*redirect_page_args) |
968
4d37b23777c3
pages (core, tickets/new): replaced post_redirect_uri mechanism by post_redirect_page:
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
921 else: |
4d37b23777c3
pages (core, tickets/new): replaced post_redirect_uri mechanism by post_redirect_page:
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
922 redirect_page = redirect_page_data |
972
c4e58c4dba75
server: getURL + minor improvments:
Goffi <goffi@goffi.org>
parents:
968
diff
changeset
|
923 redirect_uri = redirect_page.url |
968
4d37b23777c3
pages (core, tickets/new): replaced post_redirect_uri mechanism by post_redirect_page:
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
924 else: |
4d37b23777c3
pages (core, tickets/new): replaced post_redirect_uri mechanism by post_redirect_page:
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
925 redirect_page = self |
4d37b23777c3
pages (core, tickets/new): replaced post_redirect_uri mechanism by post_redirect_page:
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
926 redirect_uri = request.uri |
4d37b23777c3
pages (core, tickets/new): replaced post_redirect_uri mechanism by post_redirect_page:
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
927 |
962 | 928 if not C.POST_NO_CONFIRM in ret: |
968
4d37b23777c3
pages (core, tickets/new): replaced post_redirect_uri mechanism by post_redirect_page:
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
929 session_data.setPageFlag(redirect_page, C.FLAG_CONFIRM) |
956
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
930 request.setResponseCode(C.HTTP_SEE_OTHER) |
968
4d37b23777c3
pages (core, tickets/new): replaced post_redirect_uri mechanism by post_redirect_page:
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
931 request.setHeader("location", redirect_uri) |
955
4f7cb6335a33
server(pages): do Post/Redirect/Get pattern when on_data_post is used (avoid double posting on refresh)
Goffi <goffi@goffi.org>
parents:
950
diff
changeset
|
932 request.finish() |
4f7cb6335a33
server(pages): do Post/Redirect/Get pattern when on_data_post is used (avoid double posting on refresh)
Goffi <goffi@goffi.org>
parents:
950
diff
changeset
|
933 raise failure.Failure(exceptions.CancelError(u'Post/Redirect/Get is used')) |
4f7cb6335a33
server(pages): do Post/Redirect/Get pattern when on_data_post is used (avoid double posting on refresh)
Goffi <goffi@goffi.org>
parents:
950
diff
changeset
|
934 |
956
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
935 def _on_data_post(self, dummy, request): |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
936 csrf_token = self.host.getSessionData(request, session_iface.ISATSession).csrf_token |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
937 try: |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
938 given_csrf = self.getPostedData(request, u'csrf_token') |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
939 except KeyError: |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
940 given_csrf = None |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
941 if given_csrf is None or given_csrf != csrf_token: |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
942 log.warning(_(u"invalid CSRF token, hack attempt? URL: {url}, IP: {ip}").format( |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
943 url=request.uri, |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
944 ip=request.getClientIP())) |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
945 self.pageError(request, C.HTTP_UNAUTHORIZED) |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
946 d = defer.maybeDeferred(self.on_data_post, self, request) |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
947 d.addCallback(self._on_data_post_redirect, request) |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
948 return d |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
949 |
931
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
950 def getPostedData(self, request, keys, multiple=False): |
1010
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
951 """get data from a POST request or from URL's query part and decode it |
931
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
952 |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
953 @param request(server.Request): request linked to the session |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
954 @param keys(unicode, iterable[unicode]): name of the value(s) to get |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
955 unicode to get one value |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
956 iterable to get more than one |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
957 @param multiple(bool): True if multiple values are possible/expected |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
958 if False, the first value is returned |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
959 @return (iterator[unicode], list[iterator[unicode], unicode, list[unicode]): values received for this(these) key(s) |
956
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
960 @raise KeyError: one specific key has been requested, and it is missing |
931
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
961 """ |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
962 if isinstance(keys, basestring): |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
963 keys = [keys] |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
964 get_first = True |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
965 else: |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
966 get_first = False |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
967 |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
968 ret = [] |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
969 for key in keys: |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
970 gen = (urllib.unquote(v).decode('utf-8') for v in request.args.get(key,[])) |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
971 if multiple: |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
972 ret.append(gen) |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
973 else: |
956
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
974 try: |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
975 ret.append(next(gen)) |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
976 except StopIteration: |
962 | 977 raise KeyError(key) |
931
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
978 |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
979 return ret[0] if get_first else ret |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
980 |
1009
b57f86bc1177
pages: added "multiple" argument to getAllPostedData
Goffi <goffi@goffi.org>
parents:
1003
diff
changeset
|
981 def getAllPostedData(self, request, except_=(), multiple=True): |
959 | 982 """get all posted data |
983 | |
984 @param request(server.Request): request linked to the session | |
985 @param except_(iterable[unicode]): key of values to ignore | |
986 csrf_token will always be ignored | |
1009
b57f86bc1177
pages: added "multiple" argument to getAllPostedData
Goffi <goffi@goffi.org>
parents:
1003
diff
changeset
|
987 @param multiple(bool): if False, only the first values are returned |
959 | 988 @return (dict[unicode, list[unicode]]): post values |
989 """ | |
990 except_ = tuple(except_) + (u'csrf_token',) | |
991 ret = {} | |
992 for key, values in request.args.iteritems(): | |
993 key = urllib.unquote(key).decode('utf-8') | |
994 if key in except_: | |
995 continue | |
1009
b57f86bc1177
pages: added "multiple" argument to getAllPostedData
Goffi <goffi@goffi.org>
parents:
1003
diff
changeset
|
996 if not multiple: |
b57f86bc1177
pages: added "multiple" argument to getAllPostedData
Goffi <goffi@goffi.org>
parents:
1003
diff
changeset
|
997 ret[key] = urllib.unquote(values[0]).decode('utf-8') |
b57f86bc1177
pages: added "multiple" argument to getAllPostedData
Goffi <goffi@goffi.org>
parents:
1003
diff
changeset
|
998 else: |
b57f86bc1177
pages: added "multiple" argument to getAllPostedData
Goffi <goffi@goffi.org>
parents:
1003
diff
changeset
|
999 ret[key] = [urllib.unquote(v).decode('utf-8') for v in values] |
959 | 1000 return ret |
1001 | |
922
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1002 def getProfile(self, request): |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1003 """helper method to easily get current profile |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1004 |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1005 @return (unicode, None): current profile |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1006 None if no profile session is started |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1007 """ |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1008 sat_session = self.host.getSessionData(request, session_iface.ISATSession) |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1009 return sat_session.profile |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1010 |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1011 def getRData(self, request): |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1012 """helper method to get request data dict |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1013 |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1014 this dictionnary if for the request only, it is not saved in session |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1015 It is mainly used to pass data between pages/methods called during request workflow |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1016 @return (dict): request data |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1017 """ |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1018 try: |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1019 return request.data |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1020 except AttributeError: |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1021 request.data = {} |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1022 return request.data |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1023 |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1024 def _checkAccess(self, data, request): |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1025 """Check access according to self.access |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1026 |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1027 if access is not granted, show a HTTP_UNAUTHORIZED pageError and stop request, |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1028 else return data (so it can be inserted in deferred chain |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1029 """ |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1030 if self.access == C.PAGES_ACCESS_PUBLIC: |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1031 pass |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1032 elif self.access == C.PAGES_ACCESS_PROFILE: |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1033 profile = self.getProfile(request) |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1034 if not profile: |
962 | 1035 # no session started |
1036 if not self.host.options["allow_registration"]: | |
1037 # registration not allowed, access is not granted | |
1038 self.pageError(request, C.HTTP_UNAUTHORIZED) | |
1039 else: | |
1040 # registration allowed, we redirect to login page | |
1041 login_url = self.getPageRedirectURL(request) | |
1042 self.HTTPRedirect(request, login_url) | |
922
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1043 |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1044 return data |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1045 |
995 | 1046 def renderPartial(self, request, template, template_data): |
1047 """Render a template to be inserted in dynamic page | |
1048 | |
1049 this is NOT the normal page rendering method, it is used only to update | |
1050 dynamic pages | |
1051 @param template(unicode): path of the template to render | |
1052 @param template_data(dict): template_data to use | |
1053 """ | |
1054 if not self.dynamic: | |
1055 raise exceptions.InternalError(_(u"renderPartial must only be used with dynamic pages")) | |
1056 session_data = self.host.getSessionData(request, session_iface.ISATSession) | |
1057 | |
1058 return self.host.renderer.render( | |
1059 template, | |
1060 root_path = '/templates/', | |
1061 media_path = '/' + C.MEDIA_DIR, | |
1062 cache_path = session_data.cache_dir, | |
1063 main_menu = LiberviaPage.main_menu, | |
1064 **template_data) | |
1065 | |
1066 def renderAndUpdate(self, request, template, selectors, template_data_update, update_type="append"): | |
1067 """Helper method to render a partial page element and update the page | |
1068 | |
1069 this is NOT the normal page rendering method, it is used only to update | |
1070 dynamic pages | |
1071 @param request(server.Request): current HTTP request | |
1072 @param template: same as for [renderPartial] | |
1073 @param selectors: CSS selectors to use | |
1074 @param template_data_update: template data to use | |
1075 template data cached in request will be copied then updated | |
1076 with this data | |
1077 @parap update_type(unicode): one of: | |
1078 append: append rendered element to selected element | |
1079 """ | |
1080 template_data = request.template_data.copy() | |
1081 template_data.update(template_data_update) | |
1082 html = self.renderPartial(request, template, template_data) | |
1083 request.sendData(u'dom', | |
1084 selectors=selectors, | |
1085 update_type=update_type, | |
1086 html=html) | |
1087 | |
923
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
1088 def renderPage(self, request, skip_parse_url=False): |
937
00236973e138
server (pages): an HTTP internal error is raised if an error is uncatched during page workflow
Goffi <goffi@goffi.org>
parents:
936
diff
changeset
|
1089 """Main method to handle the workflow of a LiberviaPage""" |
994
b92b06f023cb
pages: profile is now always set in template_data, and None if there is no user logged
Goffi <goffi@goffi.org>
parents:
990
diff
changeset
|
1090 |
923
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
1091 # template_data are the variables passed to template |
917 | 1092 if not hasattr(request, 'template_data'): |
957
67bf14c91d5c
server (pages): added a confirm flag on successful post:
Goffi <goffi@goffi.org>
parents:
956
diff
changeset
|
1093 session_data = self.host.getSessionData(request, session_iface.ISATSession) |
67bf14c91d5c
server (pages): added a confirm flag on successful post:
Goffi <goffi@goffi.org>
parents:
956
diff
changeset
|
1094 csrf_token = session_data.csrf_token |
994
b92b06f023cb
pages: profile is now always set in template_data, and None if there is no user logged
Goffi <goffi@goffi.org>
parents:
990
diff
changeset
|
1095 request.template_data = {u'profile': session_data.profile, |
b92b06f023cb
pages: profile is now always set in template_data, and None if there is no user logged
Goffi <goffi@goffi.org>
parents:
990
diff
changeset
|
1096 u'csrf_token': csrf_token} |
922
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1097 |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1098 # XXX: here is the code which need to be executed once |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1099 # at the beginning of the request hanling |
917 | 1100 if request.postpath and not request.postpath[-1]: |
1101 # we don't differenciate URLs finishing with '/' or not | |
1102 del request.postpath[-1] | |
922
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1103 |
917 | 1104 d = defer.Deferred() |
922
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1105 d.addCallback(self._checkAccess, request) |
16d1084d1371
server (pages): added "None" access (page is not rendered at all) and some HTTP code constants + helper methods to get session data
Goffi <goffi@goffi.org>
parents:
921
diff
changeset
|
1106 |
923
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
1107 if self.redirect is not None: |
1015 | 1108 d.addCallback(lambda dummy: self.pageRedirect(self.redirect, request, skip_parse_url=False)) |
923
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
1109 |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
1110 if self.parse_url is not None and not skip_parse_url: |
1018 | 1111 if self.url_cache: |
1112 profile = self.getProfile(request) | |
1113 try: | |
1114 cache_url = self.cached_urls[profile][request.uri] | |
1115 except KeyError: | |
1116 # no cache for this URI yet | |
1117 # we do normal URL parsing, and then the cache | |
1118 d.addCallback(self.parse_url, request) | |
1119 d.addCallback(self._cacheURL, request, profile) | |
1120 else: | |
1121 log.debug(_(u"using URI cache for {page}").format(page=self)) | |
1122 cache_url.use(request) | |
1123 else: | |
1124 d.addCallback(self.parse_url, request) | |
917 | 1125 |
1126 d.addCallback(self._subpagesHandler, request) | |
1127 | |
931
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1128 if request.method not in (C.HTTP_METHOD_GET, C.HTTP_METHOD_POST): |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1129 # only HTTP GET and POST are handled so far |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1130 d.addCallback(lambda dummy: self.pageError(request, C.HTTP_BAD_REQUEST)) |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1131 |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1132 if request.method == C.HTTP_METHOD_POST: |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1133 if self.on_data_post is None: |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1134 # if we don't have on_data_post, the page was not expecting POST |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1135 # so we return an error |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1136 d.addCallback(lambda dummy: self.pageError(request, C.HTTP_BAD_REQUEST)) |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1137 else: |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1138 d.addCallback(self._on_data_post, request) |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1139 # by default, POST follow normal behaviour after on_data_post is called |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1140 # this can be changed by a redirection or other method call in on_data_post |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1141 |
998
0848b8b0188d
pages: dynamic set up is now done just before prepare_render call:
Goffi <goffi@goffi.org>
parents:
995
diff
changeset
|
1142 if self.dynamic: |
0848b8b0188d
pages: dynamic set up is now done just before prepare_render call:
Goffi <goffi@goffi.org>
parents:
995
diff
changeset
|
1143 d.addCallback(self._prepare_dynamic, request) |
0848b8b0188d
pages: dynamic set up is now done just before prepare_render call:
Goffi <goffi@goffi.org>
parents:
995
diff
changeset
|
1144 |
917 | 1145 if self.prepare_render: |
1146 d.addCallback(self._prepare_render, request) | |
1147 | |
1148 if self.template: | |
962 | 1149 d.addCallback(self._render_template, request) |
917 | 1150 elif self.render_method: |
1151 d.addCallback(self._render_method, request) | |
1152 | |
1153 d.addCallback(self.writeData, request) | |
1154 d.addErrback(self._renderEb, request) | |
937
00236973e138
server (pages): an HTTP internal error is raised if an error is uncatched during page workflow
Goffi <goffi@goffi.org>
parents:
936
diff
changeset
|
1155 d.addErrback(self._internalError, request) |
917 | 1156 d.callback(self) |
1157 return server.NOT_DONE_YET | |
1158 | |
923
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
1159 def render_GET(self, request): |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
1160 return self.renderPage(request) |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
1161 |
931
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1162 def render_POST(self, request): |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1163 return self.renderPage(request) |