Example #1
0
async def forward(request, url):
    #print('>', url)
    headers = {'Accept': 'application/vnd.phereo.v3+json'}
    for k in ('Cache-Control', 'If-Modified-Since', 'If-None-Match',
              'User-Agent'):
        if k in request.headers:
            headers[k] = request.headers[k]
    async with ClientSession() as client:
        async with client.request('GET',
                                  url,
                                  headers=headers,
                                  allow_redirects=False,
                                  ssl=False,
                                  data=await request.read()) as res:
            if res.status == 404:
                raise web.HTTPNotFound()
            elif res.status == 302:
                raise web.HTTPFound(location=res.headers.get('Location'))
            elif res.status == 304:
                raise web.HTTPNotModified()
            elif res.status != 200:
                raise web.HTTPInternalServerError()  # Not expected
            headers = {'Access-Control-Allow-Origin': '*'}
            for k in ('Content-Type', 'Expires', 'Cache-Control', 'Pragma',
                      'ETag', 'Last-Modified'):
                if k in res.headers:
                    headers[k] = res.headers[k]
            return web.Response(status=200,
                                headers=headers,
                                body=await res.read())
Example #2
0
async def link_redirect(request: web.Request):
    dataset = request.match_info['dataset']
    distribution = request.match_info['distribution']
    etag_if_none_match = conditional.parse_if_header(
        request, conditional.HEADER_IF_NONE_MATCH)
    if etag_if_none_match == '*':
        raise web.HTTPBadRequest(
            body='Endpoint does not support * in the If-None-Match header.')

    try:
        doc, etag = await request.app.hooks.storage_retrieve(
            app=request.app, docid=dataset, etags=etag_if_none_match)
    except KeyError:
        raise web.HTTPNotFound()
    if doc is None:
        raise web.HTTPNotModified(headers={'ETag': etag})
    headers = {'ETag': etag}
    resource_url = None
    for dist in doc.get('dcat:distribution', []):
        if dist.get('dc:identifier', None) == distribution:
            resource_url = dist.get('dcat:accessURL', None)
            break
    if resource_url is None:
        raise web.HTTPNotFound(headers=headers)
    raise web.HTTPTemporaryRedirect(location=resource_url, headers=headers)
Example #3
0
async def patch_message(req: web.Request) -> web.Response:
    message_id = req["match_info"]["message_id"]

    params = {k: v for k, v in req["body"].items() if v is not None}
    if not params:
        raise web.HTTPNotModified()

    record = await req.config_dict["pg_conn"].fetchval(
        MESSAGE.update_query_for(
            "messages", message_id, params.keys(), returning=False
        ),
        *params.values(),
        req.config_dict["sf_gen"].gen_id(),
    )

    if record is None:
        raise web.HTTPNotModified

    # FIXME: reduce number of queries!!! (3 here)
    new_row = await req.config_dict["pg_conn"].fetchrow(
        f"SELECT {MESSAGE} FROM messages_with_author WHERE id = $1", message_id
    )

    diff = MESSAGE.diff_to_json(req["message"], new_row)

    req.config_dict["emitter"].emit(events.MESSAGE_UPDATE(payload=diff))

    return web.json_response(diff)
Example #4
0
async def add_channel_recipient(req: web.Request) -> web.Response:
    await helpers.ensure_permissions(Permissions.INVITE_MEMBERS, request=req)

    channel_id = req["match_info"]["channel_id"]
    user_id = req["match_info"]["user_id"]

    await ensure_existance(req, "users", user_id, "User")

    async with req.config_dict["pg_conn"].acquire() as conn:
        async with conn.transaction():
            success = await conn.fetchval(
                "SELECT * FROM add_channel_user($1, $2)", channel_id, user_id
            )

            if not success:
                raise web.HTTPNotModified(reason="Is user already in channel?")

            message = await conn.fetchrow(
                f"SELECT {MESSAGE} FROM create_message($1, $2, $3, $4, type:=$5)",
                req.config_dict["sf_gen"].gen_id(),
                channel_id,
                user_id,
                "",
                MessageTypes.RECIPIENT_ADD.value,
            )

    req.config_dict["emitter"].emit(
        events.MESSAGE_CREATE(payload=MESSAGE.to_json(message))
    )

    raise web.HTTPNoContent()
