Пример #1
0
 def open(self, *args, **kwargs):
     api_key_headers = Headers({'x-hcx-auth-jwt-assertion': '123'})
     headers = kwargs.pop('headers', Headers())
     headers.extend(api_key_headers)
     kwargs['headers'] = headers
     return super().open(*args, **kwargs)
Пример #2
0
def test__encode_headers() -> None:
    assert _encode_headers(Headers({"Foo": "Bar"})) == [(b"foo", b"Bar")]
Пример #3
0
    def handle_error(self, e):
        '''
        Error handler for the API transforms a raised exception into a Flask response,
        with the appropriate HTTP status code and body.

        :param Exception e: the raised Exception object

        '''
        got_request_exception.send(current_app._get_current_object(),
                                   exception=e)

        include_message_in_response = current_app.config.get(
            "ERROR_INCLUDE_MESSAGE", True)
        default_data = {}

        headers = Headers()

        for typecheck, handler in six.iteritems(
                self._own_and_child_error_handlers):
            if isinstance(e, typecheck):
                result = handler(e)
                default_data, code, headers = unpack(
                    result, HTTPStatus.INTERNAL_SERVER_ERROR)
                break
        else:
            if isinstance(e, HTTPException):
                code = HTTPStatus(e.code)
                if include_message_in_response:
                    default_data = {
                        'message': getattr(e, 'description', code.phrase)
                    }
                headers = e.get_response().headers
            elif self._default_error_handler:
                result = self._default_error_handler(e)
                default_data, code, headers = unpack(
                    result, HTTPStatus.INTERNAL_SERVER_ERROR)
            else:
                code = HTTPStatus.INTERNAL_SERVER_ERROR
                if include_message_in_response:
                    default_data = {
                        'message': code.phrase,
                    }

        if include_message_in_response:
            default_data['message'] = default_data.get('message', str(e))

        data = getattr(e, 'data', default_data)
        fallback_mediatype = None

        if code >= HTTPStatus.INTERNAL_SERVER_ERROR:
            exc_info = sys.exc_info()
            if exc_info[1] is None:
                exc_info = None
            current_app.log_exception(exc_info)

        elif code == HTTPStatus.NOT_FOUND and current_app.config.get("ERROR_404_HELP", True) \
                and include_message_in_response:
            data['message'] = self._help_on_404(data.get('message', None))

        elif code == HTTPStatus.NOT_ACCEPTABLE and self.default_mediatype is None:
            # if we are handling NotAcceptable (406), make sure that
            # make_response uses a representation we support as the
            # default mediatype (so that make_response doesn't throw
            # another NotAcceptable error).
            supported_mediatypes = list(self.representations.keys())
            fallback_mediatype = supported_mediatypes[
                0] if supported_mediatypes else "text/plain"

        # Remove blacklisted headers
        for header in HEADERS_BLACKLIST:
            headers.pop(header, None)

        resp = self.make_response(data,
                                  code,
                                  headers,
                                  fallback_mediatype=fallback_mediatype)

        if code == HTTPStatus.UNAUTHORIZED:
            resp = self.unauthorized(resp)
        return resp
Пример #4
0
 def fixing_start_response(status, headers, exc_info=None):
     headers = Headers(headers)
     self.fix_headers(environ, headers, status)
     return start_response(status, headers.to_wsgi_list(), exc_info)
Пример #5
0
def handle_request(app, event, context):
    # if event.get("source") in ["scf.events", "serverless-plugin-warmup"]:
    #     print("Tencent Cloud Function warming event received, skipping handler")
    #     return {}

    if u"multiValueHeaders" in event:
        headers = Headers(event["multiValueHeaders"])
    else:
        headers = Headers(event["headers"])

    strip_stage_path = os.environ.get("STRIP_STAGE_PATH", "").lower().strip() in [
        "yes",
        "y",
        "true",
        "t",
        "1",
    ]
    if u"apigw.tencentcs.com" in headers.get(u"Host", u"") and not strip_stage_path:
        script_name = "/{}".format(event["requestContext"].get(u"stage", ""))
    else:
        script_name = ""

    # If a user is using a custom domain on API Gateway, they may have a base
    # path in their URL. This allows us to strip it out via an optional
    # environment variable.
    path_info = event["path"]
    base_path = os.environ.get("API_GATEWAY_BASE_PATH")
    print(base_path)
    if base_path:
        script_name = "/" + base_path

        if path_info.startswith(script_name):
            path_info = path_info[len(script_name) :] or "/"

    if u"body" in event:
        body = event[u"body"] or ""
    else:
        body = ""

    if event.get("isBase64Encoded", False):
        body = base64.b64decode(body)
    if isinstance(body, string_types):
        body = to_bytes(body, charset="utf-8")

    environ = {
        "CONTENT_LENGTH": str(len(body)),
        "CONTENT_TYPE": headers.get(u"Content-Type", ""),
        "PATH_INFO": url_unquote(path_info),
        "QUERY_STRING": encode_query_string(event),
        "REMOTE_ADDR": event["requestContext"]
        .get(u"identity", {})
        .get(u"sourceIp", ""),
        "REMOTE_USER": event["requestContext"]
        .get(u"authorizer", {})
        .get(u"principalId", ""),
        "REQUEST_METHOD": event["httpMethod"],
        "SCRIPT_NAME": script_name,
        "SERVER_NAME": headers.get(u"Host", "lambda"),
        "SERVER_PORT": headers.get(u"X-Forwarded-Port", "80"),
        "SERVER_PROTOCOL": "HTTP/1.1",
        "wsgi.errors": sys.stderr,
        "wsgi.input": BytesIO(body),
        "wsgi.multiprocess": False,
        "wsgi.multithread": False,
        "wsgi.run_once": False,
        "wsgi.url_scheme": headers.get(u"X-Forwarded-Proto", "http"),
        "wsgi.version": (1, 0),
        "serverless.authorizer": event["requestContext"].get(u"authorizer"),
        "serverless.event": event,
        "serverless.context": context,
        # TODO: Deprecate the following entries, as they do not comply with the WSGI
        # spec. For custom variables, the spec says:
        #
        #   Finally, the environ dictionary may also contain server-defined variables.
        #   These variables should be named using only lower-case letters, numbers, dots,
        #   and underscores, and should be prefixed with a name that is unique to the
        #   defining server or gateway.
        "API_GATEWAY_AUTHORIZER": event["requestContext"].get(u"authorizer"),
        "event": event,
        "context": context,
    }

    for key, value in environ.items():
        if isinstance(value, string_types):
            environ[key] = wsgi_encoding_dance(value)

    for key, value in headers.items():
        key = "HTTP_" + key.upper().replace("-", "_")
        if key not in ("HTTP_CONTENT_TYPE", "HTTP_CONTENT_LENGTH"):
            environ[key] = value

    response = Response.from_app(app, environ)

    returndict = {u"statusCode": response.status_code}

    if u"multiValueHeaders" in event:
        returndict["multiValueHeaders"] = group_headers(response.headers)
    else:
        returndict["headers"] = split_headers(response.headers)

    if event.get("requestContext").get("elb"):
        # If the request comes from ALB we need to add a status description
        returndict["statusDescription"] = u"%d %s" % (
            response.status_code,
            HTTP_STATUS_CODES[response.status_code],
        )

    if response.data:
        mimetype = response.mimetype or "text/plain"
        if (
            mimetype.startswith("text/") or mimetype in TEXT_MIME_TYPES
        ) and not response.headers.get("Content-Encoding", ""):
            returndict["body"] = response.get_data(as_text=True)
            returndict["isBase64Encoded"] = False
        else:
            returndict["body"] = base64.b64encode(response.data).decode("utf-8")
            returndict["isBase64Encoded"] = True

    return returndict
