def rpc_async(req): """Sends an asynchronous pRPC request. This API is low level. Most users should use Client class instead. Args: req (Request): a pRPC request. Returns the response message if the RPC status code is OK. Otherwise raises an Error. """ # The protocol is documented in # https://godoc.org/go.chromium.org/luci/grpc/prpc#hdr-Protocol # Ensure timeout is set, such that we use same values for deadline # parameter in net.request_async and X-Prpc-Timeout value are same. # Default to 10s, which is the default used in net.request_async. timeout = req.timeout or 10 headers = (req.metadata or {}).copy() headers['Content-Type'] = _BINARY_MEDIA_TYPE headers['Accept'] = _BINARY_MEDIA_TYPE headers['X-Prpc-Timeout'] = '%dS' % timeout try: res_bytes = yield net.request_async( url='http%s://%s/prpc/%s/%s' % ( '' if req.insecure else 's', req.hostname, req.service_name, req.method_name, ), method='POST', payload=req.request_message.SerializeToString(), headers=headers, scopes=req.scopes, service_account_key=req.service_account_key, delegation_token=req.delegation_token, deadline=timeout, max_attempts=req.max_attempts or 4, ) # Unfortunately, net module does not expose headers of HTTP 200 # responses. # Assume (HTTP OK => pRPC OK). except net.Error as ex: # net.Error means HTTP status code was not 200. try: code = codes.INT_TO_CODE[int(ex.headers['X-Prpc-Grpc-Code'])] except (ValueError, KeyError, TypeError): raise ProtocolError( 'response does not contain a valid X-Prpc-Grpc-Code header') msg = ex.response.decode('utf-8', 'ignore') raise RpcError(msg, code, ex.headers) # Status code is OK. # Parse the response and return it. res = req.response_message res.ParseFromString(res_bytes) raise ndb.Return(res)
def _load_docs_async(locs, rev): """Loads rendered .md files from Gitiles as a list of search.Documents. Args: locs (list of gitiles.Location): locations of files to import. rev (str): revision of files to import. """ fixed_locs = [l._replace(treeish=rev) for l in locs] headers = { 'User-Agent': app_identity.get_default_version_hostname(), } htmls = yield [ net.request_async(str(l), headers=headers, scopes=gerrit.AUTH_SCOPE) for l in fixed_locs ] raise ndb.Return([ create(loc, html) for loc, html in zip(locs, htmls) ])
def fetch_file_async(url, oauth_scopes): """Fetches a file optionally using OAuth2 for authentication. Args: url: url to a file to fetch. oauth_scopes: list of OAuth scopes to use when generating access_token for accessing |url|, if not set or empty - do not use OAuth. Returns: Byte buffer with file's body. Raises: BundleImportError on fetch errors. """ try: data = yield net.request_async(url, scopes=oauth_scopes, deadline=60) raise ndb.Return(data) except net.Error as e: raise BundleFetchError(url, e.status_code, e.response)
def fetch_file_async(url, oauth_scopes): """Fetches a file optionally using OAuth2 for authentication. Args: url: url to a file to fetch. oauth_scopes: list of OAuth scopes to use when generating access_token for accessing |url|, if not set or empty - do not use OAuth. Returns: Byte buffer with file's body. Raises: BundleImportError on fetch errors. """ try: data = yield net.request_async(url, scopes=oauth_scopes, deadline=60) raise ndb.Return(data) except net.Error as e: raise BundleFetchError(url, e.status_code, e.content)
def fetch_async(hostname, path, **kwargs): """Sends request to Gerrit, returns raw response. See 'net.request_async' for list of accepted kwargs. Returns: Response body on success. None on 404 response. Raises: net.Error on communication errors. """ assert not path.startswith('/'), path assert 'scopes' not in kwargs, kwargs['scopes'] try: url = urlparse.urljoin('https://' + hostname, 'a/' + path) result = yield net.request_async(url, scopes=[AUTH_SCOPE], **kwargs) raise ndb.Return(result) except net.NotFoundError: raise ndb.Return(None)
def rpc_async(req, response_metadata=None): """Sends an asynchronous pRPC request. This API is low level. Most users should use Client class instead. Args: req (Request): a pRPC request. response_metadata (dict): a dict to populate with the response's metadata. Returns the response message if the RPC status code is OK, if given, populates response_metadata with the response's headers. Otherwise raises an Error. """ # The protocol is documented in # https://godoc.org/go.chromium.org/luci/grpc/prpc#hdr-Protocol # Ensure timeout is set, such that we use same values for deadline # parameter in net.request_async and X-Prpc-Timeout value are same. # Default to 10s, which is the default used in net.request_async. timeout = req.timeout or 10 headers = (req.metadata or {}).copy() encoding.encode_bin_metadata(headers) headers['Content-Type'] = _BINARY_MEDIA_TYPE headers['Accept'] = _BINARY_MEDIA_TYPE headers['X-Prpc-Timeout'] = '%dS' % timeout try: res_bytes = yield net.request_async( url='http%s://%s/prpc/%s/%s' % ( '' if req.insecure else 's', req.hostname, req.service_name, req.method_name, ), method='POST', payload=req.request_message.SerializeToString(), headers=headers, scopes=req.scopes, service_account_key=req.service_account_key, delegation_token=req.delegation_token, deadline=timeout, max_attempts=req.max_attempts or 4, response_headers=response_metadata, project_id=req.project_id, ) # Unfortunately, net module does not expose headers of HTTP 200 # responses. # Assume (HTTP OK => pRPC OK). except net.Error as ex: msg = (ex.response or '<empty>').decode('utf-8', 'ignore') # Sometime requests fail before reaching the pRPC server. We recognize few # such cases. if 'X-Prpc-Grpc-Code' not in ex.headers: if ex.status_code == 500: raise RpcError(msg, codes.StatusCode.INTERNAL, ex.headers) if ex.status_code == 503: raise RpcError(msg, codes.StatusCode.UNAVAILABLE, ex.headers) # Otherwise it must be a reply from the server with a valid code header. try: code = codes.INT_TO_CODE[int(ex.headers['X-Prpc-Grpc-Code'])] except (ValueError, KeyError, TypeError): raise ProtocolError( 'response does not contain a valid X-Prpc-Grpc-Code header, ' 'its body: %r' % msg) raise RpcError(msg, code, ex.headers) # Status code is OK. # Parse the response and return it. res = req.response_message res.ParseFromString(res_bytes) try: encoding.decode_bin_metadata(response_metadata) except ValueError as ve: raise ProtocolError(ve.message) raise ndb.Return(res)