def _create_request_message(self, http_method, location_id, route_values=None, query_parameters=None): location = self._get_organization_resource_location(location_id) deployment_level = False deployment_url = None if location is None: logger.debug('API resource location ' + location_id + ' is not registered on ' + self.config.base_url + '.') deployment_url = self._get_deployment_url() if deployment_url is not None: logger.debug('Checking for location at deployment level: ' + deployment_url) location = self._get_resource_location(deployment_url, location_id) deployment_level = True if location is None: raise ValueError('API resource location ' + location_id + ' is not registered on ' + self.config.base_url + '.') if route_values is None: route_values = {} route_values['area'] = location.area route_values['resource'] = location.resource_name route_template = self._remove_optional_route_parameters(location.route_template, route_values) logger.debug('Route template: %s', location.route_template) if not deployment_level: url = self._client.format_url(route_template, **route_values) else: url = self._client.format_url(deployment_url + route_template, **route_values) request = ClientRequest(method=http_method, url=url) if query_parameters: request.format_parameters(query_parameters) return request
def test_request_url_with_params(self): request = ClientRequest('GET', '/') request.url = "a/b/c?t=y" request.format_parameters({'g': 'h'}) self.assertIn(request.url, ['a/b/c?g=h&t=y', 'a/b/c?t=y&g=h'])
def test_request_data(self): request = ClientRequest('GET', '/') data = "Lots of dataaaa" request.add_content(data) self.assertEqual(request.data, json.dumps(data)) self.assertEqual(request.headers.get('Content-Length'), '17')
def _get_resource_locations(self, all_host_types): # Check local client's cached Options first if all_host_types: if self._all_host_types_locations is not None: return self._all_host_types_locations elif self._locations is not None: return self._locations # Next check for options cached on disk if not all_host_types and OPTIONS_FILE_CACHE[self.normalized_url]: try: logger.debug('File cache hit for options on: %s', self.normalized_url) self._locations = self._base_deserialize.deserialize_data( OPTIONS_FILE_CACHE[self.normalized_url], '[ApiResourceLocation]') return self._locations except DeserializationError as ex: logger.debug(ex, exc_info=True) else: logger.debug('File cache miss for options on: %s', self.normalized_url) # Last resort, make the call to the server options_uri = self._combine_url(self.config.base_url, '_apis') request = ClientRequest(method='OPTIONS', url=self._client.format_url(options_uri)) if all_host_types: query_parameters = {'allHostTypes': True} request.format_parameters(query_parameters) headers = {'Accept': 'application/json'} if self._suppress_fedauth_redirect: headers['X-TFS-FedAuthRedirect'] = 'Suppress' if self._force_msa_pass_through: headers['X-VSS-ForceMsaPassThrough'] = 'true' response = self._send_request(request, headers=headers) wrapper = self._base_deserialize('VssJsonCollectionWrapper', response) if wrapper is None: raise VstsClientRequestError( "Failed to retrieve resource locations from: {}".format( options_uri)) collection = wrapper.value returned_locations = self._base_deserialize('[ApiResourceLocation]', collection) if all_host_types: self._all_host_types_locations = returned_locations else: self._locations = returned_locations try: OPTIONS_FILE_CACHE[self.normalized_url] = wrapper.value except SerializationError as ex: logger.debug(ex, exc_info=True) return returned_locations
def test_format_data(self): data = ClientRequest._format_data(None) self.assertEqual(data, (None, None)) data = ClientRequest._format_data("Test") self.assertEqual(data, (None, "Test")) mock_stream = mock.create_autospec(io.BytesIO) data = ClientRequest._format_data(mock_stream) self.assertEqual(data, (None, mock_stream, "application/octet-stream")) mock_stream.name = "file_name" data = ClientRequest._format_data(mock_stream) self.assertEqual(data, ("file_name", mock_stream, "application/octet-stream"))
def _create_request_message(self, http_method, location_id, route_values=None, query_parameters=None): location = self._get_resource_location(location_id) if location is None: raise ValueError('API resource location ' + location_id + ' is not registered on ' + self.config.base_url + '.') if route_values is None: route_values = {} route_values['area'] = location.area route_values['resource'] = location.resource_name url = self._transform_route_template(location.route_template, route_values) logger.debug('Route template: %s', location.route_template) request = ClientRequest(method=http_method, url=self._client.format_url(url)) if query_parameters: request.format_parameters(query_parameters) return request
async def test_basic_async_requests(): request = ClientRequest("GET", "http://bing.com") async with AsyncBasicRequestsHTTPSender() as sender: response = await sender.send(request) assert response.body() is not None assert response.status_code == 200
async def do(): conf = Configuration("http://bing.com/") request = ClientRequest("GET", "http://bing.com/") policies = [ UserAgentPolicy("myusergant") ] async with AsyncPipeline(policies, AsyncPipelineRequestsHTTPSender(AsyncTrioRequestsHTTPSender(conf))) as pipeline: return await pipeline.run(request)
async def test_conf_async_requests(): conf = Configuration("http://bing.com/") request = ClientRequest("GET", "http://bing.com/") async with AsyncRequestsHTTPSender(conf) as sender: response = await sender.send(request) assert response.body() is not None assert response.status_code == 200
async def test_basic_aiohttp(): request = ClientRequest("GET", "http://bing.com") async with AioHTTPSender() as sender: response = await sender.send(request) assert response.body() is not None assert sender._session.closed assert response.status_code == 200
def test_user_agent(): with mock.patch.dict('os.environ', {'AZURE_HTTP_USER_AGENT': "mytools"}): policy = UserAgentPolicy() assert policy.user_agent.endswith("mytools") request = ClientRequest('GET', 'http://127.0.0.1/') policy.on_request(Request(request)) assert request.headers["user-agent"].endswith("mytools")
def get_vsts_info(self, relative_remote_url): url = self._client.format_url(relative_remote_url.rstrip('/') + '/vsts/info') request = ClientRequest(method='GET', url=url) headers = {'Accept': 'application/json'} if self._suppress_fedauth_redirect: headers['X-TFS-FedAuthRedirect'] = 'Suppress' if self._force_msa_pass_through: headers['X-VSS-ForceMsaPassThrough'] = 'true' response = self._send_request(request, headers) return self._deserialize('VstsInfo', response)
async def test_basic_async_requests(): request = ClientRequest("GET", "http://bing.com") policies = [ UserAgentPolicy("myusergant") ] async with AsyncPipeline(policies, AsyncPipelineRequestsHTTPSender()) as pipeline: response = await pipeline.run(request) assert response.http_response.status_code == 200
def get_vsts_info_by_remote_url(remote_url, credentials, suppress_fedauth_redirect=True): request = ClientRequest(method='GET', url=remote_url.rstrip('/') + '/vsts/info') headers = {'Accept': 'application/json'} if suppress_fedauth_redirect: headers['X-TFS-FedAuthRedirect'] = 'Suppress' git_client = GitClient(base_url=remote_url, creds=credentials) response = git_client._send_request(request, headers) return git_client._deserialize('VstsInfo', response)
async def test_conf_async_requests(): conf = Configuration("http://bing.com/") request = ClientRequest("GET", "http://bing.com/") policies = [ UserAgentPolicy("myusergant") ] async with AsyncPipeline(policies, AsyncPipelineRequestsHTTPSender(AsyncRequestsHTTPSender(conf))) as pipeline: response = await pipeline.run(request) assert response.http_response.status_code == 200
async def test_basic_aiohttp(): request = ClientRequest("GET", "http://bing.com") policies = [ UserAgentPolicy("myusergant") ] async with AsyncPipeline(policies) as pipeline: response = await pipeline.run(request) assert pipeline._sender.driver._session.closed assert response.http_response.status_code == 200
def test_max_retries_on_default_adapter(): # max_retries must be applied only on the default adapters of requests # If the user adds its own adapter, don't touch it cfg = RequestHTTPSenderConfiguration() max_retries = cfg.retry_policy() with RequestsHTTPSender(cfg) as driver: request = ClientRequest('GET', '/') driver.session.mount('"http://127.0.0.1/"', HTTPAdapter()) driver._configure_send(request) assert driver.session.adapters["http://"].max_retries is max_retries assert driver.session.adapters["https://"].max_retries is max_retries assert driver.session.adapters[ '"http://127.0.0.1/"'].max_retries is not max_retries
def _initialize_repo(self, org, project, path, attachments): search_path = (path + '/README.md').lower().replace('\\', '/') readme_path = list( filter(lambda x: x.replace('\\', '/').lower() == search_path, attachments)) if len(readme_path) == 1: fs = helpers.FileSystem() content = fs.read_file(readme_path[0]) git_client = self.clients.get_git_client() repo = git_client.get_repositories(project.id)[0] ref_update = GitRefUpdate( name="refs/heads/master", old_object_id="0000000000000000000000000000000000000000", repository_id=repo.id) changes = [{ "changeType": "add", "item": { "path": "/README.md" }, "newContent": { "content": content, "contentType": "rawtext" } }] commit = GitCommit(comment="Initial commit.", changes=changes) push = GitPush(commits=[commit], ref_updates=[ref_update], repository=repo) git_client.create_push(push, repo.id) headers = {"content-type": "application/json; charset=utf-8'"} client_request = ClientRequest( "PATCH", f'https://dev.azure.com/{org}/_apis/Settings/project/{project.id}/Entries/host?api-version=5.1-preview.1' ) payload = { "VersionControl/ProjectOverview/DefaultRepository": repo.id } response = self.connection._client.send(request=client_request, headers=headers, content=payload) return response
def test_session_callback(): cfg = RequestHTTPSenderConfiguration() with RequestsHTTPSender(cfg) as driver: def callback(session, global_config, local_config, **kwargs): assert session is driver.session assert global_config is cfg assert local_config["test"] my_kwargs = kwargs.copy() my_kwargs.update({'used_callback': True}) return my_kwargs cfg.session_configuration_callback = callback request = ClientRequest('GET', 'http://127.0.0.1/') output_kwargs = driver._configure_send(request, **{"test": True}) assert output_kwargs['used_callback']
def test_no_log(mock_http_logger): universal_request = ClientRequest('GET', 'http://127.0.0.1/') request = Request(universal_request) http_logger = HTTPLogger() response = Response(request, ClientResponse(universal_request, None)) # By default, no log handler for HTTP http_logger.on_request(request) mock_http_logger.debug.assert_not_called() http_logger.on_response(request, response) mock_http_logger.debug.assert_not_called() mock_http_logger.reset_mock() # I can enable it per request http_logger.on_request(request, **{"enable_http_logger": True}) assert mock_http_logger.debug.call_count >= 1 http_logger.on_response(request, response, **{"enable_http_logger": True}) assert mock_http_logger.debug.call_count >= 1 mock_http_logger.reset_mock() # I can enable it per request (bool value should be honored) http_logger.on_request(request, **{"enable_http_logger": False}) mock_http_logger.debug.assert_not_called() http_logger.on_response(request, response, **{"enable_http_logger": False}) mock_http_logger.debug.assert_not_called() mock_http_logger.reset_mock() # I can enable it globally http_logger.enable_http_logger = True http_logger.on_request(request) assert mock_http_logger.debug.call_count >= 1 http_logger.on_response(request, response) assert mock_http_logger.debug.call_count >= 1 mock_http_logger.reset_mock() # I can enable it globally and override it locally http_logger.enable_http_logger = True http_logger.on_request(request, **{"enable_http_logger": False}) mock_http_logger.debug.assert_not_called() http_logger.on_response(request, response, **{"enable_http_logger": False}) mock_http_logger.debug.assert_not_called() mock_http_logger.reset_mock()
def test_sans_io_exception(): class BrokenSender(HTTPSender): def send(self, request, **config): raise ValueError("Broken") def __exit__(self, exc_type, exc_value, traceback): """Raise any exception triggered within the runtime context.""" return None pipeline = Pipeline([SansIOHTTPPolicy()], BrokenSender()) req = ClientRequest('GET', '/') with pytest.raises(ValueError): pipeline.run(req) class SwapExec(SansIOHTTPPolicy): def on_exception(self, requests, **kwargs): exc_type, exc_value, exc_traceback = sys.exc_info() raise NotImplementedError(exc_value) pipeline = Pipeline([SwapExec()], BrokenSender()) with pytest.raises(NotImplementedError): pipeline.run(req)
async def do(): conf = Configuration("http://bing.com/") request = ClientRequest("GET", "http://bing.com/") async with AsyncTrioRequestsHTTPSender(conf) as sender: return await sender.send(request) assert response.body() is not None
def test_client_formdata_add(self, format_data): format_data.return_value = "formatted" request = ClientRequest('GET', '/') request.add_formdata() assert request.files == {} request = ClientRequest('GET', '/') request.add_formdata({'Test':'Data'}) assert request.files == {'Test':'formatted'} request = ClientRequest('GET', '/') request.headers = {'Content-Type':'1234'} request.add_formdata({'1':'1', '2':'2'}) assert request.files == {'1':'formatted', '2':'formatted'} request = ClientRequest('GET', '/') request.headers = {'Content-Type':'1234'} request.add_formdata({'1':'1', '2':None}) assert request.files == {'1':'formatted'} request = ClientRequest('GET', '/') request.headers = {'Content-Type':'application/x-www-form-urlencoded'} request.add_formdata({'1':'1', '2':'2'}) assert request.files is None assert request.data == {'1':'1', '2':'2'} request = ClientRequest('GET', '/') request.headers = {'Content-Type':'application/x-www-form-urlencoded'} request.add_formdata({'1':'1', '2':None}) assert request.files is None assert request.data == {'1':'1'}
def test_client_send(self): current_ua = self.cfg.user_agent client = ServiceClient(self.creds, self.cfg) client.config.keep_alive = True req_response = requests.Response() req_response._content = br'{"real": true}' # Has to be valid bytes JSON req_response._content_consumed = True req_response.status_code = 200 def side_effect(*args, **kwargs): return req_response session = mock.create_autospec(requests.Session) session.request.side_effect = side_effect session.adapters = { "http://": HTTPAdapter(), "https://": HTTPAdapter(), } # Be sure the mock does not trick me assert not hasattr(session.resolve_redirects, 'is_msrest_patched') client.config.pipeline._sender.driver.session = session client.config.credentials.signed_session.return_value = session client.config.credentials.refresh_session.return_value = session request = ClientRequest('GET', '/') client.send(request, stream=False) session.request.call_count = 0 session.request.assert_called_with( 'GET', '/', allow_redirects=True, cert=None, headers={ 'User-Agent': current_ua, 'Test': 'true' # From global config }, stream=False, timeout=100, verify=True ) assert session.resolve_redirects.is_msrest_patched client.send(request, headers={'id':'1234'}, content={'Test':'Data'}, stream=False) session.request.assert_called_with( 'GET', '/', data='{"Test": "Data"}', allow_redirects=True, cert=None, headers={ 'User-Agent': current_ua, 'Content-Length': '16', 'id':'1234', 'Test': 'true' # From global config }, stream=False, timeout=100, verify=True ) self.assertEqual(session.request.call_count, 1) session.request.call_count = 0 assert session.resolve_redirects.is_msrest_patched session.request.side_effect = requests.RequestException("test") with self.assertRaises(ClientRequestError): client.send(request, headers={'id':'1234'}, content={'Test':'Data'}, test='value', stream=False) session.request.assert_called_with( 'GET', '/', data='{"Test": "Data"}', allow_redirects=True, cert=None, headers={ 'User-Agent': current_ua, 'Content-Length': '16', 'id':'1234', 'Test': 'true' # From global config }, stream=False, timeout=100, verify=True ) self.assertEqual(session.request.call_count, 1) session.request.call_count = 0 assert session.resolve_redirects.is_msrest_patched session.request.side_effect = oauth2.rfc6749.errors.InvalidGrantError("test") with self.assertRaises(TokenExpiredError): client.send(request, headers={'id':'1234'}, content={'Test':'Data'}, test='value') self.assertEqual(session.request.call_count, 2) session.request.call_count = 0 session.request.side_effect = ValueError("test") with self.assertRaises(ValueError): client.send(request, headers={'id':'1234'}, content={'Test':'Data'}, test='value')
def search_extensions(search_query): """ Search extensions from marketplace """ from msrest.universal_http import ClientRequest from msrest.service_client import ServiceClient from msrest import Configuration from azext_devops.version import VERSION config = Configuration(base_url=None) config.add_user_agent('devOpsCli/{}'.format(VERSION)) client = ServiceClient(creds=None, config=config) request = ClientRequest( method='POST', url= 'https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery' ) search_request = { 'assetTypes': [ 'Microsoft.VisualStudio.Services.Icons.Default', 'Microsoft.VisualStudio.Services.Icons.Branding', 'Microsoft.VisualStudio.Services.Icons.Small' ], 'filters': [{ 'criteria': [{ 'filterType': 8, 'value': 'Microsoft.VisualStudio.Services' }, { 'filterType': 8, 'value': 'Microsoft.VisualStudio.Services.Integration' }, { 'filterType': 8, 'value': 'Microsoft.VisualStudio.Services.Cloud' }, { 'filterType': 8, 'value': 'Microsoft.TeamFoundation.Server' }, { 'filterType': 8, 'value': 'Microsoft.TeamFoundation.Server.Integration' }, { 'filterType': 8, 'value': 'Microsoft.VisualStudio.Services.Cloud.Integration' }, { 'filterType': 8, 'value': 'Microsoft.VisualStudio.Services.Resource.Cloud' }, { 'filterType': 10, 'value': search_query }, { 'filterType': 12, 'value': '37888' }], 'direction': 2, 'pageSize': 50, 'pageNumber': 1, 'sortBy': 0, 'sortOrder': 0, 'pagingToken': None }], 'flags': 870 } headers = { 'Content-Type': 'application/json' + '; charset=utf-8', 'Accept': 'application/json' + ';api-version=' + '5.0-preview.1' } response = client.send(request=request, headers=headers, content=search_request) response_json = response.json() return response_json['results'][0]['extensions']
def test_request_xml(self): request = ClientRequest('GET', '/') data = ET.Element("root") request.add_content(data) assert request.data == b"<?xml version='1.0' encoding='utf8'?>\n<root />"