Пример #6
0
def verify_i18n(app):
    not_translated = 'code hello i18n'
    translated_fr = 'code bonjour'

    for accepted in ('unknown', 'en_US'):
        headers = Headers([('Accept-Language', accepted)])
        with app.test_request_context(headers=headers):
            assert not hasattr(request, 'babel_locale')
            assert not_translated == gettext(not_translated)
            assert hasattr(request, 'babel_locale')
            assert render_template_string('''
            {{ gettext('code hello i18n') }}
            ''').strip() == not_translated

    for lang in ('fr_FR', 'fr', 'fr-FR'):
        headers = Headers([('Accept-Language', lang)])
        with app.test_request_context(headers=headers):
            assert not hasattr(request, 'babel_locale')
            assert translated_fr == gettext(not_translated)
            assert hasattr(request, 'babel_locale')
            assert render_template_string('''
            {{ gettext('code hello i18n') }}
            ''').strip() == translated_fr

    # https://github.com/freedomofpress/securedrop/issues/2379
    headers = Headers([('Accept-Language',
                        'en-US;q=0.6,fr_FR;q=0.4,nb_NO;q=0.2')])
    with app.test_request_context(headers=headers):
        assert not hasattr(request, 'babel_locale')
        assert not_translated == gettext(not_translated)

    translated_cn = 'code chinese'

    for lang in ('zh-CN', 'zh-Hans-CN'):
        headers = Headers([('Accept-Language', lang)])
        with app.test_request_context(headers=headers):
            assert not hasattr(request, 'babel_locale')
            assert translated_cn == gettext(not_translated)
            assert hasattr(request, 'babel_locale')
            assert render_template_string('''
            {{ gettext('code hello i18n') }}
            ''').strip() == translated_cn

    translated_ar = 'code arabic'

    for lang in ('ar', 'ar-kw'):
        headers = Headers([('Accept-Language', lang)])
        with app.test_request_context(headers=headers):
            assert not hasattr(request, 'babel_locale')
            assert translated_ar == gettext(not_translated)
            assert hasattr(request, 'babel_locale')
            assert render_template_string('''
            {{ gettext('code hello i18n') }}
            ''').strip() == translated_ar

    with app.test_client() as c:
        page = c.get('/login')
        assert session.get('locale') is None
        assert not_translated == gettext(not_translated)
        assert b'?l=fr_FR' in page.data
        assert b'?l=en_US' not in page.data

        page = c.get('/login?l=fr_FR',
                     headers=Headers([('Accept-Language', 'en_US')]))
        assert session.get('locale') == 'fr_FR'
        assert translated_fr == gettext(not_translated)
        assert b'?l=fr_FR' not in page.data
        assert b'?l=en_US' in page.data

        c.get('/', headers=Headers([('Accept-Language', 'en_US')]))
        assert session.get('locale') == 'fr_FR'
        assert translated_fr == gettext(not_translated)

        c.get('/?l=')
        assert session.get('locale') is None
        assert not_translated == gettext(not_translated)

        c.get('/?l=en_US', headers=Headers([('Accept-Language', 'fr_FR')]))
        assert session.get('locale') == 'en_US'
        assert not_translated == gettext(not_translated)

        c.get('/', headers=Headers([('Accept-Language', 'fr_FR')]))
        assert session.get('locale') == 'en_US'
        assert not_translated == gettext(not_translated)

        c.get('/?l=', headers=Headers([('Accept-Language', 'fr_FR')]))
        assert session.get('locale') is None
        assert translated_fr == gettext(not_translated)

        c.get('/')
        assert session.get('locale') is None
        assert not_translated == gettext(not_translated)

        c.get('/?l=YY_ZZ')
        assert session.get('locale') is None
        assert not_translated == gettext(not_translated)

    with app.test_request_context():
        assert '' == render_template('locales.html')

    with app.test_client() as c:
        c.get('/')
        locales = render_template('locales.html')
        assert '?l=fr_FR' in locales
        assert '?l=en_US' not in locales
        c.get('/?l=ar')
        base = render_template('base.html')
        assert 'dir="rtl"' in base

    # the canonical locale name is norsk bokmål but
    # this is overriden with just norsk by i18n.NAME_OVERRIDES
    with app.test_client() as c:
        c.get('/?l=nb_NO')
        base = render_template('base.html')
        assert 'norsk' in base
        assert 'norsk bo' not in base
Пример #7
0
def handler(event, context):
    headers = Headers(event[u'headers'])

    if headers.get(u'Host', u'').endswith(u'.amazonaws.com'):
        script_name = '/{}'.format(event[u'requestContext'].get(u'stage', ''))
    else:
        script_name = ''

    # If a user is using a custom domain on API Gateway, they may have a base
    # path in their URL. This allows us to strip it out via an optional
    # environment variable.
    path_info = event[u'path']
    base_path = os.environ.get('API_GATEWAY_BASE_PATH', '')
    if base_path:
        script_name = '/' + base_path

        if path_info.startswith(script_name):
            path_info = path_info[len(script_name):]

    body = event[u'body'] or ''
    if event.get('isBase64Encoded', False):
        body = base64.b64decode(body)
    if isinstance(body, string_types):
        body = to_bytes(wsgi_encoding_dance(body))

    environ = {
        'API_GATEWAY_AUTHORIZER':
        event[u'requestContext'].get(u'authorizer', None),
        'CONTENT_LENGTH':
        str(len(body)),
        'CONTENT_TYPE':
        headers.get(u'Content-Type', ''),
        'PATH_INFO':
        path_info,
        'QUERY_STRING':
        url_encode(event.get(u'queryStringParameters', None) or {}),
        'REMOTE_ADDR':
        event[u'requestContext'].get(u'identity', {}).get(u'sourceIp', ''),
        'REMOTE_USER':
        event[u'requestContext'].get(u'authorizer',
                                     {}).get(u'principalId', ''),
        'REQUEST_METHOD':
        event[u'httpMethod'],
        'SCRIPT_NAME':
        script_name,
        'SERVER_NAME':
        headers.get(u'Host', 'lambda'),
        'SERVER_PORT':
        headers.get(u'X-Forwarded-Port', '80'),
        'SERVER_PROTOCOL':
        'HTTP/1.1',
        'event':
        event,
        'context':
        context,
        'wsgi.errors':
        sys.stderr,
        'wsgi.input':
        BytesIO(body),
        'wsgi.multiprocess':
        False,
        'wsgi.multithread':
        False,
        'wsgi.run_once':
        False,
        'wsgi.url_scheme':
        headers.get(u'X-Forwarded-Proto', 'http'),
        'wsgi.version': (1, 0),
    }

    for key, value in environ.items():
        if isinstance(value, string_types):
            environ[key] = wsgi_encoding_dance(value)

    for key, value in headers.items():
        key = 'HTTP_' + key.upper().replace('-', '_')
        if key not in ('HTTP_CONTENT_TYPE', 'HTTP_CONTENT_LENGTH'):
            environ[key] = value

    response = Response.from_app(wsgi_app, environ)

    # If there are multiple Set-Cookie headers, create case-mutated variations
    # in order to pass them through APIGW. This is a hack that's currently
    # needed. See: https://github.com/logandk/serverless-wsgi/issues/11
    # Source: https://github.com/Miserlou/Zappa/blob/master/zappa/middleware.py
    new_headers = [x for x in response.headers if x[0] != 'Set-Cookie']
    cookie_headers = [x for x in response.headers if x[0] == 'Set-Cookie']
    if len(cookie_headers) > 1:
        for header, new_name in zip(cookie_headers, all_casings('Set-Cookie')):
            new_headers.append((new_name, header[1]))
    elif len(cookie_headers) == 1:
        new_headers.extend(cookie_headers)

    returndict = {
        u'statusCode': response.status_code,
        u'headers': dict(new_headers)
    }

    if response.data:
        mimetype = response.mimetype or 'text/plain'
        if ((mimetype.startswith('text/') or mimetype in TEXT_MIME_TYPES)
                and not response.headers.get('Content-Encoding', '')):
            returndict['body'] = response.get_data(as_text=True)
        else:
            returndict['body'] = base64.b64encode(
                response.data).decode('utf-8')
            returndict['isBase64Encoded'] = 'true'

    return returndict
Пример #8
0
 def __init__(self):
     self.headers = Headers()
     self.status = 200
     self.content_type = None
