def construct_wsgi_from_data(request, data, replace_params={}, rewriter=None): ''' Given the data in the format of url, method, body and headers, construct a new WSGIRequest object. ''' valid_http_methods = [ 'get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'connect', 'trace' ] if rewriter: rewriter.rewrite_request(data) url = data.get('url', None) method = data.get('method', None) if url is None or method is None: raise BadBatchRequest( 'Request definition should have url, method defined.') if method.lower() not in valid_http_methods: raise BadBatchRequest('Invalid request method.') body = None if method.lower() not in ['get', 'options']: body = data.get('body', '') for name, value in replace_params.items(): placeholder = '"{{' + name + '}}"' body = json.loads(json.dumps(body).replace(placeholder, value)) headers = data.get('headers', {}) onward_variables = data.get('onward_data', {}) wsgi_request = get_wsgi_request_object(request, method, url, headers, body) return (wsgi_request, onward_variables)
def get_wsgi_requests(request): ''' For the given batch request, extract the individual requests and create WSGIRequest object for each. ''' valid_http_methods = [ "get", "post", "put", "patch", "delete", "head", "options", "connect", "trace" ] try: requests = json.loads(request.body) except ValueError: raise BadBatchRequest("Please send a valid JSON") if type(requests) not in (list, tuple): raise BadBatchRequest( "The body of batch request should always be list!") # Max limit check. no_requests = len(requests) if no_requests > _settings.MAX_LIMIT: raise BadBatchRequest("You can batch maximum of %d requests." % (_settings.MAX_LIMIT)) authentication_header = None if 'HTTP_AUTHORIZATION' in request.META: authentication_header = { 'Authorization': request.META['HTTP_AUTHORIZATION'] } # We could mutate the current request with the respective parameters, but mutation is ghost in the dark, # so lets avoid. Construct the new WSGI request object for each request. def construct_wsgi_from_data(data, authentication_header): ''' Given the data in the format of url, method, body and headers, construct a new WSGIRequest object. ''' url = data.get("url", None) method = data.get("method", None) if url is None or method is None: raise BadBatchRequest( "Request definition should have url, method defined.") if method.lower() not in valid_http_methods: raise BadBatchRequest("Invalid request method.") body = data.get("body", "") if authentication_header is None: authentication_header = data.get("headers", {}) return get_wsgi_request_object(request, method, url, authentication_header, body) return [ construct_wsgi_from_data(data, authentication_header) for data in requests ]
def get_requests_data(request): ''' For the given batch request, extract the individual requests and create WSGIRequest object for each. ''' requests = json.loads(request.body).get('batch', []) if type(requests) not in (list, tuple): raise BadBatchRequest('The body of batch request should always be list!') # Max limit check. no_requests = len(requests) if no_requests > _settings.MAX_LIMIT: raise BadBatchRequest('You can batch maximum of %d requests.' % (_settings.MAX_LIMIT)) return requests
def construct_wsgi_from_data(data): ''' Given the data in the format of url, method, body and headers, construct a new WSGIRequest object. ''' url = data.get("url", None) method = data.get("method", None) if url is None or method is None: raise BadBatchRequest("Request definition should have url, method defined.") if method.lower() not in valid_http_methods: raise BadBatchRequest("Invalid request method.") body = data.get("body", "") headers = data.get("headers", {}) return get_wsgi_request_object(request, method, url, headers, body)
def get_wsgi_requests(request): ''' For the given batch request, extract the individual requests and create WSGIRequest object for each. ''' valid_http_methods = [ "get", "post", "put", "patch", "delete", "head", "options", "connect", "trace" ] requests = json.loads(request.body.decode('utf-8')) if type(requests) not in (list, tuple): raise BadBatchRequest( "The body of batch request should always be list!") # Max limit check. no_requests = len(requests) if no_requests > _settings.MAX_LIMIT: raise BadBatchRequest("You can batch maximum of %d requests." % (_settings.MAX_LIMIT)) # We could mutate the current request with the respective parameters, but mutation is ghost in the dark, # so lets avoid. Construct the new WSGI request object for each request. def construct_wsgi_from_data(data): ''' Given the data in the format of url, method, body and headers, construct a new WSGIRequest object. ''' url = data.get("url", None) method = data.get("method", None) if url is None or method is None: raise BadBatchRequest( "Request definition should have url, method defined.") if method.lower() not in valid_http_methods: raise BadBatchRequest("Invalid request method.") body = data.get("body", "") headers = data.get("headers", {}) return get_wsgi_request_object(request, method, url, headers, body) return [construct_wsgi_from_data(data) for data in requests]
def execute_requests(request, sequential_override=False): ''' Execute the requests either sequentially or in parallel based on parallel execution setting. ''' if sequential_override: # We have to choose a rewriter before we begin processing requests as # each request can add new mappings to the rewriter. By default we'll # use a JSON-API rewriter, but in the future we may want to make this # more dynamic. rewriter = JsonApiRewriter() with transaction.atomic(): next_variables = {} results = [] # Get the data to make the requests requests = get_requests_data(request) for i, request_data in enumerate(requests): # Generate the requests using additional data if passed wsgi_request, onward_params = construct_wsgi_from_data( request, request_data, replace_params=next_variables, rewriter=rewriter ) result = get_response(wsgi_request) # Add the response to the rewriter. rewriter.update_mapping(request_data, result) results.append(result) if is_error(result['status_code']): raise BadBatchRequest( f'Sequential requests failed for request at index {i}: ' + json.dumps(result['body']) ) # Take the value of any onward passing variables from the response for name, accessor_string in onward_params.items(): value = None # Allow retrieval of nested values using dot notaion accessors = accessor_string.split('.') if len(accessors): value = result['body'] for accessor in accessors: value = value[accessor] if value: next_variables[name] = value return results else: try: # Get the Individual WSGI requests. wsgi_requests = get_wsgi_requests(request) except BadBatchRequest as brx: return HttpResponseBadRequest(content=str(brx)) return _settings.executor.execute(wsgi_requests, get_response)
def get_wsgi_requests(request): ''' For the given batch request, extract the individual requests and create WSGIRequest object for each. ''' body = request.body.decode('utf-8') requests = json.loads(body) if not isinstance(requests, (list, tuple)): raise BadBatchRequest( "The body of batch request should always be list!") if len(requests) > _settings.MAX_LIMIT: raise BadBatchRequest("You can batch maximum of %d requests." % (_settings.MAX_LIMIT)) # We could mutate the current request with the respective parameters, but # mutation is ghost in the dark, so lets avoid. Construct the new WSGI # request object for each request. def construct_wsgi_from_data(data, valid_http_methods=VALID_HTTP_METHODS): ''' Given the data in the format of url, method, body and headers, construct a new WSGIRequest object. ''' url = data.get("url", None) method = data.get("method", None) if url is None or method is None: raise BadBatchRequest( "Request definition should have url, method defined.") method = method.upper() if method not in valid_http_methods: raise BadBatchRequest("Invalid request method.") # support singly/doubly encoded JSON body = data.get("body", "") if isinstance(body, dict): body = json.dumps(body, cls=BytesEncoder) headers = data.get("headers", {}) return get_wsgi_request_object(request, method, url, headers, body) return (construct_wsgi_from_data(data) for data in requests)
def construct_wsgi_from_data(data, valid_http_methods=VALID_HTTP_METHODS): ''' Given the data in the format of url, method, body and headers, construct a new WSGIRequest object. ''' url = data.get("url", None) method = data.get("method", None) if url is None or method is None: raise BadBatchRequest("Request definition should have url, method defined.") method = method.upper() if method not in valid_http_methods: raise BadBatchRequest("Invalid request method.") # support singly/doubly encoded JSON body = data.get("body", "") if isinstance(body, dict): body = json.dumps(body, cls=BytesEncoder) headers = data.get("headers", {}) return get_wsgi_request_object(request, method, url, headers, body)