Example #5
0
def _assert_if_none_match(request: web.Request, etag: T.Union[None, bool, str],
                          require: bool):
    # The If-None-Match: header is used in two scenarios:
    # 1. GET requests by a caching client. In this case, the client will
    #    normally provide a list of (cached) ETags.
    # 2. PUT requests, where the client intends to create a new resource and
    #    wants to avoid overwriting an existing resource. In this case, the
    #    client will normally provide only the asterisk "*" character.
    etags = _parse_if_header(request, 'If-None-Match')
    if require and etags is None:
        raise web.HTTPPreconditionRequired(text='If-None-Match')
    if etags is None or etag is False or etag is None:
        return
    if etags is _STAR:
        raise web.HTTPPreconditionFailed()
    # From here on, we know that etags is a set of strings.
    if etag is True:
        raise web.HTTPPreconditionFailed(
            text="Resource doesn't support ETags.")
    # From here on, we know that etag is a string:
    if etag in etags:
        if request.method in {'GET', 'HEAD'}:
            raise web.HTTPNotModified()
        else:
            raise web.HTTPPreconditionFailed()
Example #6
0
File: files.py Project: snjypl/tao1
def img(request):
	""" return file and information about it, for static """
	proc_id = request.match_info.get('proc_id', "des:obj")
	doc_id =  request.match_info.get('doc_id', "")
	img =     request.match_info.get('img', "")
	action =  request.match_info.get('action', "img")
	att = None
	headers = {}
	try:
		fn, att, prefix = img_m(request, proc_id, doc_id, img, action)
		if not fn: return web.HTTPNotFound()
		headers['Content-Length'] = fn['length']
		lm = locale_date("%a, %d %b %Y %H:%M:%S GMT", fn['uploadDate'].timetuple(), 'en_US.UTF-8')
		headers['Last-Modified'] = lm

		ims = request.if_modified_since

		if ims and ims.strftime('%Y-%m-%d %H:%M:%S') >= fn['uploadDate'].strftime('%Y-%m-%d %H:%M:%S'):
			headers['Date'] = locale_date("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(), 'en_US.UTF-8')
			return web.HTTPNotModified( headers=MultiDict( headers ) )

		headers['Content-Type'] = fn['mime']
		headers['Cache-Control'] = 'max-age=604800'
		content  = att.read()
	finally:
		if att: att.close()
	return web.Response(body=content, headers=MultiDict( headers ))
Example #7
0
async def get_user_status_list(req):
    date_etag_separator = ' || '
    user_id =req.match_info['user_id']
    session = req.app[HTTP_SESSION]
    if not user_id:
        return web.HTTPBadRequest(text='Expected /user_status/list/{user_id}')
    goodreads_url = 'https://www.goodreads.com/user_status/list/{}?format=rss'.format(user_id)
    headers = {}
    try:
        logger.info('Checking cache..')
        with open('./data/{}'.format(user_id), 'r') as cache:
            data = cache.readline()
            lastmodm, last_etag = data.strip().split(date_etag_separator)
        headers['If-Modified-Since'] = lastmodm
        headers['If-None-Match'] = last_etag
    except FileNotFoundError:
        pass
    async with session.get(goodreads_url, headers=headers) as resp:
        if resp.status == 304:
            return web.HTTPNotModified()
        last_modified = resp.headers.get('last-modified', '')
        etag = resp.headers.get('etag', '')
        if last_modified and etag:
            with open('./data/{}'.format(user_id), 'w') as cache:
                cache.write('{}{}{}'.format(last_modified, date_etag_separator, etag))
        raw_feed = await resp.text()
        new_feed = transform_feed(raw_feed.encode('utf-8'))
    return web.Response(body=new_feed, content_type='application/rss+xml')
Example #8
0
def _assert_if_none_match(request: web.Request, etag: T.Union[None, bool, str],
                          allow_weak: bool) -> bool:
    # language=rst
    """

    Todo:
        Evert lammerts schreef: Documenteren. Ik vind _assert_if_none_match niet
        makkelijk te lezen zonder docs voor de parameters. Bv: etag heeft als
        type None, bool, of str. En if etag is True: PreconditionFailed. Die
        semantiek is vast logisch in context maar niet op zichzelf.

    The If-None-Match: header is used in two scenarios:

    1.   GET requests by a caching client. In this case, the client will
         normally provide a list of (cached) ETags.
    2.   PUT requests, where the client intends to create a new resource and
         wants to avoid overwriting an existing resource. In this case, the
         client will normally provide only the asterisk "*" character.

    Returns:
        bool: indicates if an ``If-None-Match`` header was provided.

    Raises:
        web.HTTPBadRequest:
            If the request header is syntactically incorrect.
        web.HTTPPreconditionRequired:
            If parameter `require` is ``True`` and no precondition was provided
            by the client.
        web.HTTPPreconditionFailed:
            If the precondition failed and the request is *unsafe*.
        web.HTTPNotModified:
            If the precondition failed and the request is *safe*.

    """
    etags = _parse_if_header(request, _IF_NONE_MATCH)

    if etags is None:
        # if require and request.method in unsafe_methods:
        #     raise web.HTTPPreconditionRequired(text=_IF_NONE_MATCH)
        return False
    if etag is False or etag is None:
        return True
    if etags is _STAR:
        raise web.HTTPPreconditionFailed(text=_IF_NONE_MATCH)
    # From here on, we know that etags is a set of strings.
    if etag is True:
        raise web.HTTPPreconditionFailed(text="Resource doesn't have an ETag.")
    # From here on, we know that etag is a string:
    if _match_etags(etag, etags, allow_weak):
        if request.method in {hdrs.METH_GET, hdrs.METH_HEAD}:
            raise web.HTTPNotModified()
        else:
            raise web.HTTPPreconditionFailed(text=_IF_NONE_MATCH)
    return True
Example #9
0
async def add_pin(req: web.Request) -> web.Response:
    channel_id = req["match_info"]["channel_id"]
    message_id = req["match_info"]["message_id"]

    async with req.config_dict["pg_conn"].acquire() as conn:
        async with conn.transaction():
            pins_ids = await conn.fetchval(
                "SELECT pinned_ids FROM channels WHERE id = $1", channel_id
            )
            if len(pins_ids) >= 50:
                raise web.HTTPBadRequest(reason="Too many pins (>= 50)")

            if message_id in pins_ids:
                raise web.HTTPNotModified(reason="Already pinned")

            pin_success = await conn.fetchval(
                "SELECT * FROM add_channel_pin($1, $2)", message_id, channel_id
            )
            if not pin_success:
                raise web.HTTPBadRequest(
                    reason="Failed to pin message. Does it belong to channel?"
                )

            message = await conn.fetchrow(
                f"SELECT {MESSAGE} FROM create_message($1, $2, $3, $4, type:=$5)",
                req.config_dict["sf_gen"].gen_id(),
                channel_id,
                req["access_token"].user_id,
                "",
                MessageTypes.CHANNEL_PIN_ADD.value,
            )

    req.config_dict["emitter"].emit(
        events.MESSAGE_CREATE(payload=MESSAGE.to_json(message))
    )

    raise web.HTTPNoContent()
Example #10
0
 def _handler(request):
     try:
         res = yield from handler(request)
     except web.HTTPClientError as e:
         if Config.app.debug:
             error = traceback.format_exc()
             error_page = DEFAULT_ERROR_PRINT_PAGE % (error.replace(
                 '\n', '<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'))
             logging.error(error)
         else:
             try:
                 error_template = 'errors/' + \
                     str(e.status_code) + '.html'
                 error_page = app.get('__templating__').render(
                     error_template)
             except jinja2.exceptions.TemplateNotFound:
                 error_page = DEFAULT_HTTP_ERROR_PAGE % (
                     e.status_code, "Pyblog 1.0", e.status_code,
                     e.reason)
         res = web.Response(status=e.status_code,
                            body=error_page.encode("utf-8"))
     except web.HTTPServerError as e:
         if Config.app.debug:
             error = traceback.format_exc()
             error_page = DEFAULT_ERROR_PRINT_PAGE % (error.replace(
                 '\n', '<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'))
             logging.error(error)
         else:
             try:
                 error_template = 'errors/' + \
                     str(e.status_code) + '.html'
                 error_page = app.get('__templating__').render(
                     error_template)
             except jinja2.exceptions.TemplateNotFound:
                 error_page = DEFAULT_HTTP_ERROR_PAGE % (
                     e.status_code, "Pyblog 1.0", e.status_code,
                     e.reason)
         res = web.Response(status=e.status_code,
                            body=error_page.encode("utf-8"))
     except web.HTTPException as e:
         if int(e.status_code) == 304:
             return web.HTTPNotModified()
         if Config.app.debug:
             error = traceback.format_exc()
             error_page = DEFAULT_ERROR_PRINT_PAGE % (error.replace(
                 '\n', '<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'))
             logging.error(error)
         else:
             error_page = DEFAULT_HTTP_ERROR_PAGE % (
                 e.status_code, "Pyblog 1.0", e.status_code, e.reason)
         res = web.Response(status=e.status_code,
                            body=error_page.encode('utf-8'))
     except Exception as e:
         if Config.app.debug:
             error = traceback.format_exc()
             error_page = DEFAULT_ERROR_PRINT_PAGE % (error.replace(
                 '\n', '<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'))
             logging.error(error)
         else:
             error_page = DEFAULT_HTTP_ERROR_PAGE % (
                 500, "Pyblog 1.0", 500, "Server Internal Error")
         res = web.Response(status=500, body=error_page.encode("utf-8"))
     else:
         if app.get('status'):
             res = web.Response(
                 status=app.get('status').get('code'),
                 body=app.get('status').get('message').encode('utf-8'))
             return res
     return res
Example #11
0
def view(user, page: str, if_modified_since) -> web.Response:
    if page.endswith("/"):
        page += "Main Page"

    wiki_page = WikiPage(page)
    page_error = wiki_page.page_is_valid(page)
    if page_error:
        return error.view(user, page, page_error)

    # If there is a difference in case, nicely point this out to users.
    correct_page = wiki_page.page_get_correct_case(page)
    if correct_page != page:
        return error.view(
            user,
            page,
            f'"{page}" does not exist; did you mean [[{correct_page}]]?',
        )

    status_code = 200 if wiki_page.page_exists(page) else 404
    namespaced_page = page
    if not namespaced_page.startswith(("Category/", "File/", "Folder/", "Template/")):
        namespaced_page = f"Page/{namespaced_page}"

    can_cache = status_code == 200 and not namespaced_page.startswith("Folder/")

    if CACHE_PAGE_FOLDER:
        cache_filename = f"{CACHE_PAGE_FOLDER}/{namespaced_page}.html"
    else:
        cache_filename = None

    response = None

    # Check as we might have this page already on cache.
    if can_cache and namespaced_page in metadata.LAST_TIME_RENDERED:
        if (
            if_modified_since is not None
            and metadata.LAST_TIME_RENDERED[namespaced_page] <= if_modified_since.timestamp()
        ):
            # We already rendered this page before. If the browser has it in his
            # cache, he can simply reuse that if we haven't rendered since.
            response = web.HTTPNotModified()
        elif (
            not user
            and cache_filename
            and os.path.exists(cache_filename)
            and os.path.getmtime(cache_filename) >= metadata.LAST_TIME_RENDERED[namespaced_page]
        ):
            # We already rendered this page to disk. Serve from there.
            with open(cache_filename) as fp:
                body = fp.read()
            response = web.Response(body=body, content_type="text/html", status=status_code)

    # Cache miss; render the page.
    if response is None:
        body = _view(wiki_page, user, page)

        # Never cache anything in the Folder/.
        if can_cache:
            if not user and cache_filename:
                # Cache the file on disk
                os.makedirs(os.path.dirname(cache_filename), exist_ok=True)
                with open(cache_filename, "w") as fp:
                    fp.write(body)

                page_time = os.path.getmtime(cache_filename)
            else:
                # Accuracy of time.time() is higher than getmtime(), so
                # depending if we cached, use a different clock.
                page_time = time.time()

            # Only update the time if we don't have one yet. This makes sure
            # that LAST_TIME_RENDERED has the oldest timestamp possible.
            if namespaced_page not in metadata.LAST_TIME_RENDERED:
                metadata.LAST_TIME_RENDERED[namespaced_page] = page_time

        response = web.Response(body=body, content_type="text/html", status=status_code)

    # Inform the browser under which rules it can cache this page.
    if can_cache:
        response.last_modified = metadata.LAST_TIME_RENDERED[namespaced_page]
        response.headers["Vary"] = "Accept-Encoding, Cookie"
        response.headers["Cache-Control"] = "private, must-revalidate, max-age=0"
    return response