Пример #9
0
def collect_task_headers():
    """Get headers required for appengine background task run."""
    return Headers(
        {k: v
         for k, v in request.headers if k not in BANNED_HEADERS})
Пример #10
0
 async def send_push_promise(self, path: str) -> None:
     headers = Headers()
     for name in SERVER_PUSH_HEADERS_TO_COPY:
         for value in self.headers.getlist(name):
             headers.add(name, value)
     await self._send_push_promise(path, headers)
Пример #11
0
    def handle_error(self, e):
        '''
        Error handler for the API transforms a raised exception into a Flask response,
        with the appropriate HTTP status code and body.

        :param Exception e: the raised Exception object

        '''
        got_request_exception.send(current_app._get_current_object(),
                                   exception=e)

        headers = Headers()
        if e.__class__ in self.error_handlers:
            handler = self.error_handlers[e.__class__]
            result = handler(e)
            default_data, code, headers = unpack(result, 500)
        elif isinstance(e, HTTPException):
            code = e.code
            default_data = {
                'message':
                getattr(e, 'description', HTTP_STATUS_CODES.get(code, ''))
            }
            headers = e.get_response().headers
        elif self._default_error_handler:
            result = self._default_error_handler(e)
            default_data, code, headers = unpack(result, 500)
        else:
            code = 500
            default_data = {
                'message': HTTP_STATUS_CODES.get(code, str(e)),
            }

        default_data['message'] = default_data.get('message', str(e))
        data = getattr(e, 'data', default_data)
        fallback_mediatype = None

        if code >= 500:
            exc_info = sys.exc_info()
            if exc_info[1] is None:
                exc_info = None
            current_app.log_exception(exc_info)

        elif code == 404 and current_app.config.get("ERROR_404_HELP", True):
            data['message'] = self._help_on_404(data.get('message', None))

        elif code == 406 and self.default_mediatype is None:
            # if we are handling NotAcceptable (406), make sure that
            # make_response uses a representation we support as the
            # default mediatype (so that make_response doesn't throw
            # another NotAcceptable error).
            supported_mediatypes = list(self.representations.keys())
            fallback_mediatype = supported_mediatypes[
                0] if supported_mediatypes else "text/plain"

        # Remove blacklisted headers
        for header in HEADERS_BLACKLIST:
            headers.pop(header, None)

        resp = self.make_response(data,
                                  code,
                                  headers,
                                  fallback_mediatype=fallback_mediatype)

        if code == 401:
            resp = self.unauthorized(resp)
        return resp
Пример #12
0
 def test_no_ims_header_ok(self):
     to_get = '/%s/full/full/0/default.jpg' % (self.test_jp2_color_id,)
     # get an image
     resp = self.client.get(to_get, headers=Headers())
     self.assertEqual(resp.status_code, 200)
Пример #13
0
 def test_verify_broken_pid_response(self, client):
     res = client.post(url_for('borrower_landing.verify_identity'),
                       headers=Headers([('Pid', '111112')]),
                       follow_redirects=False)
     self.assertEqual(urlparse(res.location).path, '/server-error')
     self.assertEqual(res.status_code, 302)
Пример #14
0
    def post(self, server=None, name=None, backup=None):
        """Performs an online restoration

        **POST** method provided by the webservice.
        This method returns a :mod:`flask.Response` object.

        :param server: Which server to collect data from when in multi-agent mode
        :type server: str

        :param name: The client we are working on
        :type name: str

        :param backup: The backup we are working on
        :type backup: int

        :returns: A :mod:`flask.Response` object representing an archive of the restored files
        """
        args = self.parser.parse_args()
        l = args['list']
        s = args['strip']
        f = args['format'] or 'zip'
        p = args['pass']
        resp = None
        # Check params
        if not l or not name or not backup:
            self.abort(400, 'missing arguments')
        # Manage ACL
        if (api.bui.acl and
            (not api.bui.acl.is_client_allowed(self.username, name, server)
             and not self.is_admin)):
            self.abort(
                403,
                'You are not allowed to perform a restoration for this client')
        if server:
            filename = 'restoration_%d_%s_on_%s_at_%s.%s' % (
                backup, name, server, strftime("%Y-%m-%d_%H_%M_%S",
                                               gmtime()), f)
        else:
            filename = 'restoration_%d_%s_at_%s.%s' % (
                backup, name, strftime("%Y-%m-%d_%H_%M_%S", gmtime()), f)
        if not server:
            # Standalone mode, we can just return the file unless there were errors
            archive, err = api.bui.cli.restore_files(name, backup, l, s, f, p)
            if not archive:
                if err:
                    return make_response(err, 500)
                self.abort(500)
            try:
                # Trick to delete the file while sending it to the client.
                # First, we open the file in reading mode so that a file handler
                # is open on the file. Then we delete it as soon as the request
                # ended. Because the fh is open, the file will be actually removed
                # when the transfer is done and the send_file method has closed
                # the fh. Only tested on Linux systems.
                fh = open(archive, 'r')

                @after_this_request
                def remove_file(response):
                    """Callback function to run after the client has handled
                    the request to remove temporary files.
                    """
                    import os
                    os.remove(archive)
                    return response

                resp = send_file(fh,
                                 as_attachment=True,
                                 attachment_filename=filename,
                                 mimetype='application/zip')
                resp.set_cookie('fileDownload', 'true')
            except Exception as e:
                api.bui.cli.logger.error(str(e))
                self.abort(500, str(e))
        else:
            # Multi-agent mode
            socket = None
            try:
                socket, length, err = api.bui.cli.restore_files(
                    name, backup, l, s, f, p, server)
                api.bui.cli.logger.debug('Need to get {} Bytes : {}'.format(
                    length, socket))

                if err:
                    api.bui.cli.logger.debug(
                        'Something went wrong: {}'.format(err))
                    socket.sendall(struct.pack('!Q', 2))
                    socket.sendall(b'RE')
                    socket.close()
                    return make_response(err, 500)

                def stream_file(sock, l):
                    """The restoration took place on another server so we need
                    to stream the file that is not present on the current
                    machine.
                    """
                    bsize = 1024
                    received = 0
                    if l < bsize:
                        bsize = l
                    while received < l:
                        buf = b''
                        r, _, _ = select.select([sock], [], [], 5)
                        if not r:
                            raise Exception('Socket timed-out')
                        buf += sock.recv(bsize)
                        if not buf:
                            continue
                        received += len(buf)
                        api.bui.cli.logger.debug('{}/{}'.format(received, l))
                        yield buf
                    sock.sendall(struct.pack('!Q', 2))
                    sock.sendall(b'RE')
                    sock.close()

                headers = Headers()
                headers.add('Content-Disposition',
                            'attachment',
                            filename=filename)
                headers['Content-Length'] = length

                resp = Response(stream_file(socket, length),
                                mimetype='application/zip',
                                headers=headers,
                                direct_passthrough=True)
                resp.set_cookie('fileDownload', 'true')
                resp.set_etag('flask-%s-%s-%s' %
                              (time(), length,
                               adler32(filename.encode('utf-8')) & 0xffffffff))
            except HTTPException as e:
                raise e
            except Exception as e:
                api.bui.cli.logger.error(str(e))
                self.abort(500, str(e))
        return resp
Пример #15
0
def index():
    headers = Headers()
    headers.add("Link", f'<{config["me"]}/auth>; rel="authorization_endpoint"')
    headers.add("Link", f'<{config["me"]}/token>; rel="token_endpoint"')

    return render_template("hcard.html", config=config), headers
