def upload(request: HttpRequest) -> JsonResponse: logging.log_request_received( logger, request.META['PATH_INFO'] if 'PATH_INFO' in request.META.keys() else '-path to file UNAVAILABLE-', FileTransferToken.Operation.upload ) if request.content_type in ['multipart/form-data', '', None] or request.content_type.isspace(): return gatekeeper_access_denied_response( 'Unsupported content type.', FileTransferToken.Operation.upload, ErrorCode.HEADER_CONTENT_TYPE_NOT_SUPPORTED, request.META['PATH_INFO'] if 'PATH_INFO' in request.META.keys() else 'UNAVAILABLE' ) path_to_file = request.get_full_path().partition(reverse('gatekeeper:upload'))[2] response_or_file_info = parse_headers(request, path_to_file, FileTransferToken.Operation.upload) if not isinstance(response_or_file_info, FileTransferToken.FileInfo): assert isinstance(response_or_file_info, JsonResponse) return response_or_file_info response = JsonResponse({"message": "Request passed all upload validations."}, status = 200) response["Concent-File-Size"] = response_or_file_info["size"] response["Concent-File-Checksum"] = response_or_file_info["checksum"] return response
def report_upload(_request: HttpRequest, file_path: str) -> HttpResponse: log_request_received(logger, file_path, FileTransferToken.Operation.upload) # If there's a corresponding VerificationRequest, the load it and link it to UploadReport. try: verification_request = VerificationRequest.objects.select_for_update( ).get( Q(source_package_path=file_path) | Q(result_package_path=file_path)) except VerificationRequest.DoesNotExist: verification_request = None # The app creates a new instance of UploadReport in the database. upload_report = UploadReport( path=file_path, verification_request=verification_request, ) upload_report.full_clean() upload_report.save() # The app gets the VerificationRequest and checks if both source and result packages have reports. if (verification_request is not None and verification_request.blender_subtask_definition is not None and verification_request.upload_reports.filter( path=verification_request.source_package_path).exists() and verification_request.upload_reports.filter( path=verification_request.result_package_path).exists() and verification_request.upload_reports.filter( path=file_path).count() == 1): assert file_path in [ verification_request.source_package_path, verification_request.result_package_path ] # If all expected files have been uploaded, the app sends upload_finished task to the work queue. upload_finished.delay(verification_request.subtask_id) verification_request.upload_finished = True verification_request.full_clean() verification_request.save() log(logger, 'All expected files have been uploaded', f'Result package path: {verification_request.result_package_path}.' f'Source package path: {verification_request.source_package_path}.', subtask_id=verification_request.subtask_id) # If ResultTransferRequest matching the file exists, report finished upload. result_transfer_request = ResultTransferRequest.objects.filter( result_package_path=file_path).first() if result_transfer_request is not None: update_upload_report( file_path=file_path, result_transfer_request=result_transfer_request, ) return HttpResponse()
def download(request): logging.log_request_received( logger, request.META['PATH_INFO'] if 'PATH_INFO' in request.META.keys() else '-path to file UNAVAILABLE-', FileTransferToken.Operation.download ) # The client should not sent Content-Type header with GET requests. # FIXME: When running on `manage.py runserver` in development, empty or missing Concent-Type gets replaced # with text/plain. gunicorn does not do this. Looks like a bug to me. We'll let it pass for now sice we ignore # the body anyway and the check is mostly to inform the client about its mistake. if request.content_type != 'text/plain' and request.content_type != '': return gatekeeper_access_denied_response( 'Download request cannot have data in the body.', FileTransferToken.Operation.download, ErrorCode.REQUEST_BODY_NOT_EMPTY, ) path_to_file = request.get_full_path().partition(reverse('gatekeeper:download'))[2] response_or_file_info = parse_headers(request, path_to_file, FileTransferToken.Operation.download) if not isinstance(response_or_file_info, FileTransferToken.FileInfo): assert isinstance(response_or_file_info, JsonResponse) return response_or_file_info return JsonResponse({"message": "Request passed all download validations."}, status = 200)