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