Пример #16
0
def export_view():
    '''
    Code to make an excel file for download.
    Modified from...
    http://snipplr.com/view/69344/create-excel-file-with-xlwt-and-insert-in-flask-response-valid-for-jqueryfiledownload/    
    '''
    print "export"
    #########################
    # Code for creating Flask
    # response
    #########################
    response = Response()
    response.status_code = 200

    ##################################
    # Code for creating Excel data and
    # inserting into Flask response
    ##################################

    #.... code here for adding worksheets and cells
    #Create a new workbook object
    workbook = xlwt.Workbook()

    #Add a sheet
    daily_worksheet = workbook.add_sheet('Daily Statistics')

    #columns to write to
    year_column = 0
    lake_ID_column = year_column + 1
    day_of_year_column = lake_ID_column + 1
    bppr_column = day_of_year_column + 1
    pppr_column = bppr_column + 1

    #get data from session, write to daily_worksheet
    #PLATYPUS
    pond_list = unpickle_pond_list()

    year_list = []
    lake_id_list = []
    day_of_year_list = []
    bpprList = []
    ppprList = []

    for pond in pond_list:
        year = pond.get_year()
        lake_id = pond.get_lake_id()
        day_of_year = pond.get_day_of_year()
        bppr = pond.calculate_daily_whole_lake_benthic_primary_production_m2()
        pppr = pond.calculate_daily_whole_lake_phytoplankton_primary_production_m2(
        )

        year_list.append(year)
        lake_id_list.append(lake_id)
        day_of_year_list.append(day_of_year)
        bpprList.append(bppr)
        ppprList.append(pppr)

    write_column_to_worksheet(daily_worksheet, year_column, "year", year_list)
    write_column_to_worksheet(daily_worksheet, lake_ID_column, "Lake ID",
                              lake_id_list)
    write_column_to_worksheet(daily_worksheet, day_of_year_column,
                              "day of year", day_of_year_list)
    write_column_to_worksheet(daily_worksheet, bppr_column, "bppr_m2",
                              bpprList)
    write_column_to_worksheet(daily_worksheet, pppr_column, "pppr_m2",
                              ppprList)

    #Add another sheet
    hourly_worksheet = workbook.add_sheet('Hourly Statistics')

    #columns
    year_column = 0
    lake_ID_column = year_column + 1
    day_of_year_column = lake_ID_column + 1
    layer_column = day_of_year_column + 1
    hour_column = layer_column + 1
    hourly_ppr_rates_column = hour_column + 1

    #lists
    year_list = []
    lake_id_list = []
    day_of_year_list = []
    layer_list = []
    hour_list = []
    hourly_ppr_rates_list = []
    counter = 0
    for pond in pond_list:
        year = pond.get_year()
        lake_id = pond.get_lake_id()
        day_of_year = pond.get_day_of_year()
        for layer in range(0, len(pond.get_thermal_layer_depths())):
            hourly_ppr_in_this_layer_list = []
            hourly_ppr_in_this_layer_list = pond.calculate_hourly_phytoplankton_primary_production_rates_list_over_whole_day_in_thermal_layer(
                layer)
            hour = 0.0
            time_interval = pond.get_time_interval()
            for hourly_ppr in hourly_ppr_in_this_layer_list:
                year_list.append(year)
                lake_id_list.append(lake_id)
                day_of_year_list.append(day_of_year)
                layer_list.append(layer)
                hour_list.append(hour)
                hourly_ppr_rates_list.append(hourly_ppr)
                hour += time_interval
                counter += 1
                if (counter > 10000):
                    raise Exception("too big! The ouput is too big!!!")
                    sys.exit()
                    exit()

    #write to columns
    write_column_to_worksheet(hourly_worksheet, year_column, "year", year_list)
    write_column_to_worksheet(hourly_worksheet, lake_ID_column, "lake",
                              lake_id_list)
    write_column_to_worksheet(hourly_worksheet, day_of_year_column, "day",
                              day_of_year_list)
    write_column_to_worksheet(hourly_worksheet, layer_column, "layer",
                              layer_list)
    write_column_to_worksheet(hourly_worksheet, hour_column, "hour", hour_list)
    write_column_to_worksheet(hourly_worksheet, hourly_ppr_rates_column,
                              "ppr_m3", hourly_ppr_rates_list)

    #This is the magic. The workbook is saved into the StringIO object,
    #then that is passed to response for Flask to use.
    output = StringIO.StringIO()
    workbook.save(output)
    response.data = output.getvalue()

    ################################
    # Code for setting correct
    # headers for jquery.fileDownload
    #################################
    filename = "export.xls"
    mimetype_tuple = mimetypes.guess_type(filename)

    #HTTP headers for forcing file download
    response_headers = Headers({
        'Pragma':
        "public",  # required,
        'Expires':
        '0',
        'Cache-Control':
        'must-revalidate, post-check=0, pre-check=0',
        'Cache-Control':
        'private',  # required for certain browsers,
        'Content-Type':
        mimetype_tuple[0],
        'Content-Disposition':
        'attachment; filename=\"%s\";' % filename,
        'Content-Transfer-Encoding':
        'binary',
        'Content-Length':
        len(response.data)
    })

    if not mimetype_tuple[1] is None:
        response.update({'Content-Encoding': mimetype_tuple[1]})

    response.headers = response_headers

    #as per jquery.fileDownload.js requirements
    response.set_cookie('fileDownload', 'true', path='/')

    ################################
    # Return the response
    #################################
    return response
 def _validate_headers(self, headers_list):
     headers = Headers(headers_list)
     self._validate_content_type(headers)
     self._validate_x_content_type_options(headers)
     self._validate_csp_headers(headers)
Пример #18
0
 def headers(self):
     return Headers(self.raw.headers)
Пример #19
0
 def open(self, *args, **kwargs):
     headers = kwargs.pop('headers', Headers())
     kwargs['headers'] = headers
     return super().open(*args, **kwargs)
