Mercurial > libervia-web
comparison src/server/server.py @ 923:edb322c87ea4
server (pages): pages now handle redirection, check self.pageRedirect docstring for details
author | Goffi <goffi@goffi.org> |
---|---|
date | Mon, 03 Apr 2017 01:00:29 +0200 |
parents | 16d1084d1371 |
children | 94f88277c2e7 |
comparison
equal
deleted
inserted
replaced
922:16d1084d1371 | 923:edb322c87ea4 |
---|---|
1421 | 1421 |
1422 class LiberviaPage(web_resource.Resource): | 1422 class LiberviaPage(web_resource.Resource): |
1423 isLeaf = True # we handle subpages ourself | 1423 isLeaf = True # we handle subpages ourself |
1424 named_pages = {} | 1424 named_pages = {} |
1425 | 1425 |
1426 def __init__(self, host, root_dir, name=None, access=None, parse_url=None, | 1426 def __init__(self, host, root_dir, name=None, redirect=None, access=None, parse_url=None, |
1427 prepare_render=None, render=None, template=None): | 1427 prepare_render=None, render=None, template=None): |
1428 """initiate LiberviaPages | 1428 """initiate LiberviaPages |
1429 | 1429 |
1430 LiberviaPages are the main resources of Libervia, using easy to set python files | 1430 LiberviaPages are the main resources of Libervia, using easy to set python files |
1431 The arguments are the variables found in page_meta.py | 1431 The arguments are the variables found in page_meta.py |
1432 @param host(Libervia): the running instance of Libervia | 1432 @param host(Libervia): the running instance of Libervia |
1433 @param root_dir(unicode): aboslute path of the page | 1433 @param root_dir(unicode): aboslute path of the page |
1434 @param name(unicode, None): if not None, a unique name to identify the page | 1434 @param name(unicode, None): if not None, a unique name to identify the page |
1435 can then be used for e.g. redirection | 1435 can then be used for e.g. redirection |
1436 "/" is not allowed in names (as it can be used to construct URL paths) | |
1437 @param redirect(unicode, None): if not None, this page will be a redirected | |
1438 parameter is used as in self.pageRedirect. parse_url will not be skipped | |
1439 using this redirect parameter is called "full redirection" | |
1440 using self.pageRedirect is called "partial redirection" (because some rendering method | |
1441 can still be used, e.g. parse_url) | |
1436 @param access(unicode, None): permission needed to access the page | 1442 @param access(unicode, None): permission needed to access the page |
1437 None means public access. | 1443 None means public access. |
1438 Pages inherit from parent pages: e.g. if a "settings" page is restricted to admins, | 1444 Pages inherit from parent pages: e.g. if a "settings" page is restricted to admins, |
1439 and if "settings/blog" is public, it still can only be accessed by admins. | 1445 and if "settings/blog" is public, it still can only be accessed by admins. |
1440 see C.PAGES_ACCESS_* for details | 1446 see C.PAGES_ACCESS_* for details |
1454 self.host = host | 1460 self.host = host |
1455 self.root_dir = root_dir | 1461 self.root_dir = root_dir |
1456 if name is not None: | 1462 if name is not None: |
1457 if name in self.named_pages: | 1463 if name in self.named_pages: |
1458 raise exceptions.ConflictError(_(u'a Libervia page named "{}" already exists'.format(name))) | 1464 raise exceptions.ConflictError(_(u'a Libervia page named "{}" already exists'.format(name))) |
1465 if u'/' in name: | |
1466 raise ValueError(_(u'"/" is not allowed in page names')) | |
1467 if not name: | |
1468 raise ValueError(_(u"a page name can't be empty")) | |
1459 self.named_pages[name] = self | 1469 self.named_pages[name] = self |
1460 if access is None: | 1470 if access is None: |
1461 access = C.PAGES_ACCESS_PUBLIC | 1471 access = C.PAGES_ACCESS_PUBLIC |
1462 if access not in (C.PAGES_ACCESS_PUBLIC, C.PAGES_ACCESS_PROFILE, C.PAGES_ACCESS_NONE): | 1472 if access not in (C.PAGES_ACCESS_PUBLIC, C.PAGES_ACCESS_PROFILE, C.PAGES_ACCESS_NONE): |
1463 raise NotImplementedError(_(u"{} access is not implemented yet").format(access)) | 1473 raise NotImplementedError(_(u"{} access is not implemented yet").format(access)) |
1464 self.access = access | 1474 self.access = access |
1475 if redirect is not None: | |
1476 # only page access and name make sense in case of full redirection | |
1477 if not all(lambda x: x is not None | |
1478 for x in (parse_url, prepare_render, render, template)): | |
1479 raise ValueError(_(u"you can't use full page redirection with other rendering method," | |
1480 u"check self.pageRedirect if you need to use them")) | |
1481 self.redirect = redirect | |
1482 else: | |
1483 self.redirect = None | |
1465 self.parse_url = parse_url | 1484 self.parse_url = parse_url |
1466 self.prepare_render = prepare_render | 1485 self.prepare_render = prepare_render |
1467 self.template = template | 1486 self.template = template |
1468 self.render_method = render | 1487 self.render_method = render |
1469 if access == C.PAGES_ACCESS_NONE: | 1488 if access == C.PAGES_ACCESS_NONE: |
1501 execfile(meta_path, page_data) | 1520 execfile(meta_path, page_data) |
1502 resource = LiberviaPage( | 1521 resource = LiberviaPage( |
1503 host, | 1522 host, |
1504 dir_path, | 1523 dir_path, |
1505 name=page_data.get('name'), | 1524 name=page_data.get('name'), |
1525 redirect=page_data.get('redirect'), | |
1506 access=page_data.get('access'), | 1526 access=page_data.get('access'), |
1507 parse_url=page_data.get('parse_url'), | 1527 parse_url=page_data.get('parse_url'), |
1508 prepare_render=page_data.get('prepare_render'), | 1528 prepare_render=page_data.get('prepare_render'), |
1509 render=page_data.get('render'), | 1529 render=page_data.get('render'), |
1510 template=page_data.get('template')) | 1530 template=page_data.get('template')) |
1527 """ | 1547 """ |
1528 pathElement = request.postpath.pop(0) | 1548 pathElement = request.postpath.pop(0) |
1529 request.prepath.append(pathElement) | 1549 request.prepath.append(pathElement) |
1530 return urllib.unquote(pathElement).decode('utf-8') | 1550 return urllib.unquote(pathElement).decode('utf-8') |
1531 | 1551 |
1552 def pageRedirect(self, page_path, request, skip_parse_url=True): | |
1553 """redirect a page to a named page | |
1554 | |
1555 the workflow will continue with the workflow of the named page, | |
1556 skipping named page's parse_url method if it exist. | |
1557 @param page_path(unicode): path to page (elements are separated by "/"): | |
1558 if path starts with a "/": | |
1559 path is a full path starting from root | |
1560 else: | |
1561 - first element is name as registered in name variable | |
1562 - following element are subpages path | |
1563 e.g.: "blog" redirect to page named "blog" | |
1564 "blog/atom.xml" redirect to atom.xml subpage of "blog" | |
1565 "/common/blog/atom.xml" redirect to the page at the fiven full path | |
1566 @param request(server.Request): current HTTP request | |
1567 @param skip_parse_url(bool): if True, parse_url method on redirect page will be skipped | |
1568 @raise KeyError: there is no known page with this name | |
1569 """ | |
1570 # FIXME: render non LiberviaPage resources | |
1571 path = page_path.rstrip(u'/').split(u'/') | |
1572 if not path[0]: | |
1573 redirect_page = self.host.root | |
1574 else: | |
1575 redirect_page = self.named_pages[path[0]] | |
1576 | |
1577 for subpage in path[1:]: | |
1578 redirect_page = redirect_page.childen[subpage] | |
1579 | |
1580 redirect_page.renderPage(request, skip_parse_url=True) | |
1581 raise failure.Failure(exceptions.CancelError(u'page redirection is used')) | |
1582 | |
1532 def pageError(self, request, code=C.HTTP_NOT_FOUND): | 1583 def pageError(self, request, code=C.HTTP_NOT_FOUND): |
1533 """generate an error page and terminate the request | 1584 """generate an error page and terminate the request |
1534 | 1585 |
1535 @param request(server.Request): HTTP request | 1586 @param request(server.Request): HTTP request |
1536 @param core(int): error code to use | 1587 @param core(int): error code to use |
1624 # no session started, access is not granted | 1675 # no session started, access is not granted |
1625 self.pageError(request, C.HTTP_UNAUTHORIZED) | 1676 self.pageError(request, C.HTTP_UNAUTHORIZED) |
1626 | 1677 |
1627 return data | 1678 return data |
1628 | 1679 |
1629 def render_GET(self, request): | 1680 def renderPage(self, request, skip_parse_url=False): |
1681 # template_data are the variables passed to template | |
1630 if not hasattr(request, 'template_data'): | 1682 if not hasattr(request, 'template_data'): |
1631 request.template_data = {} | 1683 request.template_data = {} |
1632 | 1684 |
1633 # XXX: here is the code which need to be executed once | 1685 # XXX: here is the code which need to be executed once |
1634 # at the beginning of the request hanling | 1686 # at the beginning of the request hanling |
1637 del request.postpath[-1] | 1689 del request.postpath[-1] |
1638 | 1690 |
1639 d = defer.Deferred() | 1691 d = defer.Deferred() |
1640 d.addCallback(self._checkAccess, request) | 1692 d.addCallback(self._checkAccess, request) |
1641 | 1693 |
1642 if self.parse_url is not None: | 1694 if self.redirect is not None: |
1695 self.pageRedirect(self.redirect, request, skip_parse_url=False) | |
1696 | |
1697 if self.parse_url is not None and not skip_parse_url: | |
1643 d.addCallback(self.parse_url, request) | 1698 d.addCallback(self.parse_url, request) |
1644 | 1699 |
1645 d.addCallback(self._subpagesHandler, request) | 1700 d.addCallback(self._subpagesHandler, request) |
1646 | 1701 |
1647 if self.prepare_render: | 1702 if self.prepare_render: |
1654 | 1709 |
1655 d.addCallback(self.writeData, request) | 1710 d.addCallback(self.writeData, request) |
1656 d.addErrback(self._renderEb, request) | 1711 d.addErrback(self._renderEb, request) |
1657 d.callback(self) | 1712 d.callback(self) |
1658 return server.NOT_DONE_YET | 1713 return server.NOT_DONE_YET |
1714 | |
1715 def render_GET(self, request): | |
1716 return self.renderPage(request) | |
1659 | 1717 |
1660 | 1718 |
1661 class Libervia(service.Service): | 1719 class Libervia(service.Service): |
1662 | 1720 |
1663 def __init__(self, options): | 1721 def __init__(self, options): |