Mercurial > libervia-web
annotate src/server/pages.py @ 1082:8d8b88bfddad
pages: default menu update
author | Goffi <goffi@goffi.org> |
---|---|
date | Tue, 27 Mar 2018 08:40:27 +0200 |
parents | 8f77e36cd51d |
children | 63ed5f6bd4eb |
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 |
1054 | 5 # Copyright (C) 2011-2018 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 |
1059
d127a85b2fee
pages: don't log error anymore when empty page_meta.py are used
Goffi <goffi@goffi.org>
parents:
1056
diff
changeset
|
205 if template is not None and render is not None: |
d127a85b2fee
pages: don't log error anymore when empty page_meta.py are used
Goffi <goffi@goffi.org>
parents:
1056
diff
changeset
|
206 log.error(_(u"render and template methods can't be used at the same time")) |
917 | 207 if parse_url is not None and not callable(parse_url): |
208 log.error(_(u"parse_url must be a callable")) | |
209 | |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
210 # if not None, next rendering will be cached |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
211 # 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
|
212 # 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
|
213 self._do_cache = None |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
214 |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
215 def __unicode__(self): |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
216 return u'LiberviaPage {name} at {url}'.format( |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
217 name = self.name or u'<anonymous>', |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
218 url = self.url) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
219 |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
220 def __str__(self): |
1013
841a595bee5a
pages: fixed str representation of LiberviaPage
Goffi <goffi@goffi.org>
parents:
1010
diff
changeset
|
221 return self.__unicode__().encode('utf-8') |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
222 |
925 | 223 @classmethod |
224 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
|
225 """Recursively import Libervia pages""" |
917 | 226 if path is None: |
227 path = [] | |
228 if parent is None: | |
229 root_dir = os.path.join(os.path.dirname(libervia.__file__), C.PAGES_DIR) | |
230 parent = host | |
231 else: | |
232 root_dir = parent.root_dir | |
233 for d in os.listdir(root_dir): | |
234 dir_path = os.path.join(root_dir, d) | |
235 if not os.path.isdir(dir_path): | |
236 continue | |
237 meta_path = os.path.join(dir_path, C.PAGES_META_FILE) | |
238 if os.path.isfile(meta_path): | |
239 page_data = {} | |
962 | 240 new_path = path + [d] |
917 | 241 # we don't want to force the presence of __init__.py |
242 # so we use execfile instead of import. | |
243 # TODO: when moved to Python 3, __init__.py is not mandatory anymore | |
244 # so we can switch to import | |
245 execfile(meta_path, page_data) | |
246 resource = LiberviaPage( | |
247 host, | |
248 dir_path, | |
962 | 249 u'/' + u'/'.join(new_path), |
917 | 250 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
|
251 redirect=page_data.get('redirect'), |
917 | 252 access=page_data.get('access'), |
995 | 253 dynamic=page_data.get('dynamic', False), |
917 | 254 parse_url=page_data.get('parse_url'), |
255 prepare_render=page_data.get('prepare_render'), | |
256 render=page_data.get('render'), | |
931
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
257 template=page_data.get('template'), |
995 | 258 on_data_post=page_data.get('on_data_post'), |
259 on_data=page_data.get('on_data'), | |
260 on_signal=page_data.get('on_signal'), | |
1018 | 261 url_cache=page_data.get('url_cache', False), |
995 | 262 ) |
917 | 263 parent.putChild(d, resource) |
264 log.info(u"Added /{path} page".format(path=u'[...]/'.join(new_path))) | |
925 | 265 if 'uri_handlers' in page_data: |
266 if not isinstance(page_data, dict): | |
267 log.error(_(u'uri_handlers must be a dict')) | |
268 else: | |
269 for uri_tuple, cb_name in page_data['uri_handlers'].iteritems(): | |
270 if len(uri_tuple) != 2 or not isinstance(cb_name, basestring): | |
271 log.error(_(u"invalid uri_tuple")) | |
272 continue | |
273 log.info(_(u'setting {}/{} URIs handler').format(*uri_tuple)) | |
274 try: | |
275 cb = page_data[cb_name] | |
276 except KeyError: | |
277 log.error(_(u'missing {name} method to handle {1}/{2}').format( | |
278 name = cb_name, *uri_tuple)) | |
279 continue | |
280 else: | |
1038 | 281 resource.registerURI(uri_tuple, cb) |
925 | 282 |
917 | 283 LiberviaPage.importPages(host, resource, new_path) |
284 | |
925 | 285 @classmethod |
990
6daa59d44ee2
pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents:
985
diff
changeset
|
286 def setMenu(cls, menus): |
6daa59d44ee2
pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents:
985
diff
changeset
|
287 main_menu = [] |
6daa59d44ee2
pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents:
985
diff
changeset
|
288 for menu in menus: |
6daa59d44ee2
pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents:
985
diff
changeset
|
289 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
|
290 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
|
291 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
|
292 raise ValueError(msg) |
990
6daa59d44ee2
pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents:
985
diff
changeset
|
293 elif isinstance(menu, list): |
6daa59d44ee2
pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents:
985
diff
changeset
|
294 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
|
295 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
|
296 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
|
297 raise ValueError(msg) |
990
6daa59d44ee2
pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents:
985
diff
changeset
|
298 page_name, url = menu |
6daa59d44ee2
pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents:
985
diff
changeset
|
299 else: |
6daa59d44ee2
pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents:
985
diff
changeset
|
300 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
|
301 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
|
302 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
|
303 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
|
304 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
|
305 raise e |
990
6daa59d44ee2
pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents:
985
diff
changeset
|
306 main_menu.append((page_name, url)) |
6daa59d44ee2
pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents:
985
diff
changeset
|
307 cls.main_menu = main_menu |
6daa59d44ee2
pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents:
985
diff
changeset
|
308 |
1038 | 309 def registerURI(self, uri_tuple, get_uri_cb): |
925 | 310 """register a URI handler |
311 | |
312 @param uri_tuple(tuple[unicode, unicode]): type or URIs handler | |
313 type/subtype as returned by tools/common/parseXMPPUri | |
1038 | 314 or type/None to handle all subtypes |
925 | 315 @param get_uri_cb(callable): method which take uri_data dict as only argument |
1038 | 316 and return absolute path with correct arguments or None if the page |
317 can't handle this URL | |
925 | 318 """ |
1038 | 319 if uri_tuple in self.uri_callbacks: |
925 | 320 log.info(_(u"{}/{} URIs are already handled, replacing by the new handler").format(*uri_tuple)) |
1038 | 321 self.uri_callbacks[uri_tuple] = (self, get_uri_cb) |
925 | 322 |
995 | 323 def registerSignal(self, request, signal, check_profile=True): |
324 r"""register a signal handler | |
325 | |
326 the page must be dynamic | |
327 when signal is received, self.on_signal will be called with: | |
328 - request | |
329 - signal name | |
330 - signal arguments | |
331 signal handler will be removed when connection with dynamic page will be lost | |
332 @param signal(unicode): name of the signal | |
333 last arg of signal must be profile, as it will be checked to filter signals | |
334 @param check_profile(bool): if True, signal profile (which MUST be last arg) will be | |
335 checked against session profile. | |
336 /!\ if False, profile will not be checked/filtered, be sure to know what you are doing | |
337 if you unset this option /!\ | |
338 """ | |
339 # FIXME: add a timeout, if socket is not opened before it, signal handler must be removed | |
340 if not self.dynamic: | |
341 log.error(_(u"You can't register signal if page is not dynamic")) | |
342 return | |
343 LiberviaPage.signals_handlers.setdefault(signal, {})[id(request)] = (self, request, check_profile) | |
344 request._signals_registered.append(signal) | |
345 | |
1038 | 346 @classmethod |
347 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
|
348 """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
|
349 |
bb4dfc2802c0
server (pages): added getPagePathFromURI method to retrieve page handling an URI
Goffi <goffi@goffi.org>
parents:
926
diff
changeset
|
350 @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
|
351 @return (unicode,None): absolute path (starting from root "/") to page handling the URI |
1038 | 352 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
|
353 """ |
bb4dfc2802c0
server (pages): added getPagePathFromURI method to retrieve page handling an URI
Goffi <goffi@goffi.org>
parents:
926
diff
changeset
|
354 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
|
355 try: |
1038 | 356 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
|
357 except KeyError: |
1038 | 358 url = None |
927
bb4dfc2802c0
server (pages): added getPagePathFromURI method to retrieve page handling an URI
Goffi <goffi@goffi.org>
parents:
926
diff
changeset
|
359 else: |
1038 | 360 url = cb(page, uri_data) |
361 if url is None: | |
362 # no handler found | |
363 # we try to find a more generic one | |
364 try: | |
365 page, cb = cls.uri_callbacks[uri_data['type'], None] | |
366 except KeyError: | |
367 pass | |
368 else: | |
369 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
|
370 return url |
bb4dfc2802c0
server (pages): added getPagePathFromURI method to retrieve page handling an URI
Goffi <goffi@goffi.org>
parents:
926
diff
changeset
|
371 |
979 | 372 @classmethod |
373 def getPageByName(cls, name): | |
936
78692d47340d
server (pages): added getPageByName
Goffi <goffi@goffi.org>
parents:
935
diff
changeset
|
374 """retrieve page instance from its name |
78692d47340d
server (pages): added getPageByName
Goffi <goffi@goffi.org>
parents:
935
diff
changeset
|
375 |
78692d47340d
server (pages): added getPageByName
Goffi <goffi@goffi.org>
parents:
935
diff
changeset
|
376 @param name(unicode): name of the page |
78692d47340d
server (pages): added getPageByName
Goffi <goffi@goffi.org>
parents:
935
diff
changeset
|
377 @return (LiberviaPage): page instance |
78692d47340d
server (pages): added getPageByName
Goffi <goffi@goffi.org>
parents:
935
diff
changeset
|
378 @raise KeyError: the page doesn't exist |
78692d47340d
server (pages): added getPageByName
Goffi <goffi@goffi.org>
parents:
935
diff
changeset
|
379 """ |
979 | 380 return cls.named_pages[name] |
936
78692d47340d
server (pages): added getPageByName
Goffi <goffi@goffi.org>
parents:
935
diff
changeset
|
381 |
962 | 382 def getPageRedirectURL(self, request, page_name=u'login', url=None): |
383 """generate URL for a page with redirect_url parameter set | |
384 | |
385 mainly used for login page with redirection to current page | |
386 @param request(server.Request): current HTTP request | |
387 @param page_name(unicode): name of the page to go | |
388 @param url(None, unicode): url to redirect to | |
389 None to use request path (i.e. current page) | |
390 @return (unicode): URL to use | |
391 """ | |
392 return u'{root_url}?redirect_url={redirect_url}'.format( | |
393 root_url = self.getPageByName(page_name).url, | |
394 redirect_url=urllib.quote_plus(request.uri) if url is None else url.encode('utf-8')) | |
395 | |
972
c4e58c4dba75
server: getURL + minor improvments:
Goffi <goffi@goffi.org>
parents:
968
diff
changeset
|
396 def getURL(self, *args): |
c4e58c4dba75
server: getURL + minor improvments:
Goffi <goffi@goffi.org>
parents:
968
diff
changeset
|
397 """retrieve URL of the page set arguments |
c4e58c4dba75
server: getURL + minor improvments:
Goffi <goffi@goffi.org>
parents:
968
diff
changeset
|
398 |
c4e58c4dba75
server: getURL + minor improvments:
Goffi <goffi@goffi.org>
parents:
968
diff
changeset
|
399 *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
|
400 empty or None arguments will be ignored |
972
c4e58c4dba75
server: getURL + minor improvments:
Goffi <goffi@goffi.org>
parents:
968
diff
changeset
|
401 """ |
1014
dfced7992460
pages: ignore empty or unset arguments in getURL
Goffi <goffi@goffi.org>
parents:
1013
diff
changeset
|
402 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
|
403 |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
404 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
|
405 # we check for redirection |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
406 redirect_data = self.pages_redirects[self.name] |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
407 args_hash = tuple(args) |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
408 for limit in xrange(len(args)+1): |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
409 current_hash = args_hash[:limit] |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
410 if current_hash in redirect_data: |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
411 url_base = redirect_data[current_hash] |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
412 remaining = args[limit:] |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
413 remaining_url = '/'.join(remaining) |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
414 return os.path.join('/', url_base, remaining_url) |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
415 |
972
c4e58c4dba75
server: getURL + minor improvments:
Goffi <goffi@goffi.org>
parents:
968
diff
changeset
|
416 return os.path.join(self.url, *url_args) |
c4e58c4dba75
server: getURL + minor improvments:
Goffi <goffi@goffi.org>
parents:
968
diff
changeset
|
417 |
1010
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
418 def getCurrentURL(self, request): |
1015 | 419 """retrieve URL used to access this page |
1010
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
420 |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
421 @return(unicode): current URL |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
422 """ |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
423 # 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
|
424 # request.prepath) because request.prepath may have been modified by |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
425 # redirection (if redirection args have been specified), while path reflect |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
426 # the real request |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
427 |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
428 # 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
|
429 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
|
430 |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
431 if request.postpath: |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
432 if not request.postpath[-1]: |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
433 # we remove trailing slash |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
434 request.postpath = request.postpath[:-1] |
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 # getSubPageURL must return subpage from the point where |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
437 # the it is called, so we have to remove remanining |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
438 # path elements |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
439 path_elts = path_elts[:-len(request.postpath)] |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
440 |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
441 return u'/' + '/'.join(path_elts).decode('utf-8') |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
442 |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
443 def getParamURL(self, request, **kwargs): |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
444 """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
|
445 |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
446 **kwargs(dict[str, unicode]): argument to use as query parameters |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
447 @return (unicode): constructed URL |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
448 """ |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
449 current_url = self.getCurrentURL(request) |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
450 if kwargs: |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
451 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
|
452 current_url = current_url + u'?' + encoded |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
453 return current_url |
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
454 |
1030
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
455 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
|
456 """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
|
457 |
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
458 @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
|
459 @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
|
460 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
|
461 @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
|
462 @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
|
463 """ |
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
464 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
|
465 try: |
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
466 child_name = child.name |
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
467 except AttributeError: |
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
468 # 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
|
469 continue |
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
470 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
|
471 return path, child |
66a050b32df8
pages: moved code getting subpage from getSubPageURL to new getSubPageByName method.
Goffi <goffi@goffi.org>
parents:
1019
diff
changeset
|
472 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
|
473 |
980
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
474 def getSubPageURL(self, request, page_name, *args): |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
475 """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
|
476 |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
477 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
|
478 i.e. it's more prepath than path). |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
479 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
|
480 by the resulting combination. |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
481 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
|
482 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
|
483 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
|
484 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
|
485 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
|
486 and potential redirections. |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
487 @param request(server.Request): current HTTP request |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
488 @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
|
489 it must be a direct children of current page |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
490 @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
|
491 @return unicode: absolute URL to the sub page |
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
492 """ |
1010
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
493 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
|
494 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
|
495 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
|
496 |
1031
4ba7df23b976
pages: new method getURLByNames to retrieve URL from list of page names/path arguments
Goffi <goffi@goffi.org>
parents:
1030
diff
changeset
|
497 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
|
498 """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
|
499 |
4ba7df23b976
pages: new method getURLByNames to retrieve URL from list of page names/path arguments
Goffi <goffi@goffi.org>
parents:
1030
diff
changeset
|
500 @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
|
501 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
|
502 - 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
|
503 - 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
|
504 @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
|
505 @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
|
506 """ |
4ba7df23b976
pages: new method getURLByNames to retrieve URL from list of page names/path arguments
Goffi <goffi@goffi.org>
parents:
1030
diff
changeset
|
507 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
|
508 path = [] |
4ba7df23b976
pages: new method getURLByNames to retrieve URL from list of page names/path arguments
Goffi <goffi@goffi.org>
parents:
1030
diff
changeset
|
509 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
|
510 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
|
511 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
|
512 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
|
513 else: |
4ba7df23b976
pages: new method getURLByNames to retrieve URL from list of page names/path arguments
Goffi <goffi@goffi.org>
parents:
1030
diff
changeset
|
514 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
|
515 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
|
516 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
|
517 path.extend([quote(a) for a in page_args]) |
1041
688b52897ba0
pages: check redirections on getURLByNames
Goffi <goffi@goffi.org>
parents:
1038
diff
changeset
|
518 return self.host.checkRedirection(u'/'.join(path)) |
980
bcacf970f970
core (pages redirection): inverted redirection + getSubPageURL:
Goffi <goffi@goffi.org>
parents:
979
diff
changeset
|
519 |
917 | 520 def getChildWithDefault(self, path, request): |
521 # we handle children ourselves | |
522 raise exceptions.InternalError(u"this method should not be used with LiberviaPage") | |
523 | |
524 def nextPath(self, request): | |
525 """get next URL path segment, and update request accordingly | |
526 | |
527 will move first segment of postpath in prepath | |
528 @param request(server.Request): current HTTP request | |
529 @return (unicode): unquoted segment | |
530 @raise IndexError: there is no segment left | |
531 """ | |
532 pathElement = request.postpath.pop(0) | |
533 request.prepath.append(pathElement) | |
534 return urllib.unquote(pathElement).decode('utf-8') | |
535 | |
1060
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
536 def _filterPathValue(self, value, handler, name, request): |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
537 """Modify a path value according to handler (see [getPathArgs])""" |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
538 if handler in (u'@', u'@jid') and value == u'@': |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
539 value = None |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
540 |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
541 if handler in (u'', u'@'): |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
542 if value is None: |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
543 return u'' |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
544 elif handler in (u'jid', u'@jid'): |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
545 if value: |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
546 try: |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
547 return jid.JID(value) |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
548 except RuntimeError: |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
549 log.warning(_(u'invalid jid argument: {value}').format(value=value)) |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
550 self.pageError(request, C.HTTP_BAD_REQUEST) |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
551 else: |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
552 return u'' |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
553 else: |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
554 return handler(self, value, name, request) |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
555 |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
556 return value |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
557 |
1056
47c354ca66a3
pages: new getPathArgs helper method to retrieve several path arguments at once
Goffi <goffi@goffi.org>
parents:
1054
diff
changeset
|
558 def getPathArgs(self, request, names, min_args=0, **kwargs): |
47c354ca66a3
pages: new getPathArgs helper method to retrieve several path arguments at once
Goffi <goffi@goffi.org>
parents:
1054
diff
changeset
|
559 """get several path arguments at once |
47c354ca66a3
pages: new getPathArgs helper method to retrieve several path arguments at once
Goffi <goffi@goffi.org>
parents:
1054
diff
changeset
|
560 |
47c354ca66a3
pages: new getPathArgs helper method to retrieve several path arguments at once
Goffi <goffi@goffi.org>
parents:
1054
diff
changeset
|
561 Arguments will be put in request data. |
47c354ca66a3
pages: new getPathArgs helper method to retrieve several path arguments at once
Goffi <goffi@goffi.org>
parents:
1054
diff
changeset
|
562 Missing arguments will have None value |
47c354ca66a3
pages: new getPathArgs helper method to retrieve several path arguments at once
Goffi <goffi@goffi.org>
parents:
1054
diff
changeset
|
563 @param names(list[unicode]): list of arguments to get |
47c354ca66a3
pages: new getPathArgs helper method to retrieve several path arguments at once
Goffi <goffi@goffi.org>
parents:
1054
diff
changeset
|
564 @param min_args(int): if less than min_args are found, PageError is used with C.HTTP_BAD_REQUEST |
1065
5f97118dc82a
pages: fixed min_args for getPathArgs
Goffi <goffi@goffi.org>
parents:
1062
diff
changeset
|
565 use 0 to ignore |
1056
47c354ca66a3
pages: new getPathArgs helper method to retrieve several path arguments at once
Goffi <goffi@goffi.org>
parents:
1054
diff
changeset
|
566 @param **kwargs: special value or optional callback to use for arguments |
47c354ca66a3
pages: new getPathArgs helper method to retrieve several path arguments at once
Goffi <goffi@goffi.org>
parents:
1054
diff
changeset
|
567 names of the arguments must correspond to those in names |
47c354ca66a3
pages: new getPathArgs helper method to retrieve several path arguments at once
Goffi <goffi@goffi.org>
parents:
1054
diff
changeset
|
568 special values may be: |
47c354ca66a3
pages: new getPathArgs helper method to retrieve several path arguments at once
Goffi <goffi@goffi.org>
parents:
1054
diff
changeset
|
569 - '': use empty string instead of None when no value is specified |
47c354ca66a3
pages: new getPathArgs helper method to retrieve several path arguments at once
Goffi <goffi@goffi.org>
parents:
1054
diff
changeset
|
570 - '@': if value of argument is empty or '@', empty string will be used |
47c354ca66a3
pages: new getPathArgs helper method to retrieve several path arguments at once
Goffi <goffi@goffi.org>
parents:
1054
diff
changeset
|
571 - 'jid': value must be converted to jid.JID if it exists, else empty string is used |
47c354ca66a3
pages: new getPathArgs helper method to retrieve several path arguments at once
Goffi <goffi@goffi.org>
parents:
1054
diff
changeset
|
572 - '@jid': if value of arguments is empty or '@', empty string will be used, else it will be converted to jid |
47c354ca66a3
pages: new getPathArgs helper method to retrieve several path arguments at once
Goffi <goffi@goffi.org>
parents:
1054
diff
changeset
|
573 """ |
47c354ca66a3
pages: new getPathArgs helper method to retrieve several path arguments at once
Goffi <goffi@goffi.org>
parents:
1054
diff
changeset
|
574 data = self.getRData(request) |
47c354ca66a3
pages: new getPathArgs helper method to retrieve several path arguments at once
Goffi <goffi@goffi.org>
parents:
1054
diff
changeset
|
575 |
47c354ca66a3
pages: new getPathArgs helper method to retrieve several path arguments at once
Goffi <goffi@goffi.org>
parents:
1054
diff
changeset
|
576 for idx, name in enumerate(names): |
1060
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
577 if name[0] == u'*': |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
578 value = data[name[1:]] = [] |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
579 while True: |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
580 try: |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
581 value.append(self.nextPath(request)) |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
582 except IndexError: |
1065
5f97118dc82a
pages: fixed min_args for getPathArgs
Goffi <goffi@goffi.org>
parents:
1062
diff
changeset
|
583 idx-=1 |
1060
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
584 break |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
585 else: |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
586 idx+=1 |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
587 else: |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
588 try: |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
589 value = data[name] = self.nextPath(request) |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
590 except IndexError: |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
591 data[name] = None |
1071
8f77e36cd51d
pages: fixed args count in getPathArgs
Goffi <goffi@goffi.org>
parents:
1065
diff
changeset
|
592 idx-=1 |
1060
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
593 break |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
594 |
1071
8f77e36cd51d
pages: fixed args count in getPathArgs
Goffi <goffi@goffi.org>
parents:
1065
diff
changeset
|
595 values_count = idx+1 |
8f77e36cd51d
pages: fixed args count in getPathArgs
Goffi <goffi@goffi.org>
parents:
1065
diff
changeset
|
596 if values_count < min_args: |
8f77e36cd51d
pages: fixed args count in getPathArgs
Goffi <goffi@goffi.org>
parents:
1065
diff
changeset
|
597 log.warning(_(u"Missing arguments in URL (got {count}, expected at least {min_args})").format( |
8f77e36cd51d
pages: fixed args count in getPathArgs
Goffi <goffi@goffi.org>
parents:
1065
diff
changeset
|
598 count = values_count, min_args = min_args)) |
1060
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
599 self.pageError(request, C.HTTP_BAD_REQUEST) |
1056
47c354ca66a3
pages: new getPathArgs helper method to retrieve several path arguments at once
Goffi <goffi@goffi.org>
parents:
1054
diff
changeset
|
600 |
1071
8f77e36cd51d
pages: fixed args count in getPathArgs
Goffi <goffi@goffi.org>
parents:
1065
diff
changeset
|
601 for name in names[values_count:]: |
1056
47c354ca66a3
pages: new getPathArgs helper method to retrieve several path arguments at once
Goffi <goffi@goffi.org>
parents:
1054
diff
changeset
|
602 data[name] = None |
47c354ca66a3
pages: new getPathArgs helper method to retrieve several path arguments at once
Goffi <goffi@goffi.org>
parents:
1054
diff
changeset
|
603 |
47c354ca66a3
pages: new getPathArgs helper method to retrieve several path arguments at once
Goffi <goffi@goffi.org>
parents:
1054
diff
changeset
|
604 for name, handler in kwargs.iteritems(): |
1060
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
605 if name[0] == '*': |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
606 data[name] = [self._filterPathValue(v, handler, name, request) for v in data[name]] |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
607 else: |
f0f7b3324749
pages: '*' can now be used to prefix the last arg name in getPathArgs, in which case the data will be a list of remaining path arguments.
Goffi <goffi@goffi.org>
parents:
1059
diff
changeset
|
608 data[name] = self._filterPathValue(data[name], handler, name, request) |
1056
47c354ca66a3
pages: new getPathArgs helper method to retrieve several path arguments at once
Goffi <goffi@goffi.org>
parents:
1054
diff
changeset
|
609 |
47c354ca66a3
pages: new getPathArgs helper method to retrieve several path arguments at once
Goffi <goffi@goffi.org>
parents:
1054
diff
changeset
|
610 |
1019
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
611 ## Cache handling ## |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
612 |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
613 def _setCacheHeaders(self, request, cache): |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
614 """Set ETag and Last-Modified HTTP headers, used for caching""" |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
615 request.setHeader('ETag', cache.hash) |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
616 last_modified = self.host.getHTTPDate(cache.created) |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
617 request.setHeader('Last-Modified', last_modified) |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
618 |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
619 def _checkCacheHeaders(self, request, cache): |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
620 """Check if a cache condition is set on the request |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
621 |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
622 if condition is valid, C.HTTP_NOT_MODIFIED is returned |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
623 """ |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
624 etag_match = request.getHeader('If-None-Match') |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
625 if etag_match is not None: |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
626 if cache.hash == etag_match: |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
627 self.pageError(request, C.HTTP_NOT_MODIFIED, no_body=True) |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
628 else: |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
629 modified_match = request.getHeader('If-Modified-Since') |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
630 if modified_match is not None: |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
631 modified = utils.date_parse(modified_match) |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
632 if modified >= int(cache.created): |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
633 self.pageError(request, C.HTTP_NOT_MODIFIED, no_body=True) |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
634 |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
635 def checkCacheSubscribeCb(self, sub_id, service, node): |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
636 self.cache_pubsub_sub.add((service, node, sub_id)) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
637 |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
638 def checkCacheSubscribeEb(self, failure_, service, node): |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
639 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
|
640 # FIXME: cache must be marked as unusable here |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
641 |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
642 def psNodeWatchAddEb(self, failure_, service, node): |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
643 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
|
644 |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
645 def checkCache(self, request, cache_type, **kwargs): |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
646 """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
|
647 |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
648 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
|
649 pubsub node) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
650 @param request(server.Request): current HTTP request |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
651 @param cache_type(int): on of C.CACHE_* const. |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
652 @param **kwargs: args according to cache_type: |
1010
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
653 C.CACHE_PUBSUB: |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
654 service: pubsub service |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
655 node: pubsub node |
1019
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
656 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
|
657 |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
658 """ |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
659 if request.postpath: |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
660 # 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
|
661 return |
1033
c34f08e05cdf
pages: cache is now working even after pageRedirect
Goffi <goffi@goffi.org>
parents:
1032
diff
changeset
|
662 |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
663 profile = self.getProfile(request) or C.SERVICE_PROFILE |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
664 |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
665 if cache_type == C.CACHE_PUBSUB: |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
666 service, node = kwargs['service'], kwargs['node'] |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
667 if not node: |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
668 try: |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
669 short = kwargs['short'] |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
670 node = self.host.ns_map[short] |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
671 except KeyError: |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
672 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
|
673 return |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
674 if profile != C.SERVICE_PROFILE: |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
675 # only service profile is cache for now |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
676 return |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
677 try: |
1052
cdf0ebed9db7
pages (caches): use request.uri to check cache, to avoid using same cache with pages using different parameters (e.g. different MAM filter for pubsub)
Goffi <goffi@goffi.org>
parents:
1049
diff
changeset
|
678 cache = self.cache[profile][cache_type][service][node][request.uri][self] |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
679 except KeyError: |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
680 # no cache yet, let's subscribe to the pubsub node |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
681 d1 = self.host.bridgeCall('psSubscribe', service.full(), node, {}, profile) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
682 d1.addCallback(self.checkCacheSubscribeCb, service, node) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
683 d1.addErrback(self.checkCacheSubscribeEb, service, node) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
684 d2 = self.host.bridgeCall('psNodeWatchAdd', service.full(), node, profile) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
685 d2.addErrback(self.psNodeWatchAddEb, service, node) |
1052
cdf0ebed9db7
pages (caches): use request.uri to check cache, to avoid using same cache with pages using different parameters (e.g. different MAM filter for pubsub)
Goffi <goffi@goffi.org>
parents:
1049
diff
changeset
|
686 self._do_cache = [self, profile, cache_type, service, node, request.uri] |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
687 # 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
|
688 # the subscription to continue with page rendering |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
689 return |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
690 |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
691 else: |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
692 raise exceptions.InternalError(u'Unknown cache_type') |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
693 log.debug(u'using cache for {page}'.format(page=self)) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
694 cache.last_access = time.time() |
1019
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
695 self._setCacheHeaders(request, cache) |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
696 self._checkCacheHeaders(request, cache) |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
697 request.write(cache.rendered) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
698 request.finish() |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
699 raise failure.Failure(exceptions.CancelError(u'cache is used')) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
700 |
1018 | 701 def _cacheURL(self, dummy, request, profile): |
702 self.cached_urls.setdefault(profile, {})[request.uri] = CacheURL(request) | |
703 | |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
704 @classmethod |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
705 def onNodeEvent(cls, host, service, node, event_type, items, profile): |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
706 """Invalidate cache for all pages linked to this node""" |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
707 try: |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
708 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
|
709 except KeyError: |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
710 log.info(_(u'Removing subscription for {service}/{node}: ' |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
711 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
|
712 d1 = host.bridgeCall('psUnsubscribe', service, node, profile) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
713 d1.addErrback(lambda failure_: |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
714 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
|
715 service=service, node=node, msg=failure_))) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
716 d2 = host.bridgeCall('psNodeWatchAdd', service, node, profile) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
717 # 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
|
718 d2.addErrback(lambda failure_: |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
719 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
|
720 service=service, node=node, msg=failure_))) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
721 else: |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
722 cache.clear() |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
723 |
995 | 724 @classmethod |
725 def onSignal(cls, host, signal, *args): | |
726 """Generic method which receive registered signals | |
727 | |
728 if a callback is registered for this signal, call it | |
729 @param host: Libervia instance | |
730 @param signal(unicode): name of the signal | |
731 @param *args: args of the signals | |
732 """ | |
733 for page, request, check_profile in cls.signals_handlers.get(signal, {}).itervalues(): | |
734 if check_profile: | |
735 signal_profile = args[-1] | |
736 request_profile = page.getProfile(request) | |
737 if not request_profile: | |
738 # if you want to use signal without session, unset check_profile | |
739 # (be sure to know what you are doing) | |
740 log.error(_(u"no session started, signal can't be checked")) | |
741 continue | |
742 if signal_profile != request_profile: | |
743 # we ignore the signal, it's not for our profile | |
744 continue | |
745 if request._signals_cache is not None: | |
746 # socket is not yet opened, we cache the signal | |
747 request._signals_cache.append((request, signal, args)) | |
748 log.debug(u"signal [{signal}] cached: {args}".format( | |
749 signal = signal, | |
750 args = args)) | |
751 else: | |
752 page.on_signal(page, request, signal, *args) | |
753 | |
754 def onSocketOpen(self, request): | |
755 """Called for dynamic pages when socket has just been opened | |
756 | |
757 we send all cached signals | |
758 """ | |
759 assert request._signals_cache is not None | |
760 cache = request._signals_cache | |
761 request._signals_cache = None | |
762 for request, signal, args in cache: | |
763 self.on_signal(self, request, signal, *args) | |
764 | |
765 def onSocketClose(self, request): | |
766 """Called for dynamic pages when socket has just been closed | |
767 | |
768 we remove signal handler | |
769 """ | |
770 for signal in request._signals_registered: | |
771 try: | |
772 del LiberviaPage.signals_handlers[signal][id(request)] | |
773 except KeyError: | |
774 log.error(_(u"Can't find signal handler for [{signal}], this should not happen").format( | |
775 signal = signal)) | |
776 else: | |
777 log.debug(_(u"Removed signal handler")) | |
778 | |
1062
c80649cdadd5
pages: new delegateToResource method to continue workflow with a Twisted Resource
Goffi <goffi@goffi.org>
parents:
1061
diff
changeset
|
779 def delegateToResource(self, request, resource): |
c80649cdadd5
pages: new delegateToResource method to continue workflow with a Twisted Resource
Goffi <goffi@goffi.org>
parents:
1061
diff
changeset
|
780 """continue workflow with Twisted Resource""" |
c80649cdadd5
pages: new delegateToResource method to continue workflow with a Twisted Resource
Goffi <goffi@goffi.org>
parents:
1061
diff
changeset
|
781 buf = resource.render(request) |
c80649cdadd5
pages: new delegateToResource method to continue workflow with a Twisted Resource
Goffi <goffi@goffi.org>
parents:
1061
diff
changeset
|
782 if buf == server.NOT_DONE_YET: |
c80649cdadd5
pages: new delegateToResource method to continue workflow with a Twisted Resource
Goffi <goffi@goffi.org>
parents:
1061
diff
changeset
|
783 pass |
c80649cdadd5
pages: new delegateToResource method to continue workflow with a Twisted Resource
Goffi <goffi@goffi.org>
parents:
1061
diff
changeset
|
784 else: |
c80649cdadd5
pages: new delegateToResource method to continue workflow with a Twisted Resource
Goffi <goffi@goffi.org>
parents:
1061
diff
changeset
|
785 request.write(buf) |
c80649cdadd5
pages: new delegateToResource method to continue workflow with a Twisted Resource
Goffi <goffi@goffi.org>
parents:
1061
diff
changeset
|
786 request.finish() |
c80649cdadd5
pages: new delegateToResource method to continue workflow with a Twisted Resource
Goffi <goffi@goffi.org>
parents:
1061
diff
changeset
|
787 raise failure.Failure(exceptions.CancelError(u'resource delegation')) |
c80649cdadd5
pages: new delegateToResource method to continue workflow with a Twisted Resource
Goffi <goffi@goffi.org>
parents:
1061
diff
changeset
|
788 |
962 | 789 def HTTPRedirect(self, request, url): |
790 """redirect to an URL using HTTP redirection | |
791 | |
792 @param request(server.Request): current HTTP request | |
793 @param url(unicode): url to redirect to | |
794 """ | |
795 web_util.redirectTo(url.encode('utf-8'), request) | |
796 request.finish() | |
797 raise failure.Failure(exceptions.CancelError(u'HTTP redirection is used')) | |
798 | |
799 def redirectOrContinue(self, request, redirect_arg=u'redirect_url'): | |
800 """helper method to redirect a page to an url given as arg | |
801 | |
802 if the arg is not present, the page will continue normal workflow | |
803 @param request(server.Request): current HTTP request | |
804 @param redirect_arg(unicode): argument to use to get redirection URL | |
805 @interrupt: redirect the page to requested URL | |
806 @interrupt pageError(C.HTTP_BAD_REQUEST): empty or non local URL is used | |
807 """ | |
808 try: | |
1061
bacb8f229742
pages: fixed unicode escaping when using a redirecting URL
Goffi <goffi@goffi.org>
parents:
1060
diff
changeset
|
809 url = request.args['redirect_url'][0] |
bacb8f229742
pages: fixed unicode escaping when using a redirecting URL
Goffi <goffi@goffi.org>
parents:
1060
diff
changeset
|
810 except (KeyError, IndexError): |
962 | 811 pass |
812 else: | |
813 # a redirection is requested | |
814 if not url or url[0] != u'/': | |
815 # we only want local urls | |
816 self.pageError(request, C.HTTP_BAD_REQUEST) | |
817 else: | |
818 self.HTTPRedirect(request, url) | |
819 | |
1032
863cc6f97068
pages: path arguments can now be specified in pageRedirect
Goffi <goffi@goffi.org>
parents:
1031
diff
changeset
|
820 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
|
821 """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
|
822 |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
823 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
|
824 skipping named page's parse_url method if it exist. |
962 | 825 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
|
826 @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
|
827 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
|
828 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
|
829 else: |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
830 - 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
|
831 - 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
|
832 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
|
833 "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
|
834 "/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
|
835 @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
|
836 @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
|
837 @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
|
838 @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
|
839 """ |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
840 # 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
|
841 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
|
842 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
|
843 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
|
844 else: |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
845 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
|
846 |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
847 for subpage in path[1:]: |
962 | 848 if redirect_page is self.host.root: |
849 redirect_page = redirect_page.children[subpage] | |
850 else: | |
851 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
|
852 |
1032
863cc6f97068
pages: path arguments can now be specified in pageRedirect
Goffi <goffi@goffi.org>
parents:
1031
diff
changeset
|
853 if path_args is not None: |
863cc6f97068
pages: path arguments can now be specified in pageRedirect
Goffi <goffi@goffi.org>
parents:
1031
diff
changeset
|
854 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
|
855 request.postpath = args + request.postpath |
863cc6f97068
pages: path arguments can now be specified in pageRedirect
Goffi <goffi@goffi.org>
parents:
1031
diff
changeset
|
856 |
1033
c34f08e05cdf
pages: cache is now working even after pageRedirect
Goffi <goffi@goffi.org>
parents:
1032
diff
changeset
|
857 if self._do_cache: |
c34f08e05cdf
pages: cache is now working even after pageRedirect
Goffi <goffi@goffi.org>
parents:
1032
diff
changeset
|
858 # 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
|
859 redirect_page._do_cache = self._do_cache |
c34f08e05cdf
pages: cache is now working even after pageRedirect
Goffi <goffi@goffi.org>
parents:
1032
diff
changeset
|
860 self._do_cache = None |
c34f08e05cdf
pages: cache is now working even after pageRedirect
Goffi <goffi@goffi.org>
parents:
1032
diff
changeset
|
861 |
1015 | 862 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
|
863 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
|
864 |
1019
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
865 def pageError(self, request, code=C.HTTP_NOT_FOUND, no_body=False): |
917 | 866 """generate an error page and terminate the request |
867 | |
868 @param request(server.Request): HTTP request | |
869 @param core(int): error code to use | |
1019
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
870 @param no_body: don't write body if True |
917 | 871 """ |
872 request.setResponseCode(code) | |
1019
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
873 if no_body: |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
874 request.finish() |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
875 else: |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
876 template = u'error/' + unicode(code) + '.html' |
917 | 877 |
1019
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
878 rendered = self.host.renderer.render( |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
879 template, |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
880 root_path = '/templates/', |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
881 error_code = code, |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
882 **request.template_data) |
917 | 883 |
1019
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
884 self.writeData(rendered, request) |
917 | 885 raise failure.Failure(exceptions.CancelError(u'error page is used')) |
886 | |
887 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
|
888 """write data to transport and finish the request""" |
917 | 889 if data is None: |
890 self.pageError(request) | |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
891 data_encoded = data.encode('utf-8') |
1019
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
892 |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
893 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
|
894 redirected_page = self._do_cache.pop(0) |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
895 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
|
896 page_cache = cache[redirected_page] = CachePage(data_encoded) |
1019
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
897 self._setCacheHeaders(request, page_cache) |
985
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
898 log.debug(_(u'{page} put in cache for [{profile}]').format( |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
899 page=self, |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
900 profile=self._do_cache[0])) |
64826e69f365
pages: cache mechanism, first draft:
Goffi <goffi@goffi.org>
parents:
984
diff
changeset
|
901 self._do_cache = None |
1019
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
902 self._checkCacheHeaders(request, page_cache) |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
903 |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
904 request.write(data_encoded) |
34240d08f682
pages: HTTP cache headers handling:
Goffi <goffi@goffi.org>
parents:
1018
diff
changeset
|
905 request.finish() |
917 | 906 |
907 def _subpagesHandler(self, dummy, request): | |
908 """render subpage if suitable | |
909 | |
910 this method checks if there is still an unmanaged part of the path | |
911 and check if it corresponds to a subpage. If so, it render the subpage | |
912 else it render a NoResource. | |
913 If there is no unmanaged part of the segment, current page workflow is pursued | |
914 """ | |
915 if request.postpath: | |
916 subpage = self.nextPath(request) | |
917 try: | |
918 child = self.children[subpage] | |
919 except KeyError: | |
920 self.pageError(request) | |
921 else: | |
922 child.render(request) | |
923 raise failure.Failure(exceptions.CancelError(u'subpage page is used')) | |
924 | |
998
0848b8b0188d
pages: dynamic set up is now done just before prepare_render call:
Goffi <goffi@goffi.org>
parents:
995
diff
changeset
|
925 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
|
926 # 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
|
927 # 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
|
928 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
|
929 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
|
930 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
|
931 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
|
932 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
|
933 # 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
|
934 request._signals_registered = [] |
0848b8b0188d
pages: dynamic set up is now done just before prepare_render call:
Goffi <goffi@goffi.org>
parents:
995
diff
changeset
|
935 # 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
|
936 request._signals_cache = [] |
0848b8b0188d
pages: dynamic set up is now done just before prepare_render call:
Goffi <goffi@goffi.org>
parents:
995
diff
changeset
|
937 |
917 | 938 def _prepare_render(self, dummy, request): |
926
612e33fd32a8
server (pages): fixed _prepare_render handling
Goffi <goffi@goffi.org>
parents:
925
diff
changeset
|
939 return defer.maybeDeferred(self.prepare_render, self, request) |
917 | 940 |
941 def _render_method(self, dummy, request): | |
942 return defer.maybeDeferred(self.render_method, self, request) | |
943 | |
962 | 944 def _render_template(self, dummy, request): |
945 template_data = request.template_data | |
946 | |
947 # if confirm variable is set in case of successfuly data post | |
948 session_data = self.host.getSessionData(request, session_iface.ISATSession) | |
949 if session_data.popPageFlag(self, C.FLAG_CONFIRM): | |
950 template_data[u'confirm'] = True | |
951 | |
917 | 952 return self.host.renderer.render( |
953 self.template, | |
954 root_path = '/templates/', | |
962 | 955 media_path = '/' + C.MEDIA_DIR, |
995 | 956 cache_path = session_data.cache_dir, |
990
6daa59d44ee2
pages: menu implementation, first draft:
Goffi <goffi@goffi.org>
parents:
985
diff
changeset
|
957 main_menu = LiberviaPage.main_menu, |
917 | 958 **template_data) |
959 | |
960 def _renderEb(self, failure_, request): | |
961 """don't raise error on CancelError""" | |
962 failure_.trap(exceptions.CancelError) | |
963 | |
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
|
964 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
|
965 """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
|
966 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
|
967 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
|
968 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
|
969 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
|
970 |
956
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
971 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
|
972 """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
|
973 |
968
4d37b23777c3
pages (core, tickets/new): replaced post_redirect_uri mechanism by post_redirect_page:
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
974 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
|
975 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
|
976 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
|
977 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
|
978 HTTP status code "See Other" (303) is used as it is the recommanded code in this case. |
962 | 979 @param ret(None, unicode, iterable): on_data_post return value |
980 see LiberviaPage.__init__ on_data_post docstring | |
956
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
981 """ |
962 | 982 if ret is None: |
983 ret = () | |
984 elif isinstance(ret, basestring): | |
985 ret = (ret,) | |
986 else: | |
987 ret = tuple(ret) | |
988 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
|
989 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
|
990 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
|
991 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
|
992 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
|
993 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
|
994 redirect_page = redirect_page_data[0] |
972
c4e58c4dba75
server: getURL + minor improvments:
Goffi <goffi@goffi.org>
parents:
968
diff
changeset
|
995 redirect_page_args = redirect_page_data[1:] |
c4e58c4dba75
server: getURL + minor improvments:
Goffi <goffi@goffi.org>
parents:
968
diff
changeset
|
996 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
|
997 else: |
4d37b23777c3
pages (core, tickets/new): replaced post_redirect_uri mechanism by post_redirect_page:
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
998 redirect_page = redirect_page_data |
972
c4e58c4dba75
server: getURL + minor improvments:
Goffi <goffi@goffi.org>
parents:
968
diff
changeset
|
999 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
|
1000 else: |
4d37b23777c3
pages (core, tickets/new): replaced post_redirect_uri mechanism by post_redirect_page:
Goffi <goffi@goffi.org>
parents:
966
diff
changeset
|
1001 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
|
1002 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
|
1003 |
962 | 1004 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
|
1005 session_data.setPageFlag(redirect_page, C.FLAG_CONFIRM) |
956
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
1006 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
|
1007 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
|
1008 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
|
1009 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
|
1010 |
956
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
1011 def _on_data_post(self, dummy, request): |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
1012 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
|
1013 try: |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
1014 given_csrf = self.getPostedData(request, u'csrf_token') |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
1015 except KeyError: |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
1016 given_csrf = None |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
1017 if given_csrf is None or given_csrf != csrf_token: |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
1018 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
|
1019 url=request.uri, |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
1020 ip=request.getClientIP())) |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
1021 self.pageError(request, C.HTTP_UNAUTHORIZED) |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
1022 d = defer.maybeDeferred(self.on_data_post, self, request) |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
1023 d.addCallback(self._on_data_post_redirect, request) |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
1024 return d |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
1025 |
931
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1026 def getPostedData(self, request, keys, multiple=False): |
1010
4de970de87d7
pages: added getCurrentURL and getParamURL:
Goffi <goffi@goffi.org>
parents:
1009
diff
changeset
|
1027 """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
|
1028 |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1029 @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
|
1030 @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
|
1031 unicode to get one value |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1032 iterable to get more than one |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1033 @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
|
1034 if False, the first value is returned |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1035 @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
|
1036 @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
|
1037 """ |
1061
bacb8f229742
pages: fixed unicode escaping when using a redirecting URL
Goffi <goffi@goffi.org>
parents:
1060
diff
changeset
|
1038 # FIXME: request.args is already unquoting the value, it seems we are doing double unquote |
931
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1039 if isinstance(keys, basestring): |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1040 keys = [keys] |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1041 get_first = True |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1042 else: |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1043 get_first = False |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1044 |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1045 ret = [] |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1046 for key in keys: |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1047 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
|
1048 if multiple: |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1049 ret.append(gen) |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1050 else: |
956
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
1051 try: |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
1052 ret.append(next(gen)) |
dabecab10faa
server (pages): impleted CSRF protection:
Goffi <goffi@goffi.org>
parents:
955
diff
changeset
|
1053 except StopIteration: |
962 | 1054 raise KeyError(key) |
931
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1055 |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1056 return ret[0] if get_first else ret |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1057 |
1009
b57f86bc1177
pages: added "multiple" argument to getAllPostedData
Goffi <goffi@goffi.org>
parents:
1003
diff
changeset
|
1058 def getAllPostedData(self, request, except_=(), multiple=True): |
959 | 1059 """get all posted data |
1060 | |
1061 @param request(server.Request): request linked to the session | |
1062 @param except_(iterable[unicode]): key of values to ignore | |
1063 csrf_token will always be ignored | |
1009
b57f86bc1177
pages: added "multiple" argument to getAllPostedData
Goffi <goffi@goffi.org>
parents:
1003
diff
changeset
|
1064 @param multiple(bool): if False, only the first values are returned |
959 | 1065 @return (dict[unicode, list[unicode]]): post values |
1066 """ | |
1067 except_ = tuple(except_) + (u'csrf_token',) | |
1068 ret = {} | |
1069 for key, values in request.args.iteritems(): | |
1070 key = urllib.unquote(key).decode('utf-8') | |
1071 if key in except_: | |
1072 continue | |
1009
b57f86bc1177
pages: added "multiple" argument to getAllPostedData
Goffi <goffi@goffi.org>
parents:
1003
diff
changeset
|
1073 if not multiple: |
b57f86bc1177
pages: added "multiple" argument to getAllPostedData
Goffi <goffi@goffi.org>
parents:
1003
diff
changeset
|
1074 ret[key] = urllib.unquote(values[0]).decode('utf-8') |
b57f86bc1177
pages: added "multiple" argument to getAllPostedData
Goffi <goffi@goffi.org>
parents:
1003
diff
changeset
|
1075 else: |
b57f86bc1177
pages: added "multiple" argument to getAllPostedData
Goffi <goffi@goffi.org>
parents:
1003
diff
changeset
|
1076 ret[key] = [urllib.unquote(v).decode('utf-8') for v in values] |
959 | 1077 return ret |
1078 | |
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
|
1079 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
|
1080 """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
|
1081 |
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
|
1082 @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
|
1083 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
|
1084 """ |
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
|
1085 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
|
1086 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
|
1087 |
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
|
1088 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
|
1089 """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
|
1090 |
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
|
1091 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
|
1092 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
|
1093 @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
|
1094 """ |
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
|
1095 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
|
1096 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
|
1097 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
|
1098 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
|
1099 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
|
1100 |
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
|
1101 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
|
1102 """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
|
1103 |
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
|
1104 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
|
1105 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
|
1106 """ |
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
|
1107 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
|
1108 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
|
1109 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
|
1110 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
|
1111 if not profile: |
962 | 1112 # no session started |
1113 if not self.host.options["allow_registration"]: | |
1114 # registration not allowed, access is not granted | |
1115 self.pageError(request, C.HTTP_UNAUTHORIZED) | |
1116 else: | |
1117 # registration allowed, we redirect to login page | |
1118 login_url = self.getPageRedirectURL(request) | |
1119 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
|
1120 |
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
|
1121 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
|
1122 |
995 | 1123 def renderPartial(self, request, template, template_data): |
1124 """Render a template to be inserted in dynamic page | |
1125 | |
1126 this is NOT the normal page rendering method, it is used only to update | |
1127 dynamic pages | |
1128 @param template(unicode): path of the template to render | |
1129 @param template_data(dict): template_data to use | |
1130 """ | |
1131 if not self.dynamic: | |
1132 raise exceptions.InternalError(_(u"renderPartial must only be used with dynamic pages")) | |
1133 session_data = self.host.getSessionData(request, session_iface.ISATSession) | |
1134 | |
1135 return self.host.renderer.render( | |
1136 template, | |
1137 root_path = '/templates/', | |
1138 media_path = '/' + C.MEDIA_DIR, | |
1139 cache_path = session_data.cache_dir, | |
1140 main_menu = LiberviaPage.main_menu, | |
1141 **template_data) | |
1142 | |
1143 def renderAndUpdate(self, request, template, selectors, template_data_update, update_type="append"): | |
1144 """Helper method to render a partial page element and update the page | |
1145 | |
1146 this is NOT the normal page rendering method, it is used only to update | |
1147 dynamic pages | |
1148 @param request(server.Request): current HTTP request | |
1149 @param template: same as for [renderPartial] | |
1150 @param selectors: CSS selectors to use | |
1151 @param template_data_update: template data to use | |
1152 template data cached in request will be copied then updated | |
1153 with this data | |
1154 @parap update_type(unicode): one of: | |
1155 append: append rendered element to selected element | |
1156 """ | |
1157 template_data = request.template_data.copy() | |
1158 template_data.update(template_data_update) | |
1159 html = self.renderPartial(request, template, template_data) | |
1160 request.sendData(u'dom', | |
1161 selectors=selectors, | |
1162 update_type=update_type, | |
1163 html=html) | |
1164 | |
923
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
1165 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
|
1166 """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
|
1167 |
923
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
1168 # template_data are the variables passed to template |
917 | 1169 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
|
1170 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
|
1171 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
|
1172 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
|
1173 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
|
1174 |
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
|
1175 # 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
|
1176 # at the beginning of the request hanling |
917 | 1177 if request.postpath and not request.postpath[-1]: |
1178 # we don't differenciate URLs finishing with '/' or not | |
1179 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
|
1180 |
917 | 1181 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
|
1182 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
|
1183 |
923
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
1184 if self.redirect is not None: |
1015 | 1185 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
|
1186 |
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
1187 if self.parse_url is not None and not skip_parse_url: |
1018 | 1188 if self.url_cache: |
1189 profile = self.getProfile(request) | |
1190 try: | |
1191 cache_url = self.cached_urls[profile][request.uri] | |
1192 except KeyError: | |
1193 # no cache for this URI yet | |
1194 # we do normal URL parsing, and then the cache | |
1195 d.addCallback(self.parse_url, request) | |
1196 d.addCallback(self._cacheURL, request, profile) | |
1197 else: | |
1198 log.debug(_(u"using URI cache for {page}").format(page=self)) | |
1199 cache_url.use(request) | |
1200 else: | |
1201 d.addCallback(self.parse_url, request) | |
917 | 1202 |
1203 d.addCallback(self._subpagesHandler, request) | |
1204 | |
931
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1205 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
|
1206 # 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
|
1207 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
|
1208 |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1209 if request.method == C.HTTP_METHOD_POST: |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1210 if self.on_data_post is None: |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1211 # 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
|
1212 # so we return an error |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1213 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
|
1214 else: |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1215 d.addCallback(self._on_data_post, request) |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1216 # 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
|
1217 # 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
|
1218 |
998
0848b8b0188d
pages: dynamic set up is now done just before prepare_render call:
Goffi <goffi@goffi.org>
parents:
995
diff
changeset
|
1219 if self.dynamic: |
0848b8b0188d
pages: dynamic set up is now done just before prepare_render call:
Goffi <goffi@goffi.org>
parents:
995
diff
changeset
|
1220 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
|
1221 |
917 | 1222 if self.prepare_render: |
1223 d.addCallback(self._prepare_render, request) | |
1224 | |
1225 if self.template: | |
962 | 1226 d.addCallback(self._render_template, request) |
917 | 1227 elif self.render_method: |
1228 d.addCallback(self._render_method, request) | |
1229 | |
1230 d.addCallback(self.writeData, request) | |
1231 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
|
1232 d.addErrback(self._internalError, request) |
917 | 1233 d.callback(self) |
1234 return server.NOT_DONE_YET | |
1235 | |
923
edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
Goffi <goffi@goffi.org>
parents:
922
diff
changeset
|
1236 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
|
1237 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
|
1238 |
931
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1239 def render_POST(self, request): |
8a393ae90f8c
server (pages): post requests are now handled:
Goffi <goffi@goffi.org>
parents:
927
diff
changeset
|
1240 return self.renderPage(request) |