Пример #20
0
def send_file(filename_or_fp,
              mimetype=None,
              as_attachment=False,
              attachment_filename=None,
              add_etags=True,
              cache_timeout=None,
              conditional=False,
              last_modified=None):
    """Sends the contents of a file to the client.  This will use the
    most efficient method available and configured.  By default it will
    try to use the WSGI server's file_wrapper support.  Alternatively
    you can set the application's :attr:`~Flask.use_x_sendfile` attribute
    to ``True`` to directly emit an ``X-Sendfile`` header.  This however
    requires support of the underlying webserver for ``X-Sendfile``.

    By default it will try to guess the mimetype for you, but you can
    also explicitly provide one.  For extra security you probably want
    to send certain files as attachment (HTML for instance).  The mimetype
    guessing requires a `filename` or an `attachment_filename` to be
    provided.

    ETags will also be attached automatically if a `filename` is provided. You
    can turn this off by setting `add_etags=False`.

    If `conditional=True` and `filename` is provided, this method will try to
    upgrade the response stream to support range requests.  This will allow
    the request to be answered with partial content response.

    Please never pass filenames to this function from user sources;
    you should use :func:`send_from_directory` instead.

    .. versionadded:: 0.2

    .. versionadded:: 0.5
       The `add_etags`, `cache_timeout` and `conditional` parameters were
       added.  The default behavior is now to attach etags.

    .. versionchanged:: 0.7
       mimetype guessing and etag support for file objects was
       deprecated because it was unreliable.  Pass a filename if you are
       able to, otherwise attach an etag yourself.  This functionality
       will be removed in Flask 1.0

    .. versionchanged:: 0.9
       cache_timeout pulls its default from application config, when None.

    .. versionchanged:: 0.12
       The filename is no longer automatically inferred from file objects. If
       you want to use automatic mimetype and etag support, pass a filepath via
       `filename_or_fp` or `attachment_filename`.

    .. versionchanged:: 0.12
       The `attachment_filename` is preferred over `filename` for MIME-type
       detection.

    :param filename_or_fp: the filename of the file to send in `latin-1`.
                           This is relative to the :attr:`~Flask.root_path`
                           if a relative path is specified.
                           Alternatively a file object might be provided in
                           which case ``X-Sendfile`` might not work and fall
                           back to the traditional method.  Make sure that the
                           file pointer is positioned at the start of data to
                           send before calling :func:`send_file`.
    :param mimetype: the mimetype of the file if provided. If a file path is
                     given, auto detection happens as fallback, otherwise an
                     error will be raised.
    :param as_attachment: set to ``True`` if you want to send this file with
                          a ``Content-Disposition: attachment`` header.
    :param attachment_filename: the filename for the attachment if it
                                differs from the file's filename.
    :param add_etags: set to ``False`` to disable attaching of etags.
    :param conditional: set to ``True`` to enable conditional responses.

    :param cache_timeout: the timeout in seconds for the headers. When ``None``
                          (default), this value is set by
                          :meth:`~Flask.get_send_file_max_age` of
                          :data:`~flask.current_app`.
    :param last_modified: set the ``Last-Modified`` header to this value,
        a :class:`~datetime.datetime` or timestamp.
        If a file was passed, this overrides its mtime.
    """
    mtime = None
    fsize = None
    if isinstance(filename_or_fp, string_types):
        filename = filename_or_fp
        if not os.path.isabs(filename):
            filename = os.path.join(current_app.root_path, filename)
        file = None
        if attachment_filename is None:
            attachment_filename = os.path.basename(filename)
    else:
        file = filename_or_fp
        filename = None

    if mimetype is None:
        if attachment_filename is not None:
            mimetype = mimetypes.guess_type(attachment_filename)[0] \
                or 'application/octet-stream'

        if mimetype is None:
            raise ValueError(
                'Unable to infer MIME-type because no filename is available. '
                'Please set either `attachment_filename`, pass a filepath to '
                '`filename_or_fp` or set your own MIME-type via `mimetype`.')

    headers = Headers()
    if as_attachment:
        if attachment_filename is None:
            raise TypeError('filename unavailable, required for '
                            'sending as attachment')
        headers.add('Content-Disposition',
                    'attachment',
                    filename=attachment_filename)

    if current_app.use_x_sendfile and filename:
        if file is not None:
            file.close()
        headers['X-Sendfile'] = filename
        fsize = os.path.getsize(filename)
        headers['Content-Length'] = fsize
        data = None
    else:
        if file is None:
            file = open(filename, 'rb')
            mtime = os.path.getmtime(filename)
            fsize = os.path.getsize(filename)
            headers['Content-Length'] = fsize
        data = wrap_file(request.environ, file)

    rv = current_app.response_class(data,
                                    mimetype=mimetype,
                                    headers=headers,
                                    direct_passthrough=True)

    if last_modified is not None:
        rv.last_modified = last_modified
    elif mtime is not None:
        rv.last_modified = mtime

    rv.cache_control.public = True
    if cache_timeout is None:
        cache_timeout = current_app.get_send_file_max_age(filename)
    if cache_timeout is not None:
        rv.cache_control.max_age = cache_timeout
        rv.expires = int(time() + cache_timeout)

    if add_etags and filename is not None:
        from warnings import warn

        try:
            rv.set_etag(
                '%s-%s-%s' %
                (os.path.getmtime(filename), os.path.getsize(filename),
                 adler32(
                     filename.encode('utf-8') if isinstance(
                         filename, text_type) else filename) & 0xffffffff))
        except OSError:
            warn(
                'Access %s failed, maybe it does not exist, so ignore etags in '
                'headers' % filename,
                stacklevel=2)

    if conditional:
        if callable(getattr(Range, 'to_content_range_header', None)):
            # Werkzeug supports Range Requests
            # Remove this test when support for Werkzeug <0.12 is dropped
            try:
                rv = rv.make_conditional(request,
                                         accept_ranges=True,
                                         complete_length=fsize)
            except RequestedRangeNotSatisfiable:
                file.close()
                raise
        else:
            rv = rv.make_conditional(request)
        # make sure we don't send x-sendfile for servers that
        # ignore the 304 status code for x-sendfile.
        if rv.status_code == 304:
            rv.headers.pop('x-sendfile', None)
    return rv
Пример #21
0
def clinvar_submissions(institute_id):
    def generate_csv(header, lines):
        yield header + '\n'
        for line in lines:  # lines have already quoted fields
            yield line + '\n'

    if request.method == 'POST':
        submission_id = request.form.get('submission_id')
        if request.form.get('update_submission'):
            if request.form.get(
                    'update_submission') == 'close':  # close a submission
                store.update_clinvar_submission_status(current_user.email,
                                                       submission_id, 'closed')
            elif request.form.get('update_submission') == 'open':
                store.update_clinvar_submission_status(
                    current_user.email, submission_id,
                    'open')  # open a submission
            elif request.form.get(
                    'update_submission') == 'register_id' and request.form.get(
                        'clinvar_id'
                    ):  # provide an official clinvar submission ID
                result = store.update_clinvar_id(
                    clinvar_id=request.form.get('clinvar_id'),
                    submission_id=submission_id)
            elif request.form.get(
                    'update_submission') == 'delete':  # delete a submission
                deleted_objects, deleted_submissions = store.delete_submission(
                    submission_id=submission_id)
                flash(
                    "Removed {} objects and {} submission from database".
                    format(deleted_objects, deleted_submissions), 'info')
        elif request.form.get(
                'delete_variant'):  # delete a variant from a submission
            store.delete_clinvar_object(
                object_id=request.form.get('delete_variant'),
                object_type='variant_data',
                submission_id=submission_id
            )  # remove variant and associated_casedata
        elif request.form.get(
                'delete_casedata'):  # delete a case from a submission
            store.delete_clinvar_object(
                object_id=request.form.get('delete_casedata'),
                object_type='case_data',
                submission_id=submission_id
            )  # remove just the casedata associated to a variant
        else:  # Download submission CSV files (for variants or casedata)

            clinvar_subm_id = request.form.get('clinvar_id')
            if clinvar_subm_id == '':
                flash(
                    'In order to download a submission CSV file you should register a Clinvar submission Name first!',
                    'warning')
                return redirect(request.referrer)

            csv_type = ''
            csv_type = request.form.get('csv_type')

            submission_objs = store.clinvar_objs(
                submission_id=submission_id, key_id=csv_type
            )  # a list of clinvar submission objects (variants or casedata)
            if submission_objs:
                csv_header_obj = controllers.clinvar_header(
                    submission_objs, csv_type
                )  # custom csv header (dict as in constants CLINVAR_HEADER and CASEDATA_HEADER, but with required fields only)
                csv_lines = controllers.clinvar_lines(
                    submission_objs, csv_header_obj
                )  # csv lines (one for each variant/casedata to be submitted)
                csv_header = list(csv_header_obj.values())
                csv_header = ['"' + str(x) + '"' for x in csv_header
                              ]  # quote columns in header for csv rendering

                headers = Headers()
                headers.add('Content-Disposition',
                            'attachment',
                            filename=clinvar_subm_id + '_' +
                            str(datetime.datetime.now().strftime("%Y-%m-%d")) +
                            '.csv')
                return Response(generate_csv(','.join(csv_header), csv_lines),
                                mimetype='text/csv',
                                headers=headers)
            else:
                flash(
                    'There are no submission objects of type "{}" to include in the csv file!'
                    .format(csv_type), 'warning')

    data = {
        'submissions':
        controllers.clinvar_submissions(store, current_user.email,
                                        institute_id),
        'institute_id':
        institute_id,
        'variant_header_fields':
        CLINVAR_HEADER,
        'casedata_header_fields':
        CASEDATA_HEADER
    }
    return data
Пример #22
0
def wsgi_environ(method, url, data=None, content_type=None, headers={}):
    hdrs = Headers(headers)
    b = EnvironBuilder(method=method, path=url, headers=hdrs)
    return b.get_environ()
