def test_subscription_remove_period(client, session): password = "******" user = UserFactory(active=True, password=password) author = AuthorFactory() sub = SubscriptionFactory(user=user, author=author, active=True) sub.add_period(PERIOD.DAILY) assert sub.has_period(PERIOD.DAILY) assert len(sub.periods) == 1 h = Headers() auth = requests.auth._basic_auth_str(user.email, password) h.add("Authorization", auth) url = "{0}{1}{2}{3}".format( url_for("subscriptions.remove_period"), "?period=Daily", "&subscription_id=", str(sub.id), ) response = client.post(url, headers=h) assert response.status_code == 302 assert len(sub.periods) == 0 assert sub.has_period(PERIOD.DAILY) is False
def test07_access_token_handler(self): with dummy_app.test_request_context('/a_request'): auth = IIIFAuthGoogle(client_secret_file=csf) response = auth.access_token_handler() self.assertEqual( response.status_code, 200 ) self.assertEqual( response.headers['Content-type'], 'application/json' ) j = json.loads(response.get_data()) self.assertEqual( j['error_description'], "No login details received" ) self.assertEqual( j['error'], "client_unauthorized" ) # add callback but no account cookie with dummy_app.test_request_context('/a_request?callback=CB'): auth = IIIFAuthGoogle(client_secret_file=csf) response = auth.access_token_handler() self.assertEqual( response.status_code, 200 ) self.assertEqual( response.headers['Content-type'], 'application/javascript' ) # strip JavaScript wrapper and then check JSON js = response.get_data() self.assertTrue( re.match('CB\(.*\);',js) ) j = json.loads(js.lstrip('CB(').rstrip(');')) self.assertEqual( j['error_description'], "No login details received" ) self.assertEqual( j['error'], "client_unauthorized" ) # add an account cookie h = Headers() h.add('Cookie', 'lol_account=ACCOUNT_TOKEN') with dummy_app.test_request_context('/a_request', headers=h): auth = IIIFAuthGoogle(client_secret_file=csf, cookie_prefix='lol_') response = auth.access_token_handler() self.assertEqual( response.status_code, 200 ) self.assertEqual( response.headers['Content-type'], 'application/json' ) j = json.loads(response.get_data()) self.assertEqual( j['access_token'], "ACCOUNT_TOKEN" ) self.assertEqual( j['token_type'], "Bearer" )
def song(id, ext): song = db.session.query(Song.id, Song.filename, Song.length, Song.mimetype, Song.artist, Song.album, Song.title, Song.track).filter(Song.id == id).first() if song == None or not os.path.exists(song.filename): return abort(404) headers = Headers() headers.add("X-Content-Duration", song.length) headers.add("X-Accel-Buffering", "no") range_header = request.headers.get('Range', None) if range_header is not None: range_header = range_header.split("-") try: range_header = intval(range_header[0]) except: range_header = None if range_header is None or range_header == 0: db.session.add(Download(song, request)) db.session.commit() ext = ext.lower() for extension, mimeset in mimetypes.items(): if song.mimetype in mimeset and extension == ext: return send_file_partial(song.filename, mimetype=song.mimetype, attachment_filename=generate_download_filename(song, ext), headers=headers) if ext not in [ "ogg", "mp3", "flac", "wav", "webm" ]: return abort(404) transcode_options = [ 'avconv', '-loglevel', 'quiet', '-i', song.filename, '-f', ext, '-y', '-fflags', 'nobuffer' ]; if ext == "ogg" or ext == "webm": transcode_options.extend([ '-acodec', 'libvorbis', '-aq', '5' ]) elif ext == "mp3": transcode_options.extend([ '-ab', '160k' ]) transcode_options.append('-') return send_process(transcode_options, mimetype=mimetypes[ext][0], attachment_filename=generate_download_filename(song, ext), headers=headers)
def iter_request_header_errors(self, request_headers): """ Validates individual request headers against the schema, yielding a :class:`~spectastic.errors.FieldError` for each failure. """ header_schemas = self.header_schemas() if len(header_schemas) == 0: return request_headers = Headers(request_headers) for header, value in request_headers.iteritems(): if header in header_schemas: schema = self.header_schema(header) for error in self.validator.iter_errors(value, schema): yield FieldError(error.message, 'header', header) for name, schema in header_schemas.iteritems(): if schema.get('required') and name.lower() \ not in request_headers: yield FieldError( 'Required header is missing', 'header', schema.get('name') )
def credentials(scope="module"): """ Note that these credentials match those mentioned in test.htpasswd """ h = Headers() h.add("Authorization", "Basic " + base64.b64encode("username:password")) return h
def __init__(self, response = None, status = None, headers = None, mimetype = None, content_type = None, direct_passthrough = False): if isinstance(headers, Headers): self.headers = headers elif not headers: self.headers = Headers() else: self.headers = Headers(headers) if content_type is None: if mimetype is None and 'content-type' not in self.headers: mimetype = self.default_mimetype if mimetype is not None: mimetype = get_content_type(mimetype, self.charset) content_type = mimetype if content_type is not None: self.headers['Content-Type'] = content_type if status is None: status = self.default_status if isinstance(status, (int, long)): self.status_code = status else: self.status = status self.direct_passthrough = direct_passthrough self._on_close = [] if response is None: self.response = [] elif isinstance(response, basestring): self.data = response else: self.response = response
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
def test_200_with_credentials(client, test_user): headers = Headers() headers.set('Authorization', 'Basic ' + base64.b64encode('[email protected]:secret123')) response = client.get('/user', headers=headers) assert response.status_code == 200 assert response.json.get('user') == test_user.id
def handler_b2s_image(self, id=None): """ Handler for `/b2s_image` url for json data. It accepts only Communication Kit Notifications. """ if id is None: raise BadRequest() headers = request.httprequest.headers self._validate_headers(headers) correspondence_obj = request.env['correspondence'].sudo() correspondence = correspondence_obj.search([('uuid', '=', id)]) if not correspondence: raise NotFound() data = correspondence.get_image() headers = Headers() if correspondence.letter_format == 'zip': fname = fields.Date.today() + ' letters.zip' headers.add( 'Content-Disposition', 'attachment', filename=fname) response = Response(data, content_type='application/zip', headers=headers) else: headers.add( 'Content-Disposition', 'attachment', filename=correspondence.file_name) response = Response(data, content_type='application/pdf', headers=headers) return response
def test_200_with_authorization_header(client, access_token, test_user): headers = Headers() headers.set('Authorization', 'Bearer ' + access_token) response = client.get('/user', headers=headers) assert response.status_code == 200 assert response.json.get('user') == test_user.id
def test_401_with_invalid_credentials(client): headers = Headers() headers.set('Authorization', 'Basic ' + base64.b64encode('invalid-username:invalid-password')) response = client.get('/user', headers=headers) assert response.status_code == 401 assert response.json.get('error') == 'invalid_token'
def test_401_with_unsupported_authorization_header(client): headers = Headers() headers.set('Authorization', 'MAC 123456789') response = client.get('/user', headers=headers) assert response.status_code == 401 assert response.json.get('error') == 'invalid_token'
def test_401_with_invalid_token(client): headers = Headers() headers.set('Authorization', 'Bearer invalid-token') response = client.get('/user', headers=headers) assert response.status_code == 401 assert response.json.get('error') == 'invalid_token'
def test_user_rss_url_etag(session, client): entries = EntryFactory.create_batch(5) author1 = AuthorFactory() author1.entries.extend(entries) user = UserFactory(active=True) user.userfeed.private = False sub1 = Subscription(user=user, author=author1) sub1.save() h = Headers() h.add("If-None-Match", None) response1 = client.get(url_for("users.user_feed", user_id=user.id), headers=h) assert response1.status_code == 200 etag = response1.headers.get("ETag") assert response1.data assert ( response1.headers.get("Content-Type") == "application/atom+xml; charset=utf-8" ) h.add("If-None-Match", etag) response2 = client.get(url_for("users.user_feed", user_id=user.id), headers=h) assert response2.status_code == 304 etag2 = response2.headers.get("ETag") assert etag2 == etag assert not response2.data
def test_subscription_remove_period(subhandler, client, session): # users = User.query.all() # pprint(users) password = '******' user = UserFactory(active=True, password=password) author = AuthorFactory() sub = SubscriptionFactory(user=user, author=author, active=True) sub.add_period(PERIOD.DAILY) # with client as c: assert sub.has_period(PERIOD.DAILY) assert len(sub.periods) == 1 h = Headers() auth = requests.auth._basic_auth_str(user.email, password) h.add('Authorization', auth) url = url_for('subscriptions.remove_period') + '?period=Daily' + '&subscription_id=' + str(sub.id) response = client.post(url, headers=h) assert response.status_code == 302 assert len(sub.periods) == 0 assert sub.has_period(PERIOD.DAILY) is False
def test_200_with_authorization_header(client, access_token): headers = Headers() headers.set('Authorization', 'Bearer ' + access_token) response = client.get('/secrets', headers=headers) assert response.status_code == 200 assert isinstance(response.json.get('secrets'), list)
def test_200_with_credentials(client): headers = Headers() headers.set('Authorization', basic_auth_encode('*****@*****.**', 'secret123')) response = client.get('/secrets', headers=headers) assert response.status_code == 200 assert isinstance(response.json.get('secrets'), list)
def test_crossdomain(self): class Foo(flask_restful.Resource): @cors.crossdomain(allow_origin='*') def get(self): return "data" app = Flask(__name__) api = flask_restful.Api(app) api.add_resource(Foo, '/') with app.test_client() as client: h = Headers() origin = "http://foo.bar" h.add('Origin', origin) res = client.get('/', headers=h) headers = res.headers assert_equals(res.status_code, 200) assert_true(headers['Access-Control-Allow-Origin'] in ('*', origin)) assert_equals(headers['Access-Control-Max-Age'], '21600') allow_methods = headers['Access-Control-Allow-Methods'] assert_true('HEAD' in allow_methods) assert_true('OPTIONS' in allow_methods) assert_true('GET' in allow_methods)
def jsonpost(self, *args, **kwargs): """Convenience method for making JSON POST requests.""" kwargs.setdefault('content_type', 'application/json') if 'data' in kwargs: kwargs['data'] = json.dumps(kwargs['data']) headers = Headers() override_headers = kwargs.pop('headers', {}) if override_headers: for k, v in override_headers.items(): headers.add(k, v) if 'useragent' in kwargs: useragent = kwargs.pop('useragent') headers.add('User-Agent', useragent) # Set a quick JSON lookup attribute. if 'method' in kwargs: method = getattr(self.client, kwargs.get('method').lower()) else: method = self.client.post response = method(headers=headers, *args, **kwargs) try: response.json = json.loads(response.data) except: response.json = None return response
def test_admin_page_rejects_bad_username(self): """ Check that incorrect username won't allow access """ h = Headers() auth = 'foo:{0}'.format(Config.PASSWORD).encode('ascii') h.add('Authorization', b'Basic ' + base64.b64encode(auth)) rv = Client.open(self.client, path='/', headers=h) self.assert_401(rv)
def item_ogg(item_id, ogg_q): from subprocess import Popen, PIPE import mimetypes; item = g.lib.get_item(item_id) filename = os.path.split(item.path)[1] filename = os.path.splitext(filename)[0] + '.ogg' headers = Headers() headers.add('Content-Type', 'audio/ogg') headers.add('Content-Disposition', 'attachment', filename=filename) if mimetypes.guess_type(item.path)[0] == 'audio/mpeg': decoded_fp = Popen( ["mpg123", "-q", "-w", "/dev/stdout", item.path], stdout=PIPE) ogg_fp = Popen( ["oggenc", "-q", str(ogg_q), "-Q", "-"], stdin=decoded_fp.stdout, stdout=PIPE); decoded_fp.stdout.close() else: ogg_fp = Popen( ["oggenc", "-q", str(ogg_q),"-Q", "-o", "/dev/stdout", item.path], stdout=PIPE); res = Response( #wrap_file(request.environ, ogg_fp.stdout), ogg_fp.stdout, headers=headers, direct_passthrough=True) res.implicit_sequence_conversion = False return res
def excel_response(spreadsheet, filename=u'export.xls'): """ Prepares an excel spreadsheet for response in Flask :param spreadsheet: the spreadsheet :type spreadsheet:class:`xlwt.Workbook` :param filename: the name of the file when downloaded :type filename: unicode :return: the flask response :rtype:class:`flask.Response` """ response = Response() response.status_code = 200 output = StringIO.StringIO() spreadsheet.save(output) response.data = output.getvalue() mimetype_tuple = mimetypes.guess_type(filename) #HTTP headers for forcing file download response_headers = Headers({ u'Pragma': u"public", # required, u'Expires': u'0', u'Cache-Control': [u'must-revalidate, post-check=0, pre-check=0', u'private'], u'Content-Type': mimetype_tuple[0], u'Content-Disposition': u'attachment; filename=\"%s\";' % filename, u'Content-Transfer-Encoding': u'binary', u'Content-Length': len(response.data) }) if not mimetype_tuple[1] is None: response_headers.update({u'Content-Encoding': mimetype_tuple[1]}) response.headers = response_headers response.set_cookie(u'fileDownload', u'true', path=u'/') return response
def test_resubscribe(self): user_email = '*****@*****.**' user_password = '******' add_admin(user_email, user_password) hub = 'http://push.superfeedr.com' responses.add(responses.POST, hub, body='{"title": "Success"}', status=204, content_type='application/json') less_24 = datetime.utcnow() + relativedelta(hours=10) feed1 = FeedFactory(lease_end=less_24, status=STATUS.SUBSCRIBED, hub=hub) feed1.save() with self.app.test_client() as c: h = Headers() auth = requests.auth._basic_auth_str(user_email, user_password) h.add('Authorization', auth) url = url_for('pubsubhubbub.resubscribe') response = c.post(url, headers=h) self.assertEqual(response.status_code, 200)
def test_200_with_credentials(client): headers = Headers() headers.set("Authorization", basic_auth_encode("*****@*****.**", "secret123")) response = client.get("/secrets", headers=headers) assert response.status_code == 200 assert isinstance(response.json.get("secrets"), list)
def test07_access_token_handler(self): with dummy_app.test_request_context('/a_request'): auth = IIIFAuthBasic() response = auth.access_token_handler() self.assertEqual( response.status_code, 200 ) self.assertEqual( response.headers['Content-type'], 'application/json' ) j = json.loads(response.get_data()) self.assertEqual( j['error_description'], "No login details received" ) self.assertEqual( j['error'], "client_unauthorized" ) # add Authorization header, check we get token h = Headers() h.add('Authorization', 'Basic ' + base64.b64encode('userpass:userpass')) with dummy_app.test_request_context('/a_request', headers=h): auth = IIIFAuthBasic() response = auth.access_token_handler() self.assertEqual( response.status_code, 200 ) self.assertEqual( response.headers['Content-type'], 'application/json' ) j = json.loads(response.get_data()) self.assertEqual( j['access_token'], "secret_token_here" ) #FIXME self.assertEqual( j['token_type'], "Bearer" ) self.assertEqual( j['expires_in'], 3600 ) # add callback but no Authorization header with dummy_app.test_request_context('/a_request?callback=CB'): auth = IIIFAuthBasic() response = auth.access_token_handler() self.assertEqual( response.status_code, 200 ) self.assertEqual( response.headers['Content-type'], 'application/javascript' ) # strip JavaScript wrapper and then check JSON js = response.get_data() self.assertTrue( re.match('CB\(.*\);',js) ) j = json.loads(js.lstrip('CB(').rstrip(');')) self.assertEqual( j['error_description'], "No login details received" ) self.assertEqual( j['error'], "client_unauthorized" )
def test_401_with_invalid_token(client): headers = Headers() headers.set("Authorization", "Bearer invalid-token") response = client.get("/secrets", headers=headers) assert response.status_code == 401 assert response.json.get("error") == "invalid_token"
def test_200_with_authorization_header(client, access_token): headers = Headers() headers.set("Authorization", "Bearer " + access_token) response = client.get("/secrets", headers=headers) assert response.status_code == 200 assert isinstance(response.json.get("secrets"), list)
def fetch(): url = request.form['url'] print url try: h = Headers(request.headers) h.clear() h.add('referer', 'https://www.facebook.com/') r = requests.request( method='GET', url=url, headers=h, timeout=5 ) except ( requests.exceptions.Timeout, requests.exceptions.ConnectTimeout, requests.exceptions.ReadTimeout): return Response(status=504) except ( requests.exceptions.ConnectionError, requests.exceptions.HTTPError, requests.exceptions.TooManyRedirects): return Response(status=502) except ( requests.exceptions.RequestException, Exception) as e: if app.debug: raise e return Response(status=500) mimetype = "text/html" return Response(r.content, mimetype=mimetype)
def test_401_with_unsupported_authorization_header(client): headers = Headers() headers.set("Authorization", "MAC 123456789") response = client.get("/secrets", headers=headers) assert response.status_code == 401 assert response.json.get("error") == "invalid_token"
def test_admin_page_rejects_bad_password(self): """ Check that incorrect password won't allow access """ h = Headers() auth = '{0}:foo'.format(Config.USERNAME).encode('ascii') h.add('Authorization', b'Basic ' + base64.b64encode(auth)) rv = Client.open(self.client, path='/', headers=h) self.assert_401(rv)
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 e 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 and code >= 500: exc_info = sys.exc_info() if exc_info[1] is None: exc_info = None current_app.log_exception(exc_info) 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
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
def get_headers(): return Headers([('X-Real-Ip', '172.20.0.1'), ('Host', 'up-distributey'), ('Connection', 'close'), ('User-Agent', 'curl/7.68.0'), ('Accept', '*/*'), ('Authorization', f'Bearer {get_jwt()}')])
def handler(request): headers = Headers() headers.add('Content-Type', 'application/json') return Response(response=json.dumps({"data": "Hello World!"}), headers=headers)
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)
class Request(object): """ A Request object. This should not be manually created. Instead, it is automatically provided by Kyokai. If you must create one, use :meth:`from_data` or :meth:`parse`. :ivar method: The HTTP method (GET, POST, PUT, etc) :ivar path: The full path of the request (``/api/v1/whatever``) :ivar headers: A :class:`IOrderedDict` representing the headers of the request. :ivar query: The raw query string (``a=b&c=d``) :ivar body: The raw body of the request. :ivar cookies: A :class:`cookies.SimpleCookie` containing the cookies of the request. :ivar args: The arguments from the query string, parsed out. :ivar form: The form data for the request. If the request was JSON, this is automatically parsed out. :ivar values: THe arguments and the form combined. :ivar source: The source IP of the request. """ def __init__(self): """ Creates a new request. The request is probably useless right now, but the HTTP parser will then go on to set the right attributes on it. """ # Empty values. self.method = "" # This differs from path/query because it's the full `/a/b/?c=d`. # This is then urlsplit into a path and query string in _parse_path. self.full_path = b"" self.path = "" self.query = "" self.version = "" # Empty body, as this isn't known until it's passed in. self.body = "" self.cookies = cookies.SimpleCookie() # We use a Headers object here as it serves our purposes the best. self.headers = Headers() # Args, values, and forms are OrderedMultiDicts. # So are files. self.args = OrderedMultiDict() self._form = OrderedMultiDict() self.values = OrderedMultiDict() self.files = OrderedMultiDict() # Protocol-specific data. self.ip = "" self.port = 0 # Extra values, for hooks. self.extra = {} self.should_keep_alive = False @property def form(self) -> dict: """ Returns the form data for the specified request. JSON forms are lazy loaded. This means that parsing is done in the first call to `.form`, rather than when the request is created. """ if self._form: return self._form # Parse JSON, otherwise. if self.headers.get("Content-Type") == "application/json": self._form = json.loads(self.body) self.values.update(self._form if self._form else {}) return self._form def _parse_path(self): """ urlsplits the full path. """ split = uparse.urlsplit(self.full_path.decode()) self.path = split.path self.query = split.query def _parse_query(self): """ Parses the query string, and updates `args` with it as appropriate. """ new_args = uparse.parse_qs(self.query) # Unpack the urlparsed arguments. for name, value in new_args.items(): if len(value) == 1: self.args[name] = value[0] elif len(value) == 0: self.args[name] = None else: self.args[name] = value def _parse_body(self): """ Parses the body data. """ if self.headers.get("Content-Type") != "application/json": # Parse the form data out. f_parser = formparser.FormDataParser() # Wrap the body in a BytesIO. body = BytesIO(self.body.encode()) # The headers can't be directly passed into Werkzeug. # Instead, we have to get a the custom content type, then pass in some fake WSGI options. mimetype, c_t_args = parse_options_header( self.headers.get("Content-Type")) if mimetype: # We have a valid mimetype. # This is good! # Now parse the body. # Construct a fake WSGI environment. env = { "Content-Type": self.headers.get("Content-Type"), "Content-Length": self.headers.get("Content-Length") } # Take the boundary out of the Content-Type, if applicable. boundary = c_t_args.get("boundary") if boundary is not None: env["boundary"] = boundary # Get a good content length. content_length = self.headers.get("Content-Length") try: content_length = int(content_length) except ValueError: content_length = len(self.body) except TypeError: # NoneType... raise HTTPException(411) # Then, the form body itself is parsed. data = f_parser.parse(body, mimetype, content_length, options=env) # Extract the new data from the form parser. self._form.update(data[1]) self.files.update(data[2]) def parse_all(self): """ Called when all data is parsed. This tells the request to re-parse everything based off of the raw data. This is an internal method. .. versionadded:: 1.9 """ # Call _parse_path to parse the path. self._parse_path() # Call _parse_query to parse the query string. self._parse_query() # Call _parse_body to parse the body. self._parse_body() # Load cookies. cookie_header = self.headers.get_all("Cookie") for c in cookie_header: self.cookies.load(c)
def report_download(self, data, token): requestcontent = json.loads(data) url, type = requestcontent[0], requestcontent[1] try: if type == 'qweb-pdf': reportname = url.split('/report/pdf/')[1].split('?')[0] docids = None if '/' in reportname: reportname, docids = reportname.split('/') if docids: # Generic report: response = self.report_routes(reportname, docids=docids, converter='pdf') else: # Particular report: data = url_decode(url.split( '?')[1]) # decoding the args represented in JSON response = self.report_routes(reportname, converter='pdf', **dict(data)) temp_dict = {} temp_dict.update(json.loads(dict(data).pop('options'))) if 'skit_report_type' in temp_dict.keys( ) and temp_dict['skit_report_type'] == 'XLS': report = request.env[ 'ir.actions.report']._get_report_from_name( reportname) filename = "%s.%s" % (report.name, "xls") # Customize the report name must be what we want # from print xls report ,pass the report_name and customize it. # code added for skit.event.report module execute same model for all event report if 'report_name' in temp_dict.keys( ) and temp_dict['skit_report_type'] == 'XLS': filename = "%s.%s" % (temp_dict['report_name'], "xls") response.headers.add('Content-Disposition', content_disposition(filename)) response.set_cookie('fileToken', token) return response report = request.env[ 'ir.actions.report']._get_report_from_name(reportname) filename = "%s.%s" % (report.name, "pdf") response.headers.add('Content-Disposition', content_disposition(filename)) response.set_cookie('fileToken', token) return response elif type == 'controller': reqheaders = Headers(request.httprequest.headers) response = Client(request.httprequest.app, BaseResponse).get(url, headers=reqheaders, follow_redirects=True) response.set_cookie('fileToken', token) return response else: return except Exception as e: se = _serialize_exception(e) error = {'code': 200, 'message': "Odoo Server Error", 'data': se} return request.make_response(html_escape(json.dumps(error)))
def add_cors_headers(status, headers, exc_info=None): headers = Headers(headers) headers.add("Access-Control-Allow-Origin", self.origin) headers.add("Access-Control-Allow-Headers", "CsrfCheck") headers.add("Access-Control-Allow-Credentials", "true") headers.add("Access-Control-Allow-Methods", "GET, POST") headers.add("Access-Control-Expose-Headers", "...") return start_response(status, headers, exc_info)
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
def i_have_the_url_to_the_contact_page(step): world.contact_url = '/contact' referrer = ('Referer', 'some/url') world.header = Headers([referrer])
def report_download(self, data, token): """This function is used by 'qwebactionmanager.js' in order to trigger the download of a pdf/controller report. :param data: a javascript array JSON.stringified containg report internal url ([0]) and type [1] :returns: Response with a filetoken cookie and an attachment header """ requestcontent = json.loads(data) url, type = requestcontent[0], requestcontent[1] try: if type == 'qweb-pdf': reportname = url.split('/report/pdf/')[1].split('?')[0] docids = None if '/' in reportname: reportname, docids = reportname.split('/') if docids: # Generic report: response = self.report_routes(reportname, docids=docids, converter='pdf') else: # Particular report: data = url_decode( url.split('?') [1]).items() # decoding the args represented in JSON response = self.report_routes(reportname, converter='pdf', **dict(data)) report = request.env['report']._get_report_from_name( reportname) filename = "%s.%s" % (report.name, "pdf") if docids: ids = [int(x) for x in docids.split(",")] obj = request.env[report.model].browse(ids) if report.print_report_name and not len(obj) > 1: filename = safe_eval(report.print_report_name, { 'object': obj, 'time': time }) response.headers.add('Content-Disposition', content_disposition(filename)) response.set_cookie('fileToken', token) return response elif type == 'controller': reqheaders = Headers(request.httprequest.headers) response = Client(request.httprequest.app, BaseResponse).get(url, headers=reqheaders, follow_redirects=True) response.set_cookie('fileToken', token) return response else: return except Exception, e: se = _serialize_exception(e) error = {'code': 200, 'message': u'系统错误', 'data': se} return request.make_response(html_escape(json.dumps(error)))
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
def write_medium_index_excel(Q, now_year, Q_monthes, location_id, douban_data, youli_data, wuxian_data, zhihu_data, weipiao_data, one_data, xueqiu_data, huxiu_data, ledongli_data, kecheng_data, xiecheng_data, momo_data, lama_data, nice_data, meijie_data, other_data, total_money, total_medium_money2, total_now_Q_money_check, total_first_month_money, total_second_month_money, total_third_month_money, total_now_Q_money_zhixing): response = Response() response.status_code = 200 output = StringIO.StringIO() workbook = xlsxwriter.Workbook(output) worksheet = workbook.add_worksheet() align_center = workbook.add_format({ 'align': 'center', 'valign': 'vcenter', 'border': 1 }) title = [ u'投放媒体', u'状态', u'合同号', u'代理名称', u'项目名称', u'行业', u'直客销售', u'渠道销售', u'合同金额', u'媒体金额', u'本季度确认额', u'本季度执行额', u'上季度执行额', u'下季度执行额' ] title += [str(k) + u'月执行额' for k in Q_monthes] title += [u'80%预估', u'50%以上预估', u'50%以下预估', u'类型', u'执行', u'开始时间', u'结束时间'] for k in range(len(title)): worksheet.write(0, 0 + k, title[k], align_center) # 设置宽度 for k in range(33): worksheet.set_column(k, 0, 20) # 根据媒体展示详情 th = 1 th = new_insert_order_table(worksheet, align_center, douban_data, th, u'豆瓣') th = new_insert_order_table(worksheet, align_center, youli_data, th, u'优力互动') th = new_insert_order_table(worksheet, align_center, wuxian_data, th, u'无线互联') th = new_insert_order_table(worksheet, align_center, zhihu_data, th, u'知乎') th = new_insert_order_table(worksheet, align_center, weipiao_data, th, u'微票儿') th = new_insert_order_table(worksheet, align_center, one_data, th, u'ONE') th = new_insert_order_table(worksheet, align_center, xueqiu_data, th, u'雪球') th = new_insert_order_table(worksheet, align_center, huxiu_data, th, u'虎嗅') th = new_insert_order_table(worksheet, align_center, ledongli_data, th, u'乐动力') th = new_insert_order_table(worksheet, align_center, kecheng_data, th, u'课程格子') th = new_insert_order_table(worksheet, align_center, xiecheng_data, th, u'携程') th = new_insert_order_table(worksheet, align_center, momo_data, th, u'陌陌') th = new_insert_order_table(worksheet, align_center, lama_data, th, u'辣妈帮') th = new_insert_order_table(worksheet, align_center, nice_data, th, u'nice') th = new_insert_order_table(worksheet, align_center, other_data, th, u'其他媒体') th = new_insert_order_table(worksheet, align_center, meijie_data, th, u'媒介下单') # 展示总计信息 total_title = [u"投放媒体", u'合同金额', u"媒体金额", u"本季度确认额", u"本季度执行额"] total_title += [str(k) + u'月执行额' for k in Q_monthes] for k in range(len(total_title)): worksheet.write(0, 25 + k, total_title[k], align_center) th = 1 th = new_insert_total_table(worksheet, align_center, douban_data, th, u'豆瓣') th = new_insert_total_table(worksheet, align_center, youli_data, th, u'优力互动') th = new_insert_total_table(worksheet, align_center, wuxian_data, th, u'无线互联') th = new_insert_total_table(worksheet, align_center, zhihu_data, th, u'知乎') th = new_insert_total_table(worksheet, align_center, weipiao_data, th, u'微票儿') th = new_insert_total_table(worksheet, align_center, one_data, th, u'ONE') th = new_insert_total_table(worksheet, align_center, xueqiu_data, th, u'雪球') th = new_insert_total_table(worksheet, align_center, huxiu_data, th, u'虎嗅') th = new_insert_total_table(worksheet, align_center, ledongli_data, th, u'乐动力') th = new_insert_total_table(worksheet, align_center, kecheng_data, th, u'课程格子') th = new_insert_total_table(worksheet, align_center, xiecheng_data, th, u'携程') th = new_insert_total_table(worksheet, align_center, momo_data, th, u'陌陌') th = new_insert_total_table(worksheet, align_center, lama_data, th, u'辣妈帮') th = new_insert_total_table(worksheet, align_center, nice_data, th, u'nice') th = new_insert_total_table(worksheet, align_center, other_data, th, u'其他媒体') # 合计展示 worksheet.write(th, 25, u'总计', align_center) worksheet.write(th, 26, total_money, align_center) worksheet.write(th, 27, total_medium_money2, align_center) worksheet.write(th, 28, total_now_Q_money_check, align_center) worksheet.write(th, 29, total_now_Q_money_zhixing, align_center) worksheet.write(th, 30, total_first_month_money, align_center) worksheet.write(th, 31, total_second_month_money, align_center) worksheet.write(th, 32, total_third_month_money, align_center) th += 1 th = new_insert_total_table(worksheet, align_center, meijie_data, th, u'其中媒介下单') workbook.close() response.data = output.getvalue() filename = ("%s-%s-%s-%s.xls" % (u"MediumWeekly", str(now_year), str(Q), TEAM_LOCATION_CN[location_id])) mimetype_tuple = mimetypes.guess_type(filename) response_headers = Headers({ 'Pragma': "public", 'Expires': '0', 'Cache-Control': 'must-revalidate, post-check=0, pre-check=0', 'Cache-Control': 'private', 'Content-Type': mimetype_tuple[0], 'Content-Disposition': 'attachment; filename=\"%s\";' % filename, 'Content-Transfer-Encoding': 'binary', 'Content-Length': len(response.data) }) response.headers = response_headers response.set_cookie('fileDownload', 'true', path='/') return response
def collect_task_headers(): """Get headers required for appengine background task run.""" headers = {} if hasattr(request, "headers"): headers = {k: v for k, v in request.headers if k not in BANNED_HEADERS} return Headers(headers)
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 without checking them first. Something like this is usually sufficient to avoid security problems:: if '..' in filename or filename.startswith('/'): abort(404) .. 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 # 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: 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)) 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
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'): 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 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)
output = StringIO.StringIO() workbook.save(output) response.data = output.getvalue() mimetype_tuple = mimetypes.guess_type(filename) #HTTP headers for forcing file download response_headers = Headers({ 'Pragma': "public", 'Expires': '0', 'Cache-Control': 'must-revalidate, post-check=0, pre-check=0', 'Cache-Control': 'private', 'Content-Type': mimetype_tuple[0] or 'application/vnd.ms-excel', '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
def write_client_excel(huabei_agent_salers_orders, huabei_direct_salers_orders, huanan_agent_salers_orders, huanan_direct_salers_orders, huadong_agent_salers_orders, huadong_direct_salers_orders, now_year, Q, Q_monthes, otype='client'): if otype == 'douban': filename = ("%s-%s.xls" % (u"DoubanWeekly", datetime.datetime.now().strftime('%Y%m%d%H%M%S'))) else: filename = ( "%s-%s.xls" % (u"InadWeekly", datetime.datetime.now().strftime('%Y%m%d%H%M%S'))) response = Response() response.status_code = 200 output = StringIO.StringIO() workbook = xlsxwriter.Workbook(output) worksheet = workbook.add_worksheet() Q_format = workbook.add_format({ 'align': 'left', 'valign': 'vcenter', 'fg_color': '#D7E4BC', 'border': 1 }) worksheet.merge_range(0, 0, 1, 8, Q, Q_format) # 画出华北区渠道销售 worksheet, th = _insert_excel(workbook, worksheet, huabei_agent_salers_orders, 'agent', u'华北区', now_year, Q, Q_monthes, otype, th=2) # 画出华北区直客销售 worksheet, th = _insert_excel(workbook, worksheet, huabei_direct_salers_orders, 'direct', u'华北区', now_year, Q, Q_monthes, otype, th) huabei_orders = huabei_agent_salers_orders + huabei_direct_salers_orders # 画出华北区综合 worksheet, th = _insert_excel_location_total(workbook, worksheet, huabei_orders, otype, th) # 画出华南区渠道销售 worksheet, th = _insert_excel(workbook, worksheet, huanan_agent_salers_orders, 'agent', u'华南区', now_year, Q, Q_monthes, otype, th) # 画出华南区直客销售 worksheet, th = _insert_excel(workbook, worksheet, huanan_direct_salers_orders, 'direct', u'华南区', now_year, Q, Q_monthes, otype, th) huanan_orders = huanan_agent_salers_orders + huanan_direct_salers_orders # 画出华南区综合 worksheet, th = _insert_excel_location_total(workbook, worksheet, huanan_orders, otype, th) # 画出华东区渠道销售 worksheet, th = _insert_excel(workbook, worksheet, huadong_agent_salers_orders, 'agent', u'华东区', now_year, Q, Q_monthes, otype, th) # 画出华南区直客销售 worksheet, th = _insert_excel(workbook, worksheet, huadong_direct_salers_orders, 'direct', u'华东区', now_year, Q, Q_monthes, otype, th) huadong_orders = huadong_agent_salers_orders + huadong_direct_salers_orders # 画出华南区综合 worksheet, th = _insert_excel_location_total(workbook, worksheet, huadong_orders, otype, th) # 画出所有合同总和 total_orders = huabei_orders + huanan_orders + huadong_orders worksheet, th = _insert_excel_total(workbook, worksheet, total_orders, th, Q_monthes, otype) workbook.close() response.data = output.getvalue() mimetype_tuple = mimetypes.guess_type(filename) response_headers = Headers({ 'Pragma': "public", 'Expires': '0', 'Cache-Control': 'must-revalidate, post-check=0, pre-check=0', 'Cache-Control': 'private', 'Content-Type': mimetype_tuple[0], 'Content-Disposition': 'attachment; filename=\"%s\";' % filename, 'Content-Transfer-Encoding': 'binary', 'Content-Length': len(response.data) }) response.headers = response_headers response.set_cookie('fileDownload', 'true', path='/') return response
def get(self, scope_name): """ Metalink redirect .. :quickref: MetaLinkRedirector; Metalink redirect. :param scope_name: data identifier (scope)/(name). :resheader Content-Type: application/metalink4+xml'. :status 200: OK. :status 401: Invalid Auth Token. :status 404: RSE Not Found. :status 404: DID Not Found. :status 406: Not Acceptable. :status 500: Internal Error. :returns: Metalink file """ headers = Headers() headers.set('Access-Control-Allow-Origin', request.environ.get('HTTP_ORIGIN')) headers.set('Access-Control-Allow-Headers', request.environ.get('HTTP_ACCESS_CONTROL_REQUEST_HEADERS')) headers.set('Access-Control-Allow-Methods', '*') headers.set('Access-Control-Allow-Credentials', 'true') try: scope, name = parse_scope_name( scope_name, request.headers.get('X-Rucio-VO', default='def')) except ValueError as error: return generate_http_error_flask(400, 'ValueError', error.args[0], headers=headers) except Exception as error: print(format_exc()) return str(error), 500, headers dids, schemes, select = [{ 'scope': scope, 'name': name }], ['http', 'https', 'root', 'gsiftp', 'srm', 'davs'], None # set the correct client IP client_ip = request.headers.get('X-Forwarded-For', default=request.remote_addr) client_location = {'ip': client_ip, 'fqdn': None, 'site': None} if request.query_string: query_string = request.query_string.decode(encoding='utf-8') params = parse_qs(query_string) if 'schemes' in params: schemes = params['schemes'] if 'select' in params: select = params['select'][0] if 'sort' in params: select = params['sort'][0] if 'ip' in params: client_location['ip'] = params['ip'][0] if 'fqdn' in params: client_location['fqdn'] = params['fqdn'][0] if 'site' in params: client_location['site'] = params['site'][0] # get vo if given vo = request.headers.get('X-Rucio-VO', default='def') try: replicas_iter = list_replicas(dids=dids, schemes=schemes, client_location=client_location, vo=vo) try: first = next(replicas_iter) except StopIteration: return 'no redirection possible - cannot find the DID', 404 def generate(): # first, set the appropriate content type, and stream the header yield '<?xml version="1.0" encoding="UTF-8"?>\n<metalink xmlns="urn:ietf:params:xml:ns:metalink">\n' # iteratively stream the XML per file for rfile in itertools.chain((first, ), replicas_iter): replicas = [] dictreplica = {} for rse in rfile['rses']: for replica in rfile['rses'][rse]: replicas.append(replica) dictreplica[replica] = rse # stream metadata yield ' <file name="' + rfile['name'] + '">\n' yield ' <identity>' + rfile['scope'] + ':' + rfile[ 'name'] + '</identity>\n' if rfile['adler32'] is not None: yield ' <hash type="adler32">' + rfile[ 'adler32'] + '</hash>\n' if rfile['md5'] is not None: yield ' <hash type="md5">' + rfile['md5'] + '</hash>\n' yield ' <size>' + str(rfile['bytes']) + '</size>\n' yield ' <glfn name="/atlas/rucio/%s:%s">' % ( rfile['scope'], rfile['name']) yield '</glfn>\n' # sort the actual replicas if necessary if select == 'geoip': replicas = sort_geoip(dictreplica, client_location['ip'], ignore_error=True) elif select == 'closeness': replicas = sort_closeness(dictreplica, client_location) elif select == 'dynamic': replicas = sort_dynamic(dictreplica, client_location) elif select == 'ranking': replicas = sort_ranking(dictreplica, client_location) else: replicas = sort_random(dictreplica) # stream URLs idx = 1 for replica in replicas: yield ' <url location="' + str( dictreplica[replica]) + '" priority="' + str( idx) + '">' + replica + '</url>\n' idx += 1 yield ' </file>\n' # don't forget to send the metalink footer yield '</metalink>\n' return try_stream(generate(), content_type='application/metalink4+xml') except DataIdentifierNotFound as error: return generate_http_error_flask(404, 'DataIdentifierNotFound', error.args[0], headers=headers) except ReplicaNotFound as error: return generate_http_error_flask(404, 'ReplicaNotFound', error.args[0], headers=headers) except RucioException as error: return generate_http_error_flask(500, error.__class__.__name__, error.args[0], headers=headers) except Exception as error: print(format_exc()) return str(error), 500, headers
def web(chatbotname, messenger): platform = messenger # Messenger web - facebook - telegram - kik if request.method == 'GET' and messenger != 'facebook': abort(404) config = app.config["CHATBOTS"] if chatbotname not in config: abort(404) # Facebook Challenge if request.method == 'GET' and messenger == 'facebook': hub_mode = request.args.get('hub.mode', '') hub_verify_token = request.args.get('hub.verify_token', '') hub_challenge = request.args.get('hub.challenge', '') if hub_mode == 'subscribe' and hub_verify_token == config[chatbotname][ "facebook"]["HUB_VERIFY_TOKEN"]: return hub_challenge else: abort(403) # wat = watson(config[chatbotname]["watson"]["username"], config[chatbotname]["watson"]["password"], config[chatbotname]["watson"]["workspace_id"]) if messenger == 'web': if request.form.get("question") == '': m = None else: m = request.form.get("question") chat_id = request.form.get("chat_id") messages = [] watson_responses = get_watson_response(wat, platform, chatbotname, chat_id, m) for watson_response in watson_responses: messages = messages + watson_response["output"]["text"] for k in range(0, len(messages)): messages[k] = get_external_data(messages[k]) message = {"message": messages} json_response = json.dumps(message) h = Headers() h.add("Access-Control-Allow-Origin", "*") return Response(json_response, mimetype='application/json', headers=h) elif messenger == 'facebook': if request.method == 'POST': msg = request.json with open("log/Output.txt", "a") as text_file: text_file.write("\n\n") text_file.write(str(msg)) if msg['object'] == 'page': for entries in msg['entry']: for message in entries['messaging']: needs_answer = False if "message" in message: senderId = message['sender']['id'] if "text" in message["message"]: m = message["message"]["text"] needs_answer = True elif "sticker_id" in message["message"]: m = "sticker_id {}".format( message["message"]["sticker_id"]) needs_answer = True elif "read" in message: senderId = message['sender']['id'] m = "[read]" #needs_answer = True elif "postback" in message: if message["postback"].get( "payload") == "Get Started": senderId = message['sender']['id'] m = None needs_answer = True if needs_answer: if m == '/start': m = None if m == '/configure': facebookConfigureBot(chatbotname) watson_responses = get_watson_response( wat, platform, chatbotname, senderId, m) recipientId = senderId for watson_response in watson_responses: for watson_message in watson_response[ "output"]["text"]: img_url = extract_image(watson_message) voice_url = extract_voice(watson_message) audio_url = extract_audio(watson_message) if img_url: facebookSendFile( recipientId, img_url, 'image', chatbotname) elif voice_url: facebookSendFile( recipientId, voice_url, 'voice', chatbotname) elif audio_url: facebookSendFile( recipientId, audio_url, 'audio', chatbotname) else: watson_message = get_external_data( watson_message) facebookSendTextMessage( recipientId, markdown_facebook(watson_message), chatbotname) return jsonify({}) elif messenger == 'telegram': msg = request.json with open("log/OutputTelegram.txt", "a") as text_file: text_file.write("\n\n") text_file.write(str(msg)) if "message" not in msg: return jsonify({}) if "text" not in msg["message"] and "voice" not in msg["message"]: return jsonify({}) answer = { 'method': "sendMessage", 'chat_id': msg["message"]["chat"]["id"], 'text': "*Hi there!*", 'parse_mode': 'Markdown', 'disable_web_page_preview': True } if "voice" in msg["message"]: file_id = msg["message"]["voice"]["file_id"] mime_type = msg["message"]["voice"]["mime_type"] duration = msg["message"]["voice"]["duration"] if duration > 15: answer["text"] = "Audio muy largo. Duración máxima 15 segundos" return jsonify(answer) fileData = {"file_id": file_id} fileJson = telegramCallSendAPI('getFile', chatbotname, data=fileData) try: fileJson = fileJson.json() except: return jsonify({}) with open("log/OutputTelegram.txt", "a") as text_file: text_file.write("\n\n") text_file.write(str(fileJson)) if "result" in fileJson and "file_path" in fileJson["result"]: file_path = fileJson["result"]["file_path"] answer["text"] = file_path token = app.config["CHATBOTS"][chatbotname]["telegram"][ "token"] url = "https://api.telegram.org/file/bot{}/{}".format( token, file_path) #r = requests.get(url) local_filename = "voice/{}".format(file_id) r = requests.get(url, stream=True) with open(local_filename, 'wb') as f: for chunk in r.iter_content(chunk_size=1024): if chunk: # filter out keep-alive new chunks f.write(chunk) #f.flush() commented by recommendation from J.F.Sebastian username = app.config["CHATBOTS"][chatbotname]["watson-stt"][ "username"] password = app.config["CHATBOTS"][chatbotname]["watson-stt"][ "password"] api_url = "https://stream.watsonplatform.net/speech-to-text/api" if 'VCAP_SERVICES' in os.environ: vcap = json.loads(os.getenv('VCAP_SERVICES')) print('Found VCAP_SERVICES') if 'speech_to_text' in vcap: creds = vcap['speech_to_text'][0]['credentials'] username = creds['username'] password = creds['password'] api_url = creds['url'] headers = { 'Content-Type': mime_type, #'Transfer-Encoding': 'chunked' } url = "{}/v1/recognize?model=es-ES_BroadbandModel".format( api_url) files = {'upload_file': open(local_filename, 'rb')} r = requests.post(url, headers=headers, files=files, auth=(username, password)) try: sttJson = r.json() except: return jsonify({}) with open("log/OutputTelegram.txt", "a") as text_file: text_file.write("\n\n") text_file.write(str(sttJson)) if "results" not in sttJson: answer["text"] = str(sttJson) return jsonify(answer) if len(sttJson["results"]) == 0: answer["text"] = "Error procesando audio" return jsonify(answer) transcript = sttJson["results"][0]["alternatives"][0][ "transcript"] msg["message"]["text"] = transcript # return jsonify(answer) # return jsonify({}) if msg["message"]["text"] == '/start': msg["message"]["text"] = None chat_id = msg["message"]["chat"]["id"] watson_responses = get_watson_response(wat, platform, chatbotname, chat_id, msg["message"]["text"]) messages = [] for watson_response in watson_responses: messages = messages + watson_response["output"]["text"] for message in messages: img_url = extract_image(message) voice_url = extract_voice(message) audio_url = extract_audio(message) if img_url: if img_url.endswith("giphy.gif"): telegramSendFile(chat_id, img_url, "video", chatbotname) else: telegramSendFile(chat_id, img_url, "image", chatbotname) elif voice_url: telegramSendFile(chat_id, voice_url, "voice", chatbotname) elif audio_url: telegramSendFile(chat_id, audio_url, "audio", chatbotname) else: message = get_external_data(message) telegramSendTextMessage(chat_id, markdown_telegram(message), chatbotname) # answer["text"] = markdown_telegram("\n\n".join(messages)) # return jsonify(answer) return jsonify({})
def fixing_start_response(status, headers, exc_info=None): self.fix_headers(environ, Headers.linked(headers), status) return start_response(status, headers, exc_info)
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) 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 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
def variants(institute_id, case_name): """Display a list of SNV variants.""" page = int(request.form.get('page', 1)) institute_obj, case_obj = institute_and_case(store, institute_id, case_name) variant_type = request.args.get('variant_type', 'clinical') # Update filter settings if Clinical Filter was requested default_panels = [] for panel in case_obj['panels']: if panel.get('is_default'): default_panels.append(panel['panel_name']) request.form.get('gene_panels') if bool(request.form.get('clinical_filter')): clinical_filter = MultiDict({ 'variant_type': 'clinical', 'region_annotations': ['exonic','splicing'], 'functional_annotations': SEVERE_SO_TERMS, 'clinsig': [4,5], 'clinsig_confident_always_returned': True, 'gnomad_frequency': str(institute_obj['frequency_cutoff']), 'variant_type': 'clinical', 'gene_panels': default_panels }) if(request.method == "POST"): if bool(request.form.get('clinical_filter')): form = FiltersForm(clinical_filter) form.csrf_token = request.args.get('csrf_token') else: form = FiltersForm(request.form) else: form = FiltersForm(request.args) # populate available panel choices available_panels = case_obj.get('panels', []) + [ {'panel_name': 'hpo', 'display_name': 'HPO'}] panel_choices = [(panel['panel_name'], panel['display_name']) for panel in available_panels] form.gene_panels.choices = panel_choices # upload gene panel if symbol file exists if (request.files): file = request.files[form.symbol_file.name] if request.files and file and file.filename != '': log.debug("Upload file request files: {0}".format(request.files.to_dict())) try: stream = io.StringIO(file.stream.read().decode('utf-8'), newline=None) except UnicodeDecodeError as error: flash("Only text files are supported!", 'warning') return redirect(request.referrer) hgnc_symbols_set = set(form.hgnc_symbols.data) log.debug("Symbols prior to upload: {0}".format(hgnc_symbols_set)) new_hgnc_symbols = controllers.upload_panel(store, institute_id, case_name, stream) hgnc_symbols_set.update(new_hgnc_symbols) form.hgnc_symbols.data = hgnc_symbols_set # reset gene panels form.gene_panels.data = '' # update status of case if vistited for the first time if case_obj['status'] == 'inactive' and not current_user.is_admin: flash('You just activated this case!', 'info') user_obj = store.user(current_user.email) case_link = url_for('cases.case', institute_id=institute_obj['_id'], case_name=case_obj['display_name']) store.update_status(institute_obj, case_obj, user_obj, 'active', case_link) # check if supplied gene symbols exist hgnc_symbols = [] non_clinical_symbols = [] not_found_symbols = [] not_found_ids = [] if (form.hgnc_symbols.data) and len(form.hgnc_symbols.data) > 0: is_clinical = form.data.get('variant_type', 'clinical') == 'clinical' clinical_symbols = store.clinical_symbols(case_obj) if is_clinical else None for hgnc_symbol in form.hgnc_symbols.data: if hgnc_symbol.isdigit(): hgnc_gene = store.hgnc_gene(int(hgnc_symbol)) if hgnc_gene is None: not_found_ids.append(hgnc_symbol) else: hgnc_symbols.append(hgnc_gene['hgnc_symbol']) elif sum(1 for i in store.hgnc_genes(hgnc_symbol)) == 0: not_found_symbols.append(hgnc_symbol) elif is_clinical and (hgnc_symbol not in clinical_symbols): non_clinical_symbols.append(hgnc_symbol) else: hgnc_symbols.append(hgnc_symbol) if (not_found_ids): flash("HGNC id not found: {}".format(", ".join(not_found_ids)), 'warning') if (not_found_symbols): flash("HGNC symbol not found: {}".format(", ".join(not_found_symbols)), 'warning') if (non_clinical_symbols): flash("Gene not included in clinical list: {}".format(", ".join(non_clinical_symbols)), 'warning') form.hgnc_symbols.data = hgnc_symbols # handle HPO gene list separately if 'hpo' in form.data['gene_panels']: hpo_symbols = list(set(term_obj['hgnc_symbol'] for term_obj in case_obj['dynamic_gene_list'])) current_symbols = set(hgnc_symbols) current_symbols.update(hpo_symbols) form.hgnc_symbols.data = list(current_symbols) variants_query = store.variants(case_obj['_id'], query=form.data) data = {} if request.form.get('export'): document_header = controllers.variants_export_header(case_obj) export_lines = [] if form.data['chrom'] == 'MT': # Return all MT variants export_lines = controllers.variant_export_lines(store, case_obj, variants_query) else: # Return max 500 variants export_lines = controllers.variant_export_lines(store, case_obj, variants_query.limit(500)) def generate(header, lines): yield header + '\n' for line in lines: yield line + '\n' headers = Headers() headers.add('Content-Disposition','attachment', filename=str(case_obj['display_name'])+'-filtered_variants.csv') # return a csv with the exported variants return Response(generate(",".join(document_header), export_lines), mimetype='text/csv', headers=headers) data = controllers.variants(store, institute_obj, case_obj, variants_query, page) return dict(institute=institute_obj, case=case_obj, form=form, severe_so_terms=SEVERE_SO_TERMS, page=page, **data)
def get(self, scope_name): """ Header Redirect .. :quickref: HeaderRedirector; Header redirect. :param scope_name: data identifier (scope)/(name). :resheader Content-Type: application/metalink+xml'. :status 303: Redirect. :status 401: Invalid Auth Token. :status 404: RSE Not Found. :status 404: DID Not Found. :status 500: Internal Error. """ headers = Headers() headers.set('Access-Control-Allow-Origin', request.environ.get('HTTP_ORIGIN')) headers.set('Access-Control-Allow-Headers', request.environ.get('HTTP_ACCESS_CONTROL_REQUEST_HEADERS')) headers.set('Access-Control-Allow-Methods', '*') headers.set('Access-Control-Allow-Credentials', 'true') try: scope, name = parse_scope_name( scope_name, request.headers.get('X-Rucio-VO', default='def')) except ValueError as error: return generate_http_error_flask(400, 'ValueError', error.args[0], headers=headers) except Exception as error: print(format_exc()) return str(error), 500, headers try: # use the default HTTP protocols if no scheme is given select, rse, site, schemes = 'random', None, None, [ 'davs', 'http', 'https' ] client_ip = request.headers.get('X-Forwarded-For', default=request.remote_addr) client_location = {'ip': client_ip, 'fqdn': None, 'site': None} if request.query_string: query_string = request.query_string.decode(encoding='utf-8') params = parse_qs(query_string) if 'select' in params: select = params['select'][0] if 'sort' in params: select = params['sort'][0] if 'rse' in params: rse = params['rse'][0] if 'site' in params: site = params['site'][0] if 'schemes' in params: schemes = params['schemes'][0] else: schemes = ['davs', 'https', 's3'] if 'ip' in params: client_location['ip'] = params['ip'][0] if 'fqdn' in params: client_location['fqdn'] = params['fqdn'][0] if 'site' in params: client_location['site'] = params['site'][0] # correctly forward the schemes and select to potential metalink followups cleaned_url = request.environ.get('REQUEST_URI').split('?')[0] if isinstance(schemes, list): headers.set( 'Link', '<%s/metalink?schemes=%s&select=%s>; rel=describedby; type="application/metalink+xml"' % (cleaned_url, ','.join(schemes), select)) else: headers.set( 'Link', '<%s/metalink?schemes=%s&select=%s>; rel=describedby; type="application/metalink+xml"' % (cleaned_url, schemes, select)) schemes = [schemes] # list_replicas needs a list # get vo if given vo = request.headers.get('X-Rucio-VO', default='def') replicas = [ r for r in list_replicas(dids=[{ 'scope': scope, 'name': name, 'type': 'FILE' }], schemes=schemes, client_location=client_location, vo=vo) ] selected_url = None for r in replicas: if r['rses']: dictreplica = {} if rse: if rse in r['rses'] and r['rses'][rse]: selected_url = r['rses'][rse][0] else: return 'no redirection possible - no valid RSE for HTTP redirection found', 404, headers else: for rep in r['rses']: for replica in r['rses'][rep]: # since this is HTTP-only redirection, and to ensure compatibility with as many http clients as possible # forcibly replacement davs and s3 URLs to https replica = replica.replace( 'davs://', 'https://').replace('s3://', 'https://') dictreplica[replica] = rep if not dictreplica: return 'no redirection possible - no valid RSE for HTTP redirection found', 404, headers elif site: rep = site_selector(dictreplica, site, vo) if rep: selected_url = rep[0] else: return 'no redirection possible - no valid RSE for HTTP redirection found', 404, headers else: if select == 'geoip': rep = sort_geoip(dictreplica, client_location['ip']) elif select == 'closeness': rep = sort_closeness(dictreplica, client_location) elif select == 'dynamic': rep = sort_dynamic(dictreplica, client_location) elif select == 'ranking': rep = sort_ranking(dictreplica, client_location) else: rep = sort_random(dictreplica) selected_url = rep[0] if selected_url: response = redirect(selected_url, code=303) response.headers.extend(headers) return response return 'no redirection possible - file does not exist', 404, headers except ReplicaNotFound as error: return generate_http_error_flask(404, 'ReplicaNotFound', error.args[0], headers=headers) except RucioException as error: return generate_http_error_flask(500, error.__class__.__name__, error.args[0], headers=headers) except Exception as error: print(format_exc()) return str(error), 500, headers
def _parse_v2_payload_format_lambda_output(lambda_output, binary_types, flask_request): """ Parses the output from the Lambda Container :param str lambda_output: Output from Lambda Invoke :return: Tuple(int, dict, str, bool) """ # pylint: disable-msg=too-many-statements try: json_output = json.loads(lambda_output) except ValueError as ex: raise LambdaResponseParseException( "Lambda response must be valid json") from ex # lambda can return any valid json response in payload format version 2.0. # response can be a simple type like string, or integer # https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html#http-api-develop-integrations-lambda.response if isinstance(json_output, dict): body = json_output.get( "body") if "statusCode" in json_output else json.dumps( json_output) else: body = json_output json_output = {} if body is None: LOG.warning("Lambda returned empty body!") status_code = json_output.get("statusCode") or 200 headers = Headers(json_output.get("headers") or {}) is_base_64_encoded = json_output.get("isBase64Encoded") or False try: status_code = int(status_code) if status_code <= 0: raise ValueError except ValueError as ex: raise LambdaResponseParseException( "statusCode must be a positive int") from ex try: if body: body = str(body) except ValueError as ex: raise LambdaResponseParseException( f"Non null response bodies should be able to convert to string: {body}" ) from ex # API Gateway only accepts statusCode, body, headers, and isBase64Encoded in # a response shape. # Don't check the response keys when inferring a response, see # https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html#http-api-develop-integrations-lambda.v2. invalid_keys = LocalApigwService._invalid_apig_response_keys( json_output) if "statusCode" in json_output and invalid_keys: raise LambdaResponseParseException( f"Invalid API Gateway Response Keys: {invalid_keys} in {json_output}" ) # If the customer doesn't define Content-Type default to application/json if "Content-Type" not in headers: LOG.info( "No Content-Type given. Defaulting to 'application/json'.") headers["Content-Type"] = "application/json" try: if LocalApigwService._should_base64_decode_body( binary_types, flask_request, headers, is_base_64_encoded): body = base64.b64decode(body) except ValueError as ex: LambdaResponseParseException(str(ex)) return status_code, headers, body
def proxy_request(host, file=""): hostname, port = parse_host_port(host) if "proxy" in hostname: abort(403) response = requests.get( "https://proxy-filter.herokuapp.com/is_blacklisted", params={'hostname': hostname}) json_response = response.content.decode() response_dictionary = json.loads(json_response) success = response_dictionary['success'] message = response_dictionary['message'] if success == 0: abort(403) else: # 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 conn = http.client.HTTPConnection(hostname, port) conn.request(request.method, path, body=form_data, headers=request_headers) resp = conn.getresponse() # Clean up response headers for forwarding d = {} response_headers = Headers() for key, value in resp.getheaders(): 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"] response = requests.get(redirect) return response.content # 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. if d["content-type"].find("application/json") >= 0: # JSON format contents 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) flask_response = Response(response=contents, status=resp.status, headers=response_headers, content_type=resp.getheader('content-type')) return flask_response.data
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"): 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: # a request without Accept-Language or "l" argument gets the # default locale page = c.get("/login") assert session.get("locale") == "en_US" assert not_translated == gettext(not_translated) assert b"?l=fr_FR" in page.data assert b"?l=en_US" not in page.data # the session locale should change when the "l" request # argument is present and valid 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 # confirm that the chosen locale, now in the session, is used # despite not matching the client's Accept-Language header c.get("/", headers=Headers([("Accept-Language", "en_US")])) assert session.get("locale") == "fr_FR" assert translated_fr == gettext(not_translated) # the session locale should not change if an empty "l" request # argument is sent c.get("/?l=") assert session.get("locale") == "fr_FR" assert translated_fr == gettext(not_translated) # the session locale should not change if no "l" request # argument is sent c.get("/") assert session.get("locale") == "fr_FR" assert translated_fr == gettext(not_translated) # sending an invalid locale identifier should not change the # session locale c.get("/?l=YY_ZZ") assert session.get("locale") == "fr_FR" assert translated_fr == gettext(not_translated) # requesting a valid locale via the request argument "l" # should change the session locale c.get("/?l=en_US", headers=Headers([("Accept-Language", "fr_FR")])) assert session.get("locale") == "en_US" assert not_translated == gettext(not_translated) # again, the session locale should stick even if not included # in the client's Accept-Language header c.get("/", headers=Headers([("Accept-Language", "fr_FR")])) assert session.get("locale") == "en_US" 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 # Test that A[lang,hreflang] attributes (if present) will validate as # BCP47/RFC5646 language tags from `i18n.RequestLocaleInfo.language_tag`. if 'lang="' in locales: assert 'lang="en-US"' in locales assert 'lang="fr-FR"' in locales if 'hreflang="' in locales: assert 'hreflang="en-US"' in locales assert 'hreflang="fr-FR"' in locales c.get("/?l=ar") base = render_template("base.html") assert 'dir="rtl"' in base
def sv_variants(institute_id, case_name): """Display a list of structural variants.""" page = int(request.form.get('page', 1)) variant_type = request.args.get('variant_type', 'clinical') institute_obj, case_obj = institute_and_case(store, institute_id, case_name) form = SvFiltersForm(request.form) default_panels = [] for panel in case_obj['panels']: if (panel.get('is_default') and panel['is_default'] is True) or ('default_panels' in case_obj and panel['panel_id'] in case_obj['default_panels']): default_panels.append(panel['panel_name']) request.form.get('gene_panels') if bool(request.form.get('clinical_filter')): clinical_filter = MultiDict({ 'variant_type': 'clinical', 'region_annotations': ['exonic','splicing'], 'functional_annotations': SEVERE_SO_TERMS, 'thousand_genomes_frequency': str(institute_obj['frequency_cutoff']), 'variant_type': 'clinical', 'clingen_ngi': 10, 'swegen': 10, 'size': 100, 'gene_panels': default_panels }) if(request.method == "POST"): if bool(request.form.get('clinical_filter')): form = SvFiltersForm(clinical_filter) form.csrf_token = request.args.get('csrf_token') else: form = SvFiltersForm(request.form) else: form = SvFiltersForm(request.args) available_panels = case_obj.get('panels', []) + [ {'panel_name': 'hpo', 'display_name': 'HPO'}] panel_choices = [(panel['panel_name'], panel['display_name']) for panel in available_panels] form.gene_panels.choices = panel_choices # check if supplied gene symbols exist hgnc_symbols = [] non_clinical_symbols = [] not_found_symbols = [] not_found_ids = [] if (form.hgnc_symbols.data) and len(form.hgnc_symbols.data) > 0: is_clinical = form.data.get('variant_type', 'clinical') == 'clinical' clinical_symbols = store.clinical_symbols(case_obj) if is_clinical else None for hgnc_symbol in form.hgnc_symbols.data: if hgnc_symbol.isdigit(): hgnc_gene = store.hgnc_gene(int(hgnc_symbol)) if hgnc_gene is None: not_found_ids.append(hgnc_symbol) else: hgnc_symbols.append(hgnc_gene['hgnc_symbol']) elif sum(1 for i in store.hgnc_genes(hgnc_symbol)) == 0: not_found_symbols.append(hgnc_symbol) elif is_clinical and (hgnc_symbol not in clinical_symbols): non_clinical_symbols.append(hgnc_symbol) else: hgnc_symbols.append(hgnc_symbol) if (not_found_ids): flash("HGNC id not found: {}".format(", ".join(not_found_ids)), 'warning') if (not_found_symbols): flash("HGNC symbol not found: {}".format(", ".join(not_found_symbols)), 'warning') if (non_clinical_symbols): flash("Gene not included in clinical list: {}".format(", ".join(non_clinical_symbols)), 'warning') form.hgnc_symbols.data = hgnc_symbols # handle HPO gene list separately if 'hpo' in form.data['gene_panels']: hpo_symbols = list(set(term_obj['hgnc_symbol'] for term_obj in case_obj['dynamic_gene_list'])) current_symbols = set(hgnc_symbols) current_symbols.update(hpo_symbols) form.hgnc_symbols.data = list(current_symbols) # update status of case if vistited for the first time if case_obj['status'] == 'inactive' and not current_user.is_admin: flash('You just activated this case!', 'info') user_obj = store.user(current_user.email) case_link = url_for('cases.case', institute_id=institute_obj['_id'], case_name=case_obj['display_name']) store.update_status(institute_obj, case_obj, user_obj, 'active', case_link) variants_query = store.variants(case_obj['_id'], category='sv', query=form.data) data = {} # if variants should be exported if request.form.get('export'): document_header = controllers.variants_export_header(case_obj) export_lines = [] # Return max 500 variants export_lines = controllers.variant_export_lines(store, case_obj, variants_query.limit(500)) def generate(header, lines): yield header + '\n' for line in lines: yield line + '\n' headers = Headers() headers.add('Content-Disposition','attachment', filename=str(case_obj['display_name'])+'-filtered_sv-variants.csv') return Response(generate(",".join(document_header), export_lines), mimetype='text/csv', headers=headers) # return a csv with the exported variants else: data = controllers.sv_variants(store, institute_obj, case_obj, variants_query, page) return dict(institute=institute_obj, case=case_obj, variant_type=variant_type, form=form, severe_so_terms=SEVERE_SO_TERMS, page=page, **data)
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)
def _request_handler(self, **kwargs): """ We handle all requests to the host:port. The general flow of handling a request is as follows * Fetch request from the Flask Global state. This is where Flask places the request and is per thread so multiple requests are still handled correctly * Find the Lambda function to invoke by doing a look up based on the request.endpoint and method * If we don't find the function, we will throw a 502 (just like the 404 and 405 responses we get from Flask. * Since we found a Lambda function to invoke, we construct the Lambda Event from the request * Then Invoke the Lambda function (docker container) * We then transform the response or errors we get from the Invoke and return the data back to the caller Parameters ---------- kwargs dict Keyword Args that are passed to the function from Flask. This happens when we have path parameters Returns ------- Response object """ route = self._get_current_route(request) cors_headers = Cors.cors_to_headers(self.api.cors) method, endpoint = self.get_request_methods_endpoints(request) if method == "OPTIONS" and self.api.cors: headers = Headers(cors_headers) return self.service_response("", headers, 200) try: # the Lambda Event 2.0 is only used for the HTTP API gateway with defined payload format version equal 2.0 # or none, as the default value to be used is 2.0 # https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-integrations.html#apis-apiid-integrations-prop-createintegrationinput-payloadformatversion if route.event_type == Route.HTTP and route.payload_format_version in [ None, "2.0" ]: route_key = self._v2_route_key(method, endpoint, route.is_default_route) event = self._construct_v_2_0_event_http( request, self.port, self.api.binary_media_types, self.api.stage_name, self.api.stage_variables, route_key, ) else: event = self._construct_v_1_0_event( request, self.port, self.api.binary_media_types, self.api.stage_name, self.api.stage_variables) except UnicodeDecodeError: return ServiceErrorResponses.lambda_failure_response() stdout_stream = io.BytesIO() stdout_stream_writer = StreamWriter(stdout_stream, self.is_debugging) try: self.lambda_runner.invoke(route.function_name, event, stdout=stdout_stream_writer, stderr=self.stderr) except FunctionNotFound: return ServiceErrorResponses.lambda_not_found_response() lambda_response, lambda_logs, _ = LambdaOutputParser.get_lambda_output( stdout_stream) if self.stderr and lambda_logs: # Write the logs to stderr if available. self.stderr.write(lambda_logs) try: if route.event_type == Route.HTTP and ( not route.payload_format_version or route.payload_format_version == "2.0"): (status_code, headers, body) = self._parse_v2_payload_format_lambda_output( lambda_response, self.api.binary_media_types, request) else: (status_code, headers, body) = self._parse_v1_payload_format_lambda_output( lambda_response, self.api.binary_media_types, request) except LambdaResponseParseException as ex: LOG.error("Invalid lambda response received: %s", ex) return ServiceErrorResponses.lambda_failure_response() return self.service_response(body, headers, status_code)