def package(app, request, path): # Get our filename and filepath from the request path filename = os.path.basename(path) filepath = safe_join(os.path.abspath(app.config.paths.packages), path) # If we cannot safely join the requested path with our directory # return a 404 if filepath is None: raise NotFound("{} was not found".format(filename)) # Open the file and attempt to wrap in the wsgi.file_wrapper if it's # available, otherwise read it directly. try: fp = open(filepath, "rb") data = wrap_file(request.environ, fp) except IOError: raise NotFound("{} was not found".format(filename)) # Get the project name and normalize it lookup_filename = filename[:-4] if filename.endswith(".asc") else filename project = app.db.packaging.get_project_for_filename(lookup_filename) # Get the MD5 hash of the file content_md5 = app.db.packaging.get_filename_md5(filename) headers = {} # Add in additional headers if we're using Fastly headers["Surrogate-Key"] = " ".join( fastly.projects.format_keys(project=project), ) # Look up the last serial for this file serial = app.db.packaging.get_last_serial(project) if serial is not None: headers["X-PyPI-Last-Serial"] = serial # Pass through the data directly to the response object resp = Response( data, headers=headers, mimetype=get_mimetype(filename), direct_passthrough=True, ) # Setup the Last-Modified header resp.last_modified = os.path.getmtime(filepath) # Setup the Content-Length header resp.content_length = os.path.getsize(filepath) if content_md5: # Setup the Content-MD5 headers resp.content_md5 = content_md5 # Setup Conditional Responses resp.set_etag(content_md5) resp.make_conditional(request) return resp
def test_get_mimetype(filename, expected): assert get_mimetype(filename) == expected
def package(app, request, path): # Get our filename and filepath from the request path filename = os.path.basename(path) filepath = safe_join( os.path.abspath(app.config.paths.packages), path ) # If we cannot safely join the requested path with our directory # return a 404 if filepath is None: raise NotFound("{} was not found".format(filename)) # Open the file and attempt to wrap in the wsgi.file_wrapper if it's # available, otherwise read it directly. try: fp = open(filepath, "rb") data = wrap_file(request.environ, fp) except IOError: raise NotFound("{} was not found".format(filename)) # Get the project name and normalize it lookup_filename = filename[:-4] if filename.endswith(".asc") else filename project = app.db.packaging.get_project_for_filename(lookup_filename) normalized = normalize(project) # Get the MD5 hash of the file content_md5 = app.db.packaging.get_filename_md5(filename) headers = {} # Add in additional headers if we're using Fastly headers.update({ "Surrogate-Key": " ".join([ "package", "package~{}".format(normalized), ]), }) # Look up the last serial for this file serial = app.db.packaging.get_last_serial(project) if serial is not None: headers["X-PyPI-Last-Serial"] = serial # Pass through the data directly to the response object resp = Response( data, headers=headers, mimetype=get_mimetype(filename), direct_passthrough=True, ) # Setup the Last-Modified header resp.last_modified = os.path.getmtime(filepath) # Setup the Content-Length header resp.content_length = os.path.getsize(filepath) if content_md5: # Setup the Content-MD5 headers resp.content_md5 = content_md5 # Setup Conditional Responses resp.set_etag(content_md5) resp.make_conditional(request) return resp