Пример #23
0
def send_file(
    filename_or_fp,
    mimetype=None,
    as_attachment=False,
    attachment_filename=None,
    add_etags=True,
    cache_timeout=None,
    conditional=False,
    last_modified=None,
):
    """Sends the contents of a file to the client.  This will use the
    most efficient method available and configured.  By default it will
    try to use the WSGI server's file_wrapper support.  Alternatively
    you can set the application's :attr:`~Flask.use_x_sendfile` attribute
    to ``True`` to directly emit an ``X-Sendfile`` header.  This however
    requires support of the underlying webserver for ``X-Sendfile``.

    By default it will try to guess the mimetype for you, but you can
    also explicitly provide one.  For extra security you probably want
    to send certain files as attachment (HTML for instance).  The mimetype
    guessing requires a `filename` or an `attachment_filename` to be
    provided.

    ETags will also be attached automatically if a `filename` is provided. You
    can turn this off by setting `add_etags=False`.

    If `conditional=True` and `filename` is provided, this method will try to
    upgrade the response stream to support range requests.  This will allow
    the request to be answered with partial content response.

    Please never pass filenames to this function from user sources;
    you should use :func:`send_from_directory` instead.

    .. versionadded:: 0.2

    .. versionadded:: 0.5
       The `add_etags`, `cache_timeout` and `conditional` parameters were
       added.  The default behavior is now to attach etags.

    .. versionchanged:: 0.7
       mimetype guessing and etag support for file objects was
       deprecated because it was unreliable.  Pass a filename if you are
       able to, otherwise attach an etag yourself.  This functionality
       will be removed in Flask 1.0

    .. versionchanged:: 0.9
       cache_timeout pulls its default from application config, when None.

    .. versionchanged:: 0.12
       The filename is no longer automatically inferred from file objects. If
       you want to use automatic mimetype and etag support, pass a filepath via
       `filename_or_fp` or `attachment_filename`.

    .. versionchanged:: 0.12
       The `attachment_filename` is preferred over `filename` for MIME-type
       detection.

    .. versionchanged:: 1.0
        UTF-8 filenames, as specified in `RFC 2231`_, are supported.

    .. _RFC 2231: https://tools.ietf.org/html/rfc2231#section-4

    .. versionchanged:: 1.0.3
        Filenames are encoded with ASCII instead of Latin-1 for broader
        compatibility with WSGI servers.

    .. versionchanged:: 1.1
        Filename may be a :class:`~os.PathLike` object.

    .. versionadded:: 1.1
        Partial content supports :class:`~io.BytesIO`.

    :param filename_or_fp: the filename of the file to send.
                           This is relative to the :attr:`~Flask.root_path`
                           if a relative path is specified.
                           Alternatively a file object might be provided in
                           which case ``X-Sendfile`` might not work and fall
                           back to the traditional method.  Make sure that the
                           file pointer is positioned at the start of data to
                           send before calling :func:`send_file`.
    :param mimetype: the mimetype of the file if provided. If a file path is
                     given, auto detection happens as fallback, otherwise an
                     error will be raised.
    :param as_attachment: set to ``True`` if you want to send this file with
                          a ``Content-Disposition: attachment`` header.
    :param attachment_filename: the filename for the attachment if it
                                differs from the file's filename.
    :param add_etags: set to ``False`` to disable attaching of etags.
    :param conditional: set to ``True`` to enable conditional responses.

    :param cache_timeout: the timeout in seconds for the headers. When ``None``
                          (default), this value is set by
                          :meth:`~Flask.get_send_file_max_age` of
                          :data:`~flask.current_app`.
    :param last_modified: set the ``Last-Modified`` header to this value,
        a :class:`~datetime.datetime` or timestamp.
        If a file was passed, this overrides its mtime.
    """
    mtime = None
    fsize = None

    if hasattr(filename_or_fp, "__fspath__"):
        filename_or_fp = fspath(filename_or_fp)

    if isinstance(filename_or_fp, string_types):
        filename = filename_or_fp
        if not os.path.isabs(filename):
            filename = os.path.join(current_app.root_path, filename)
        file = None
        if attachment_filename is None:
            attachment_filename = os.path.basename(filename)
    else:
        file = filename_or_fp
        filename = None

    if mimetype is None:
        if attachment_filename is not None:
            mimetype = (mimetypes.guess_type(attachment_filename)[0]
                        or "application/octet-stream")

        if mimetype is None:
            raise ValueError(
                "Unable to infer MIME-type because no filename is available. "
                "Please set either `attachment_filename`, pass a filepath to "
                "`filename_or_fp` or set your own MIME-type via `mimetype`.")

    headers = Headers()
    if as_attachment:
        if attachment_filename is None:
            raise TypeError(
                "filename unavailable, required for sending as attachment")

        if not isinstance(attachment_filename, text_type):
            attachment_filename = attachment_filename.decode("utf-8")

        try:
            attachment_filename = attachment_filename.encode("ascii")
        except UnicodeEncodeError:
            filenames = {
                "filename":
                unicodedata.normalize("NFKD", attachment_filename).encode(
                    "ascii", "ignore"),
                "filename*":
                "UTF-8''%s" % url_quote(attachment_filename, safe=b""),
            }
        else:
            filenames = {"filename": attachment_filename}

        headers.add("Content-Disposition", "attachment", **filenames)

    if current_app.use_x_sendfile and filename:
        if file is not None:
            file.close()
        headers["X-Sendfile"] = filename
        fsize = os.path.getsize(filename)
        headers["Content-Length"] = fsize
        data = None
    else:
        if file is None:
            file = open(filename, "rb")
            mtime = os.path.getmtime(filename)
            fsize = os.path.getsize(filename)
            headers["Content-Length"] = fsize
        elif isinstance(file, io.BytesIO):
            try:
                fsize = file.getbuffer().nbytes
            except AttributeError:
                # Python 2 doesn't have getbuffer
                fsize = len(file.getvalue())
            headers["Content-Length"] = fsize
        data = wrap_file(request.environ, file)

    rv = current_app.response_class(data,
                                    mimetype=mimetype,
                                    headers=headers,
                                    direct_passthrough=True)

    if last_modified is not None:
        rv.last_modified = last_modified
    elif mtime is not None:
        rv.last_modified = mtime

    rv.cache_control.public = True
    if cache_timeout is None:
        cache_timeout = current_app.get_send_file_max_age(filename)
    if cache_timeout is not None:
        rv.cache_control.max_age = cache_timeout
        rv.expires = int(time() + cache_timeout)

    if add_etags and filename is not None:
        from warnings import warn

        try:
            rv.set_etag("%s-%s-%s" % (
                os.path.getmtime(filename),
                os.path.getsize(filename),
                adler32(
                    filename.encode("utf-8") if isinstance(
                        filename, text_type) else filename)
                & 0xFFFFFFFF,
            ))
        except OSError:
            warn(
                "Access %s failed, maybe it does not exist, so ignore etags in "
                "headers" % filename,
                stacklevel=2,
            )

    if conditional:
        try:
            rv = rv.make_conditional(request,
                                     accept_ranges=True,
                                     complete_length=fsize)
        except RequestedRangeNotSatisfiable:
            if file is not None:
                file.close()
            raise
        # make sure we don't send x-sendfile for servers that
        # ignore the 304 status code for x-sendfile.
        if rv.status_code == 304:
            rv.headers.pop("x-sendfile", None)
    return rv
Пример #24
0
    def export_xls(name, app, user_id=None):
        # Flask response
        response = Response()
        response.status_code = 200

        # Create an in-memory output file for the new workbook.
        output = io.BytesIO()

        if name.lower() == 'all':
            # Get Questionnaire Names
            questionnaire_names = ExportXlsService.get_questionnaire_names(app)
        else:
            cl = ExportService.get_class(name)
            info = ExportService.get_single_table_info(cl, None)
            questionnaire_names = [name]
            for sub_table in info.sub_tables:
                questionnaire_names.append(sub_table.class_name)

        # Create workbook
        workbook = xlsxwriter.Workbook(output, {'in_memory': True})

        # Add a bold format to use to highlight cells.
        bold = workbook.add_format({'bold': True})

        for qname in questionnaire_names:
            worksheet = workbook.add_worksheet(
                ExportXlsService.pretty_title_from_snakecase(qname))
            # Some data we want to write to the worksheet.
            # Get header fields from the schema in case the first record is missing fields
            schema = ExportService.get_schema(qname, many=True)
            header_fields = schema.fields
            if user_id:
                questionnaires = schema.dump(ExportService().get_data(
                    name=qname, user_id=user_id))
            else:
                questionnaires = schema.dump(
                    ExportService().get_data(name=qname))

            # Start from the first cell. Rows and columns are zero indexed.
            row = 0
            col = 0

            # Write the column headers.
            for key in header_fields:
                worksheet.write(row, col, key, bold)
                col += 1
            row += 1

            # Iterate over the data and write it out row by row.
            for item in questionnaires[0]:
                col = -1
                for key in item:
                    if key == "_links":
                        continue
                    if isinstance(item[key], dict):
                        continue
                    if isinstance(item[key],
                                  list) and len(item[key]) > 0 and isinstance(
                                      item[key][0], dict):
                        continue  # Don't try to represent sub-table data.
                    if isinstance(item[key], list):
                        list_string = ''
                        for value in item[key]:
                            list_string = list_string + str(value) + ', '
                        col += 1
                        worksheet.write(row, col, list_string)
                    else:
                        col += 1
                        worksheet.write(row, col, item[key])
                row += 1

        # Close the workbook before streaming the data.
        workbook.close()

        # Rewind the buffer.
        output.seek(0)

        # Add output to response
        response.data = output.read()

        # Set filename
        file_name = 'export_{}_{}.xlsx'.format(name, datetime.utcnow())

        # HTTP headers for forcing file download
        response_headers = Headers({
            'Pragma':
            "public",  # required,
            'Expires':
            '0',
            'Cache-Control':
            'must-revalidate, private',  # required for certain browsers
            'Content-Type':
            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            'Content-Disposition':
            'attachment; filename=\"%s\";' % file_name,
            'Content-Transfer-Encoding':
            'binary',
            'Access-Control-Expose-Headers':
            'x-filename',
            'x-filename':
            file_name,
            'Content-Length':
            len(response.data)
        })

        # Add headers
        response.headers = response_headers

        # jquery.fileDownload.js requirements
        response.set_cookie('fileDownload', 'true', path='/')

        # Return the response
        return response
