-
Notifications
You must be signed in to change notification settings - Fork 0
Low Level Client
Our low-level clients provide simple, reliable connection to raw HTTP for previews and advanced usage. We provide caller send_request
on the client to send requests to the service.
Calls through this method fully harness the power of azure-core
and azure-identity
. We provide both synchronous and asynchronous low-level clients.
The basic structure of calls with low-level clients is:
We will go into each step in the following sections
First you import your client from the namespace of your package. For example, let's say your namespace is azure.pets
and your client's name
is PetsClient
. Your import would look like
from azure.pets import PetsClient
Most clients require authenticating through their credential
parameter. Depending on what authentication support your library is using, you can either authenticate-with-aad or authenticate with an AzureKeyCredential
.
Additionally, most of our clients accept an endpoint
parameter at initialization, usually a link to your own resource.
Depending on your library, our clients support authenticating with an Azure Active Directory (AAD) token credential. We always recommend
using a credential type obtained from the azure-identity
library for AAD authentication. For this example,
we use the most common DefaultAzureCredential
.
As an installation note, the azure-identity
library is not a dependency of this library. Please pip install azure-identity
before using AAD authentication
pip install azure-identity
The following code snippet shows you how to authenticate with a DefaultAzureCredential
.
from azure.identity import DefaultAzureCredential
from azure.pets import PetsClient
client = PetsClient(
endpoint="https://myPets",
credential=DefaultAzureCredential()
)
Authenticating with AzureKeyCredential
Some libraries support authenticating with an AzureKeyCredential
. The following code snippet shows you how to authenticate with an
AzureKeyCredential
from azure.core.credentials import AzureKeyCredential
from azure.pets import PetsClient
credential: str = "myCredential"
client = PetsClient(
endpoint="https://myPets",
credential=AzureKeyCredential(credential)
)
Next, you need to create the request you want to be sent to the service.
You have two options here: create the HttpRequest
fully by yourself, or enlist the help of our request preparers.
When creating your HttpRequest
, always refer to your service's REST API docs to see what they should look like.
Creating an HttpRequest
by yourself offers you the most flexibility, and is always a great fallback option.
One thing to note for the url
you pass to your request: it can either by absolute, or you can pass in a relative url.
Relative urls will be relative to the endpoint
parameter you pass your client.
Below is a code
example for how to create an HttpRequest
. Here we POST
a json
body to a service's 3.0
endpoint.
from azure.core.pipeline.transport import HttpRequest
# Can use any of the following urls, the request will end up the same
# Relative urls are relative to the `endpoint` param you pass your client
absolute_url = "https://myPets/v3.0/cutePets"
relative_url = "/v3.0/cutePets"
request = HttpRequest("POST", relative_url,
json={
"pets": [
{
"name": "Fido",
"age": 42,
"favoriteFood": "meat"
},
{
"name": "Bessie",
"age": 1,
"favoriteFood": "fish"
}
]
}
)
# now we format the query parameters
request.format_parameters(
{
"petOwnerName": "azure",
}
)
We also offer request preparers to help you create requests for each of the documented endpoints. These preparers are included in the protocol
folder of our libraries. With the request preparers, we handle things like
the URL path and formatting query and header parameters. We also provide better intellisense, so you know just what to pass to our preparers.
API versions are an important part of our request preparers, so they are always tied to our request preparers. With different API versions, the arguments to your method calls may also change, so please be aware of this behavior.
We allow two ways to assert the API version you would like when using our request preparers. You can see our following code snippets and choose which one works best for you.
Let's make the same call as in the previous example.
-
Directly import the API version of the request preparers you want to use
from azure.pets.protocol.v3_0 import PetsPreparers from azure.core.pipeline.transport import HttpRequest request: HttpRequest = PetsPreparers.prepare_cute_pets( body={ "pets": [ { "name": "Fido", "age": 42, "favoriteFood": "meat" }, { "name": "Bessie", "age": 1, "favoriteFood": "fish" } ] }, pet_owner_name="azure", )
-
Import our multi-API request preparers, and pass the API version through the required positional parameter
api_version
from azure.pets.protocol import PetsPreparers from azure.core.pipeline.transport import HttpRequest request: HttpRequest = PetsPreparers.prepare_cute_pets( api_version="v3.0", body={ "pets": [ { "name": "Fido", "age": 42, "favoriteFood": "meat" }, { "name": "Bessie", "age": 1, "favoriteFood": "fish" } ] }, pet_owner_name="azure", )
Now, we pass this request to your client's send_request
method.
from azure.pets import PetsClient
from azure.core.pipeline.transport import HttpResponse
# Create your request. See above examples for how to.
response: HttpResponse = client.send_request(request)
Our send_request
call returns an HttpResponse
.
The response you get back from send_request
will not automatically raise if your response is an error.
If you wish to raise an error if your response is bad, call .raise_for_status()
on your returned
response. This will raise an exception defined in azure-core
if the response is bad.
Otherwise, nothing will happen.
If the response you get back should be a json
object, you can call .json()
on your response
to get it json
-deserialized.
Putting this all together, see our code snippets for how you can deal with your response object
response: HttpResponse = client.send_request(request)
response.raise_for_status() # raises an error if your response is not good
json_response = response.json() # get your response as a json object
# Now play with your JSON response!
We also offer a way to get a generator for streaming yor response body's data, it is method stream_download()
on your response object.
response: HttpResponse = client.send_request(request)
response.raise_for_status() # raises an error if your response is not good
# iterate over the chunks in your stream
for chunk in response.stream_download(None):
...
All of our low-level client libraries also include async clients. A lot of the code you write using sync and async clients will be the same (i.e. request preparation is completely sansio, so this portion of your code will look the same). This section will only include example code for the sections that are different
Initializing and authenticating an async client is largely the same as doing so for a sync client,
what changes is the import location. Async clients reside
in the aio
folder of the namespace.
Authenticating with Azure Active Directory (AAD) token credential also differs, as you will have to use the async version of each credential.
Below, we create an async client and authenticate with async DefaultAzureCredential
from azure.identity.aio import DefaultAzureCredential
from azure.pets.aio import PetsClient
client = PetsClient(
endpoint="https://myPets",
credential=DefaultAzureCredential()
)
Make sure to close your clients and credentials after using to avoid unclosed client sessions!
As you are making an async network call, you need to await the response of .send_request()
.
from azure.pets.aio import PetsClient
from azure.core.pipeline.transport import AsyncHttpResponse
# Create your request. See above examples for how to.
response: AsyncHttpResponse = await client.send_request(request)
The main difference between sync and async response handling is the need to first load the whole response so following sync methods can access the response's body.
response: AsyncHttpResponse = await client.send_request(request)
response.raise_for_status() # raises an error if your response is not good
await response.load_body() # loads the memory into the body, so the following sync methods can access it
json_response = response.json() # get your response as a json object
# Now play with your JSON response!
Async stream downloading differs from sync stream downloading, as users have to asynchronously loop over the chunks in your stream. This is because async network calls will be made to retrieve your chunks.
response: AsyncHttpResponse = await client.send_request(request)
response.raise_for_status() # raises an error if your response is not good
# iterate over the chunks in your stream
async for chunk in response.stream_download(None):
...
All errors thrown by .raise_for_error()
are exceptions defined in azure-core
.
Our low-level clients also have logging support. They use the standard logging library for logging. Basic information about HTTP sessions (URLs, headers, etc.) is logged at INFO level.
Detailed DEBUG level logging, including request/response bodies and un-redacted
headers, can be enabled on a client with the logging_enable
keyword argument.
from azure.identity import DefaultAzureCredential
from azure.pets import PetsClient
client = PetsClient(
endpoint="https://myPets",
credential=DefaultAzureCredential(),
logging_enable=True
)