def handle_api_static_request(self, request, start_response): """Handler for requests to _ah/api/static/.*. This calls start_response and returns the response body. Args: request: An ApiRequest, the request from the user. start_response: A function with semantics defined in PEP-333. Returns: A string containing the response body. """ discovery_api = discovery_api_proxy.DiscoveryApiProxy() response, body = discovery_api.get_static_file(request.relative_url) status_string = '%d %s' % (response.status, response.reason) if response.status == 200: # Some of the headers that come back from the server can't be passed # along in our response. Specifically, the response from the server has # transfer-encoding: chunked, which doesn't apply to the response that # we're forwarding. There may be other problematic headers, so we strip # off everything but Content-Type. return util.send_wsgi_response(status_string, [('Content-Type', response.getheader('Content-Type'))], body, start_response) else: logging.error('Discovery API proxy failed on %s with %d. Details: %s', request.relative_url, response.status, body) return util.send_wsgi_response(status_string, response.getheaders(), body, start_response)
def handle_api_static_request(self, request, start_response): """Handler for requests to _ah/api/static/.*. This calls start_response and returns the response body. Args: request: An ApiRequest, the request from the user. start_response: A function with semantics defined in PEP-333. Returns: A string containing the response body. """ discovery_api = discovery_api_proxy.DiscoveryApiProxy() response, body = discovery_api.get_static_file(request.relative_url) status_string = '%d %s' % (response.status, response.reason) if response.status == 200: # Some of the headers that come back from the server can't be passed # along in our response. Specifically, the response from the server has # transfer-encoding: chunked, which doesn't apply to the response that # we're forwarding. There may be other problematic headers, so we strip # off everything but Content-Type. return util.send_wsgi_response( status_string, [('Content-Type', response.getheader('Content-Type'))], body, start_response) else: logging.error( 'Discovery API proxy failed on %s with %d. Details: %s', request.relative_url, response.status, body) return util.send_wsgi_response(status_string, response.getheaders(), body, start_response)
def _handle_request_error(self, orig_request, error, start_response): """Handle a request error, converting it to a WSGI response. Args: orig_request: An ApiRequest, the original request from the user. error: A RequestError containing information about the error. start_response: A function with semantics defined in PEP-333. Returns: A string containing the response body. """ headers = [('Content-Type', 'application/json')] if orig_request.is_rpc(): # JSON RPC errors are returned with status 200 OK and the # error details in the body. status_code = 200 body = self._finish_rpc_response(orig_request.body_json.get('id'), orig_request.is_batch(), error.rpc_error()) else: status_code = error.status_code() body = error.rest_error() response_status = '%d %s' % ( status_code, httplib.responses.get(status_code, 'Unknown Error')) cors_handler = EndpointsDispatcher.__CheckCorsHeaders(orig_request) return util.send_wsgi_response(response_status, headers, body, start_response, cors_handler=cors_handler)
def dispatch_non_api_requests(self, request, start_response): """Dispatch this request if this is a request to a reserved URL. If the request matches one of our reserved URLs, this calls start_response and returns the response body. This also handles OPTIONS CORS requests. Args: request: An ApiRequest, the request from the user. start_response: A function with semantics defined in PEP-333. Returns: None if the request doesn't match one of the reserved URLs this handles. Otherwise, returns the response body. """ for path_regex, dispatch_function in self._dispatchers: if path_regex.match(request.relative_url): return dispatch_function(request, start_response) if request.http_method == 'OPTIONS': cors_handler = EndpointsDispatcher.__CheckCorsHeaders(request) if cors_handler.allow_cors_request: # The server returns 200 rather than 204, for some reason. return util.send_wsgi_response('200', [], '', start_response, cors_handler) return None
def _handle_request_error(self, orig_request, error, start_response): """Handle a request error, converting it to a WSGI response. Args: orig_request: An ApiRequest, the original request from the user. error: A RequestError containing information about the error. start_response: A function with semantics defined in PEP-333. Returns: A string containing the response body. """ headers = [('Content-Type', 'application/json')] if orig_request.is_rpc(): # JSON RPC errors are returned with status 200 OK and the # error details in the body. status_code = 200 body = self._finish_rpc_response(orig_request.body_json.get('id'), orig_request.is_batch(), error.rpc_error()) else: status_code = error.status_code() body = error.rest_error() response_status = '%d %s' % (status_code, httplib.responses.get(status_code, 'Unknown Error')) cors_handler = EndpointsDispatcher.__CheckCorsHeaders(orig_request) return util.send_wsgi_response(response_status, headers, body, start_response, cors_handler=cors_handler)
def dispatch_non_api_requests(self, request, start_response): """Dispatch this request if this is a request to a reserved URL. If the request matches one of our reserved URLs, this calls start_response and returns the response body. This also handles OPTIONS CORS requests. Args: request: An ApiRequest, the request from the user. start_response: A function with semantics defined in PEP-333. Returns: None if the request doesn't match one of the reserved URLs this handles. Otherwise, returns the response body. """ for path_regex, dispatch_function in self._dispatchers: if path_regex.match(request.relative_url): return dispatch_function(request, start_response) if request.http_method == 'OPTIONS': cors_handler = EndpointsDispatcher.__CheckCorsHeaders(request) if cors_handler.allow_cors_request: # The server returns 200 rather than 204, for some reason. return util.send_wsgi_response('200', [], '', start_response, cors_handler) return None
def handle_spi_response(self, orig_request, spi_request, response, start_response): """Handle SPI response, transforming output as needed. This calls start_response and returns the response body. Args: orig_request: An ApiRequest, the original request from the user. spi_request: An ApiRequest, the transformed request that was sent to the SPI handler. response: A ResponseTuple, the response from the SPI handler. start_response: A function with semantics defined in PEP-333. Returns: A string containing the response body. """ # Verify that the response is json. If it isn't treat, the body as an # error message and wrap it in a json error response. for header, value in response.headers: if (header.lower() == 'content-type' and not value.lower().startswith('application/json')): return self.fail_request(orig_request, 'Non-JSON reply: %s' % response.content, start_response) body = response.content # Need to check is_rpc() against the original request, because the # incoming request here has had its path modified. if orig_request.is_rpc(): body = self.transform_jsonrpc_response(spi_request, body) cors_handler = EndpointsDispatcher.__CheckCorsHeaders(orig_request) return util.send_wsgi_response(response.status, response.headers, body, start_response, cors_handler=cors_handler)
def test_send_wsgi_response(self): mock_headers = [('content-type', 'text/plain')] content = 'Test output' response = util.send_wsgi_response('200', mock_headers, content, self.start_response) self.assert_http_match(response, 200, [('content-type', 'text/plain'), ('Content-Length', '11')], content)
def test_send_wsgi_response(self): mock_headers = [('content-type', 'text/plain')] content = 'Test output' response = util.send_wsgi_response( '200', mock_headers, content, self.start_response) self.assert_http_match(response, 200, [('content-type', 'text/plain'), ('Content-Length', '11')], content)
def handle_spi_response(self, orig_request, spi_request, response, method_config, start_response): """Handle SPI response, transforming output as needed. This calls start_response and returns the response body. Args: orig_request: An ApiRequest, the original request from the user. spi_request: An ApiRequest, the transformed request that was sent to the SPI handler. response: A ResponseTuple, the response from the SPI handler. method_config: A dict, the API config of the method to be called. start_response: A function with semantics defined in PEP-333. Returns: A string containing the response body. """ # Verify that the response is json. If it isn't treat, the body as an # error message and wrap it in a json error response. for header, value in response.headers: if (header.lower() == 'content-type' and not value.lower().startswith('application/json')): return self.fail_request( orig_request, 'Non-JSON reply: %s' % response.content, start_response) self.check_error_response(response) # Need to check is_rpc() against the original request, because the # incoming request here has had its path modified. if orig_request.is_rpc(): body = self.transform_jsonrpc_response(spi_request, response.content) else: # Check if the response from the SPI was empty. Empty REST responses # generate a HTTP 204. empty_response = self.check_empty_response(orig_request, method_config, start_response) if empty_response is not None: return empty_response body = self.transform_rest_response(response.content) cors_handler = EndpointsDispatcher.__CheckCorsHeaders(orig_request) return util.send_wsgi_response(response.status, response.headers, body, start_response, cors_handler=cors_handler)
def _send_success_response(self, response, start_response): """Sends an HTTP 200 json success response. This calls start_response and returns the response body. Args: response: A string containing the response body to return. start_response: A function with semantics defined in PEP-333. Returns: A string, the response body. """ headers = [('Content-Type', 'application/json; charset=UTF-8')] return util.send_wsgi_response('200', headers, response, start_response)
def _send_success_response(self, response, start_response): """Sends an HTTP 200 json success response. This calls start_response and returns the response body. Args: response: A string containing the response body to return. start_response: A function with semantics defined in PEP-333. Returns: A string, the response body. """ headers = [('Content-Type', 'application/json; charset=UTF-8')] return util.send_wsgi_response('200', headers, response, start_response)
def test_send_wsgi_response(self): mock_headers = [("content-type", "text/plain")] content = "Test output" response = util.send_wsgi_response("200", mock_headers, content, self.start_response) self.assert_http_match(response, 200, [("content-type", "text/plain"), ("Content-Length", "11")], content)