Пример #25
0
        "query_string": b"",
        "subprotocols": [],
        "extensions": {
            "websocket.http.response": {}
        },
    }
    connection = ASGIWebsocketConnection(app, scope)
    websocket = connection._create_websocket_from_scope(lambda: None)
    assert websocket.path == "/path"


@pytest.mark.asyncio
@pytest.mark.parametrize(
    "scope, headers, subprotocol, has_headers",
    [
        ({}, Headers(), None, False),
        ({}, Headers(), "abc", False),
        ({
            "asgi": {
                "spec_version": "2.1"
            }
        }, Headers({"a": "b"}), None, True),
        ({
            "asgi": {
                "spec_version": "2.1.1"
            }
        }, Headers({"a": "b"}), None, True),
    ],
)
async def test_websocket_accept_connection(scope: dict, headers: Headers,
                                           subprotocol: Optional[str],
Пример #26
0
    def __init__(self,
                 path='/',
                 base_url=None,
                 query_string=None,
                 method='GET',
                 input_stream=None,
                 content_type=None,
                 content_length=None,
                 errors_stream=None,
                 multithread=False,
                 multiprocess=False,
                 run_once=False,
                 headers=None,
                 data=None,
                 environ_base=None,
                 environ_overrides=None,
                 charset='utf-8',
                 mimetype=None):
        path_s = make_literal_wrapper(path)
        if query_string is None and path_s('?') in path:
            path, query_string = path.split(path_s('?'), 1)
        self.charset = charset
        self.path = iri_to_uri(path)
        if base_url is not None:
            base_url = url_fix(iri_to_uri(base_url, charset), charset)
        self.base_url = base_url
        if isinstance(query_string, (bytes, text_type)):
            self.query_string = query_string
        else:
            if query_string is None:
                query_string = MultiDict()
            elif not isinstance(query_string, MultiDict):
                query_string = MultiDict(query_string)
            self.args = query_string
        self.method = method
        if headers is None:
            headers = Headers()
        elif not isinstance(headers, Headers):
            headers = Headers(headers)
        self.headers = headers
        if content_type is not None:
            self.content_type = content_type
        if errors_stream is None:
            errors_stream = sys.stderr
        self.errors_stream = errors_stream
        self.multithread = multithread
        self.multiprocess = multiprocess
        self.run_once = run_once
        self.environ_base = environ_base
        self.environ_overrides = environ_overrides
        self.input_stream = input_stream
        self.content_length = content_length
        self.closed = False

        if data:
            if input_stream is not None:
                raise TypeError('can\'t provide input stream and data')
            if hasattr(data, 'read'):
                data = data.read()
            if isinstance(data, text_type):
                data = data.encode(self.charset)
            if isinstance(data, bytes):
                self.input_stream = BytesIO(data)
                if self.content_length is None:
                    self.content_length = len(data)
            else:
                for key, value in _iter_data(data):
                    if isinstance(value, (tuple, dict)) or \
                       hasattr(value, 'read'):
                        self._add_file_from_data(key, value)
                    else:
                        self.form.setlistdefault(key).append(value)

        if mimetype is not None:
            self.mimetype = mimetype
Пример #27
0
def send_file(filename_or_fp,
              mimetype=None,
              as_attachment=False,
              attachment_filename=None,
              add_etags=True,
              cache_timeout=None,
              conditional=False):
    """Sends the contents of a file to the client.  This will use the
    most efficient method available and configured.  By default it will
    try to use the WSGI server's file_wrapper support.  Alternatively
    you can set the application's :attr:`~Flask.use_x_sendfile` attribute
    to ``True`` to directly emit an ``X-Sendfile`` header.  This however
    requires support of the underlying webserver for ``X-Sendfile``.

    By default it will try to guess the mimetype for you, but you can
    also explicitly provide one.  For extra security you probably want
    to send certain files as attachment (HTML for instance).  The mimetype
    guessing requires a `filename` or an `attachment_filename` to be
    provided.

    Please never pass filenames to this function from user sources;
    you should use :func:`send_from_directory` instead.

    .. versionadded:: 0.2

    .. versionadded:: 0.5
       The `add_etags`, `cache_timeout` and `conditional` parameters were
       added.  The default behavior is now to attach etags.

    .. versionchanged:: 0.7
       mimetype guessing and etag support for file objects was
       deprecated because it was unreliable.  Pass a filename if you are
       able to, otherwise attach an etag yourself.  This functionality
       will be removed in Flask 1.0

    .. versionchanged:: 0.9
       cache_timeout pulls its default from application config, when None.

    :param filename_or_fp: the filename of the file to send.  This is
                           relative to the :attr:`~Flask.root_path` if a
                           relative path is specified.
                           Alternatively a file object might be provided
                           in which case ``X-Sendfile`` might not work and
                           fall back to the traditional method.  Make sure
                           that the file pointer is positioned at the start
                           of data to send before calling :func:`send_file`.
    :param mimetype: the mimetype of the file if provided, otherwise
                     auto detection happens.
    :param as_attachment: set to ``True`` if you want to send this file with
                          a ``Content-Disposition: attachment`` header.
    :param attachment_filename: the filename for the attachment if it
                                differs from the file's filename.
    :param add_etags: set to ``False`` to disable attaching of etags.
    :param conditional: set to ``True`` to enable conditional responses.

    :param cache_timeout: the timeout in seconds for the headers. When ``None``
                          (default), this value is set by
                          :meth:`~Flask.get_send_file_max_age` of
                          :data:`~flask.current_app`.
    """
    mtime = None
    if isinstance(filename_or_fp, string_types):
        filename = filename_or_fp
        file = None
    else:
        from warnings import warn
        file = filename_or_fp
        filename = getattr(file, 'name', None)

        # XXX: this behavior is now deprecated because it was unreliable.
        # removed in Flask 1.0
        if not attachment_filename and not mimetype \
           and isinstance(filename, string_types):
            warn(DeprecationWarning(
                'The filename support for file objects '
                'passed to send_file is now deprecated.  Pass an '
                'attach_filename if you want mimetypes to be guessed.'),
                 stacklevel=2)
        if add_etags:
            warn(DeprecationWarning(
                'In future flask releases etags will no '
                'longer be generated for file objects passed to the send_file '
                'function because this behavior was unreliable.  Pass '
                'filenames instead if possible, otherwise attach an etag '
                'yourself based on another value'),
                 stacklevel=2)

    if filename is not None:
        if not os.path.isabs(filename):
            filename = os.path.join(current_app.root_path, filename)
    if mimetype is None and (filename or attachment_filename):
        mimetype = mimetypes.guess_type(filename or attachment_filename)[0]
    if mimetype is None:
        mimetype = 'application/octet-stream'

    headers = Headers()
    if as_attachment:
        if attachment_filename is None:
            if filename is None:
                raise TypeError('filename unavailable, required for '
                                'sending as attachment')
            attachment_filename = os.path.basename(filename)
        headers.add('Content-Disposition',
                    'attachment',
                    filename=attachment_filename)

    if current_app.use_x_sendfile and filename:
        if file is not None:
            file.close()
        headers['X-Sendfile'] = filename
        headers['Content-Length'] = os.path.getsize(filename)
        data = None
    else:
        if file is None:
            file = open(filename, 'rb')
            mtime = os.path.getmtime(filename)
            headers['Content-Length'] = os.path.getsize(filename)
        data = wrap_file(request.environ, file)

    rv = current_app.response_class(data,
                                    mimetype=mimetype,
                                    headers=headers,
                                    direct_passthrough=True)

    # if we know the file modification date, we can store it as
    # the time of the last modification.
    if mtime is not None:
        rv.last_modified = int(mtime)

    rv.cache_control.public = True
    if cache_timeout is None:
        cache_timeout = current_app.get_send_file_max_age(filename)
    if cache_timeout is not None:
        rv.cache_control.max_age = cache_timeout
        rv.expires = int(time() + cache_timeout)

    if add_etags and filename is not None:
        try:
            rv.set_etag(
                'flask-%s-%s-%s' %
                (os.path.getmtime(filename), os.path.getsize(filename),
                 adler32(
                     filename.encode('utf-8') if isinstance(
                         filename, text_type) else filename) & 0xffffffff))
        except OSError:
            warn(
                'Access %s failed, maybe it does not exist, so ignore etags in '
                'headers' % filename,
                stacklevel=2)

        if conditional:
            rv = rv.make_conditional(request)
            # make sure we don't send x-sendfile for servers that
            # ignore the 304 status code for x-sendfile.
            if rv.status_code == 304:
                rv.headers.pop('x-sendfile', None)
    return rv
Пример #28
0
def proxy_request(host, file=""):
    hostname, port = parse_host_port(host)

    print "H: '%s' P: %d" % (hostname, port)
    print "F: '%s'" % (file)
    # Whitelist a few headers to pass on
    request_headers = {}
    for h in ["Cookie", "Referer", "X-Csrf-Token"]:
        if h in request.headers:
            request_headers[h] = request.headers[h]

    if request.query_string:
        path = "/%s?%s" % (file, request.query_string)
    else:
        path = "/" + file

    if request.method == "POST" or request.method == "PUT":
        form_data = list(iterform(request.form))
        form_data = urllib.urlencode(form_data)
        request_headers["Content-Length"] = len(form_data)
    else:
        form_data = None

    print "Debug: I am here"
    print "Debug: host" + hostname
    print "Debug: path " + path
    conn = httplib.HTTPConnection("127.0.0.1", 8087)
    # conn = httplib.HTTPConnection(hostname, port)
    conn.request(request.method,
                 'http://' + host + path,
                 body=form_data,
                 headers=request_headers)
    resp = conn.getresponse()
    print "Debug: request"

    # Clean up response headers for forwarding
    d = {}
    response_headers = Headers()
    for key, value in resp.getheaders():
        print "HEADER: '%s':'%s'" % (key, value)
        d[key.lower()] = value
        if key in ["content-length", "connection", "content-type"]:
            continue

        if key == "set-cookie":
            cookies = value.split(",")
            [response_headers.add(key, c) for c in cookies]
        else:
            response_headers.add(key, value)

    # If this is a redirect, munge the Location URL
    if "location" in response_headers:
        redirect = response_headers["location"]
        parsed = urlparse.urlparse(request.url)
        redirect_parsed = urlparse.urlparse(redirect)

        redirect_host = redirect_parsed.netloc
        if not redirect_host:
            redirect_host = "%s:%d" % (hostname, port)

        redirect_path = redirect_parsed.path
        if redirect_parsed.query:
            redirect_path += "?" + redirect_parsed.query

        munged_path = url_for(".proxy_request",
                              host=redirect_host,
                              file=redirect_path[1:])

        url = "%s://%s%s" % (parsed.scheme, parsed.netloc, munged_path)
        response_headers["location"] = url

    # Rewrite URLs in the content to point to our URL schemt.method == " instead.
    # Ugly, but seems to mostly work.
    root = url_for(".proxy_request", host=host)
    contents = resp.read()

    # Restructing Contents.
    print "Debug content-type: "
    print d
    """
    if d["content-type"].find("application/json") >= 0:
        # JSON format conentens will be modified here.
        jc = json.loads(contents)
        if jc.has_key("nodes"):
            del jc["nodes"]
        contents = json.dumps(jc)

    else:
        # Generic HTTP.
        for regex in REGEXES:
           contents = regex.sub(r'\1%s' % root, contents)
    """
    for regex in REGEXES:
        contents = regex.sub(r'\1%s' % root, contents)

    flask_response = Response(response=contents,
                              status=resp.status,
                              headers=response_headers,
                              content_type=resp.getheader('content-type'))
    return flask_response
Пример #29
0
 def open(self, *args, **kwargs):
     headers = kwargs.pop("headers", Headers())
     headers.extend(
         Headers({"Authorization": "Bearer %s" % jwt_test_token}))
     kwargs["headers"] = headers
     return super().open(*args, **kwargs)
Пример #30
0
    def handle_error(self, e):
        """Error handler for the API transforms a raised exception into a Flask
        response, with the appropriate HTTP status code and body.

        :param e: the raised Exception object
        :type e: Exception

        """
        got_request_exception.send(current_app._get_current_object(), exception=e)

        if not isinstance(e, HTTPException) and current_app.propagate_exceptions:
            exc_type, exc_value, tb = sys.exc_info()
            if exc_value is e:
                raise
            else:
                raise e

        headers = Headers()
        if isinstance(e, HTTPException):
            code = e.code
            default_data = {
                'message': getattr(e, 'description', http_status_message(code))
            }
            headers = e.get_response().headers
        else:
            code = 500
            default_data = {
                'message': http_status_message(code),
            }

        # Werkzeug exceptions generate a content-length header which is added
        # to the response in addition to the actual content-length header
        # https://github.com/flask-restful/flask-restful/issues/534
        remove_headers = ('Content-Length',)

        for header in remove_headers:
            headers.pop(header, None)

        data = getattr(e, 'data', default_data)

        if code >= 500:
            exc_info = sys.exc_info()
            if exc_info[1] is None:
                exc_info = None
            current_app.log_exception(exc_info)

        help_on_404 = current_app.config.get("ERROR_404_HELP", True)
        if code == 404 and help_on_404:
            rules = dict([(re.sub('(<.*>)', '', rule.rule), rule.rule)
                          for rule in current_app.url_map.iter_rules()])
            close_matches = difflib.get_close_matches(request.path, rules.keys())
            if close_matches:
                # If we already have a message, add punctuation and continue it.
                if "message" in data:
                    data["message"] = data["message"].rstrip('.') + '. '
                else:
                    data["message"] = ""

                data['message'] += 'You have requested this URI [' + request.path + \
                                   '] but did you mean ' + \
                                   ' or '.join((
                                       rules[match] for match in close_matches)
                                   ) + ' ?'

        error_cls_name = type(e).__name__
        if error_cls_name in self.errors:
            custom_data = self.errors.get(error_cls_name, {})
            code = custom_data.get('status', 500)
            data.update(custom_data)

        if code == 406 and self.default_mediatype is None:
            # if we are handling NotAcceptable (406), make sure that
            # make_response uses a representation we support as the
            # default mediatype (so that make_response doesn't throw
            # another NotAcceptable error).
            supported_mediatypes = list(self.representations.keys())
            fallback_mediatype = supported_mediatypes[0] if supported_mediatypes else "text/plain"
            resp = self.make_response(
                data,
                code,
                headers,
                fallback_mediatype = fallback_mediatype
            )
        else:
            resp = self.make_response(data, code, headers)

        if code == 401:
            resp = self.unauthorized(resp)
        return resp