def __call__(self, environ, start_response): request = Request(environ) if not request.headers.get(REQUEST_ID_HEADER, None): req_id = str(uuid.uuid4()) request.headers[REQUEST_ID_HEADER] = req_id def custom_start_response(status, headers, exc_info=None): headers = ResponseHeaders(headers) req_id_header = request.headers.get(REQUEST_ID_HEADER, None) if req_id_header: headers[REQUEST_ID_HEADER] = req_id_header return start_response(status, headers._items, exc_info) return self.app(environ, custom_start_response)
def __call__(self, environ, start_response): request = Request(environ) def custom_start_response(status, headers, exc_info=None): headers = ResponseHeaders(headers) origin = request.headers.get('Origin') origins = set(cfg.CONF.api.allow_origin) # Build a list of the default allowed origins public_api_url = cfg.CONF.auth.api_url # Default gulp development server WebUI URL origins.add('http://127.0.0.1:3000') # By default WebUI simple http server listens on 8080 origins.add('http://localhost:8080') origins.add('http://127.0.0.1:8080') if public_api_url: # Public API URL origins.add(public_api_url) if origin: if '*' in origins: origin_allowed = '*' else: # See http://www.w3.org/TR/cors/#access-control-allow-origin-response-header origin_allowed = origin if origin in origins else 'null' else: origin_allowed = list(origins)[0] methods_allowed = ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'] request_headers_allowed = [ 'Content-Type', 'Authorization', HEADER_ATTRIBUTE_NAME, HEADER_API_KEY_ATTRIBUTE_NAME, REQUEST_ID_HEADER ] response_headers_allowed = [ 'Content-Type', 'X-Limit', 'X-Total-Count', REQUEST_ID_HEADER ] headers['Access-Control-Allow-Origin'] = origin_allowed headers['Access-Control-Allow-Methods'] = ','.join(methods_allowed) headers['Access-Control-Allow-Headers'] = ','.join( request_headers_allowed) headers['Access-Control-Expose-Headers'] = ','.join( response_headers_allowed) return start_response(status, headers._items, exc_info) try: return self.app(environ, custom_start_response) except NotFoundException: if request.method != 'options': raise return Response()(environ, custom_start_response)
def __call__(self, environ, start_response): # The middleware sets a number of headers that helps prevent a range of attacks in browser # environment. It also handles OPTIONS requests used by browser as pre-flight check before # the potentially insecure request is made. An absence of this headers on the response will # prevent the error from ever reaching the JS layer of client-side code making it impossible # to process the response or provide a human-friendly error message. Order is not important # as long at this condition is met and headers not get overridden by another middleware # higher up the call stack. request = Request(environ) def custom_start_response(status, headers, exc_info=None): headers = ResponseHeaders(headers) origin = request.headers.get('Origin') origins = set(cfg.CONF.api.allow_origin) # Build a list of the default allowed origins public_api_url = cfg.CONF.auth.api_url # Default gulp development server WebUI URL origins.add('http://127.0.0.1:3000') # By default WebUI simple http server listens on 8080 origins.add('http://localhost:8080') origins.add('http://127.0.0.1:8080') if public_api_url: # Public API URL origins.add(public_api_url) if origin: if '*' in origins: origin_allowed = '*' else: # See http://www.w3.org/TR/cors/#access-control-allow-origin-response-header origin_allowed = origin if origin in origins else 'null' else: origin_allowed = list(origins)[0] methods_allowed = ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'] request_headers_allowed = ['Content-Type', 'Authorization', HEADER_ATTRIBUTE_NAME, HEADER_API_KEY_ATTRIBUTE_NAME, REQUEST_ID_HEADER] response_headers_allowed = ['Content-Type', 'X-Limit', 'X-Total-Count', REQUEST_ID_HEADER] headers['Access-Control-Allow-Origin'] = origin_allowed headers['Access-Control-Allow-Methods'] = ','.join(methods_allowed) headers['Access-Control-Allow-Headers'] = ','.join(request_headers_allowed) headers['Access-Control-Expose-Headers'] = ','.join(response_headers_allowed) return start_response(status, headers._items, exc_info) if request.method == 'OPTIONS': return Response()(environ, custom_start_response) else: return self.app(environ, custom_start_response)
def __call__(self, environ, start_response): # The middleware adds unique `X-Request-ID` header on the requests that don't have it and # modifies the responses to have the same exact header as their request. The middleware # helps us better track relation between request and response in places where it might not # be immediately obvious (like logs for example). In general, you want to place this header # as soon as possible to ensure it's present by the time it's needed. Certainly before # LoggingMiddleware which relies on this header. request = Request(environ) if not request.headers.get(REQUEST_ID_HEADER, None): req_id = str(uuid.uuid4()) request.headers[REQUEST_ID_HEADER] = req_id def custom_start_response(status, headers, exc_info=None): headers = ResponseHeaders(headers) req_id_header = request.headers.get(REQUEST_ID_HEADER, None) if req_id_header: headers[REQUEST_ID_HEADER] = req_id_header return start_response(status, headers._items, exc_info) return self.app(environ, custom_start_response)
def __call__(self, environ, start_response): start_time = clock() status_code = [] content_length = [] request = Request(environ) query_params = request.GET.dict_of_lists() # Mask secret / sensitive query params secret_query_params = SECRET_QUERY_PARAMS + cfg.CONF.log.mask_secrets_blacklist for param_name in secret_query_params: if param_name in query_params: query_params[param_name] = MASKED_ATTRIBUTE_VALUE # Log the incoming request values = { 'method': request.method, 'path': request.path, 'remote_addr': request.remote_addr, 'query': query_params, 'request_id': request.headers.get(REQUEST_ID_HEADER, None) } LOG.info('%(request_id)s - %(method)s %(path)s with query=%(query)s' % values, extra=values) def custom_start_response(status, headers, exc_info=None): status_code.append(int(status.split(' ')[0])) for name, value in headers: if name.lower() == 'content-length': content_length.append(int(value)) break return start_response(status, headers, exc_info) retval = self.app(environ, custom_start_response) try: endpoint, path_vars = self.router.match(request) except NotFoundException: endpoint = {} log_result = endpoint.get('x-log-result', True) if isinstance(retval, (types.GeneratorType, itertools.chain)): # Note: We don't log the result when return value is a generator, because this would # result in calling str() on the generator and as such, exhausting it content_length = [float('inf')] log_result = False # Log the response values = { 'method': request.method, 'path': request.path, 'remote_addr': request.remote_addr, 'status': status_code[0], 'runtime': float("{0:.3f}".format((clock() - start_time) * 10**3)), 'content_length': content_length[0] if content_length else len(b''.join(retval)), 'request_id': request.headers.get(REQUEST_ID_HEADER, None) } log_msg = '%(request_id)s - %(status)s %(content_length)s %(runtime)sms' % ( values) LOG.info(log_msg, extra=values) if log_result: values['result'] = retval[0] log_msg = ( '%(request_id)s - %(status)s %(content_length)s %(runtime)sms\n%(result)s' % (values)) LOG.debug(log_msg, extra=values) return retval
def __call__(self, environ, start_response): start_time = clock() status_code = [] content_length = [] request = Request(environ) # Log the incoming request values = { 'method': request.method, 'path': request.path, 'remote_addr': request.remote_addr, 'query': request.GET.dict_of_lists(), 'request_id': request.headers.get(REQUEST_ID_HEADER, None) } LOG.info('%(request_id)s - %(method)s %(path)s with query=%(query)s' % values, extra=values) def custom_start_response(status, headers, exc_info=None): status_code.append(int(status.split(' ')[0])) for name, value in headers: if name.lower() == 'content-length': content_length.append(int(value)) break return start_response(status, headers, exc_info) retval = self.app(environ, custom_start_response) try: endpoint, path_vars = self.router.match(request) except NotFoundException: endpoint = {} log_result = endpoint.get('x-log-result', True) if isinstance(retval, types.GeneratorType): content_length = [float('inf')] log_result = False # Log the incoming request values = { 'method': request.method, 'path': request.path, 'remote_addr': request.remote_addr, 'status': status_code[0], 'runtime': float("{0:.3f}".format((clock() - start_time) * 10**3)), 'content_length': content_length[0] if content_length else len(b''.join(retval)), 'request_id': request.headers.get(REQUEST_ID_HEADER, None) } if log_result: values['result'] = retval[0] log_msg = '%(request_id)s - %(status)s %(content_length)s %(runtime)sms\n%(result)s'\ % values else: log_msg = '%(request_id)s - %(status)s %(content_length)s %(runtime)sms' % values LOG.info(log_msg, extra=values) return retval