'Convert an HTTP request to a list of mailpile.command objects.
>>> urlmap.map(request, \'GET\', \'/in/inbox/\', {}, {})
[<mailpile.plugins.core.Output...>, <mailpile.plugins.search.Search...>]
The /api/ URL space is versioned and provides access to all the
built-in commands. Requesting the wrong version or a bogus command
throws exceptions.
>>> urlmap.map(request, \'GET\', \'/api/999/bogus/\', {}, {})
Traceback (most recent call last):
UsageError: Unknown API level: 999
>>> urlmap.map(request, \'GET\', \'/api/0/bogus/\', {}, {})
Traceback (most recent call last):
UsageError: Not available for GET: bogus
This is the async version of the API.
>>> urlmap.map(request, \'GET\', \'/async/0/search/\', {}, {})
[<mailpile.plugins.core.Output...>, <mailpile.plugins.search.Search...>]
The root currently just redirects to /profiles/:
>>> r = urlmap.map(request, \'GET\', \'/\', {}, {})[0]
>>> r, r.args
(<...UrlRedirect...>, (\'/profiles/\',))
Tag searches have an /in/TAGNAME shorthand:
>>> urlmap.map(request, \'GET\', \'/in/inbox/\', {}, {})
[<mailpile.plugins.core.Output...>, <mailpile.plugins.search.Search...>]
Thread shortcuts are /thread/METADATAID/:
>>> urlmap.map(request, \'GET\', \'/thread/123/\', {}, {})
[<mailpile.plugins.core.Output...>, <mailpile.plugins.search.View...>]
Other commands use the command name as the first path component:
>>> urlmap.map(request, \'GET\', \'/search/bjarni/\', {}, {})
[<mailpile.plugins.core.Output...>, <mailpile.plugins.search.Search...>]
>>> urlmap.map(request, \'GET\', \'/message/draft/=123/\', {}, {})
[<mailpile.plugins.core.Output...>, <mailpile.plugins.compose.Draft...>]'

def map(self, request, method, path, query_data, post_data, authenticate=False):

    if self.session:
        sid = self.session.ui.html_variables.get('http_session')
        user_session = (mailpile.auth.SESSION_CACHE.get(sid) if sid else None)
    else:
        sid = user_session = None
    is_async = path.startswith(('/%s/' % self.MAP_ASYNC_API))
    is_api = path.startswith(('/%s/' % self.MAP_API))
    if authenticate:
        def auth(commands, user_session):
            if user_session:
                if user_session.is_expired():
                    mailpile.auth.SESSION_CACHE.delete_expired()
                    user_session = None
                else:
                    user_session.update_ts()
                if (user_session and (method == 'POST')):
                    if isinstance(post_data, cgi.FieldStorage):
                        try:
                            csrf = post_data['csrf'].value
                        except KeyError:
                            csrf = ''
                    else:
                        csrf = post_data.get('csrf', [''])[0]
                    if (not security.valid_csrf_token(request.server.secret, sid, csrf)):
                        user_session = None
            if ((not user_session) or (not user_session.auth)):
                for c in commands:
                    if ((c.HTTP_AUTH_REQUIRED is True) or ((c.HTTP_AUTH_REQUIRED == 'Maybe') and self.session.config.prefs.gpg_recipient)):
                        if (is_async or is_api):
                            raise AccessError()
                        self.redirect_to_auth_or_setup(method, path, query_data)
            return commands
    else:
        def auth(commands, user_session):
            return commands
    if (is_api or is_async):
        path_parts = path.split('/')
        if (int(path_parts[2]) not in self.API_VERSIONS):
            raise UsageError(('Unknown    API    level:    %s' % path_parts[2]))
        return auth(self._map_api_command(method, path_parts[3:], query_data, post_data, fmt='json', async=is_async), user_session)
    path_parts = path[1:].split('/')
    try:
        return auth(self._map_api_command(method, path_parts[:], query_data, post_data), user_session)
    except UsageError:
        if (path_parts[0] in self.MAP_PATHS):
            if (authenticate and ((not user_session) or (not user_session.auth))):
                self.redirect_to_auth_or_setup(method, path, query_data)
            mapper = self.MAP_PATHS[path_parts[0]]
            return auth(mapper(self, request, path_parts, query_data, post_data), user_session)
        raise
