Chamar as operações da API REST com a autorização de Chave Partilhada

Este artigo mostra como chamar uma operação da API REST do Armazenamento do Azure criando uma solicitação REST autorizada usando C#. Depois de aprender a chamar uma operação de API REST para o Armazenamento de Blob, você pode usar etapas semelhantes para qualquer outra operação REST do Armazenamento do Azure.

Pré-requisitos

O aplicativo de exemplo lista os contêineres de blob para uma conta de armazenamento. Para experimentar o código neste artigo, você precisa dos seguintes itens:

  • Instale o Visual Studio e inclua a carga de trabalho de desenvolvimento do Azure. Este exemplo foi criado usando o Visual Studio 2019. Se você usar uma versão diferente, a orientação pode variar um pouco.

  • Uma subscrição do Azure. Se não tiver uma subscrição do Azure, crie uma conta gratuita antes de começar.

  • Uma conta de armazenamento de uso geral. Se ainda não tiver uma conta de armazenamento, consulte Criar uma conta de armazenamento.

  • O exemplo neste artigo mostra como listar os contêineres em uma conta de armazenamento. Para ver a saída, adicione alguns contêineres de blob à conta de armazenamento antes de começar.

Transferir a aplicação de exemplo

O aplicativo de exemplo é um aplicativo de console escrito em C#.

Utilize o git para transferir uma cópia da aplicação para o seu ambiente de desenvolvimento.

git clone https://github.com/Azure-Samples/storage-dotnet-rest-api-with-auth.git

Este comando clona o repositório para a sua pasta local do git. Para abrir a solução Visual Studio, navegue até a pasta storage-dotnet-rest-api-with-auth e abra StorageRestApiAuth.sln.

Sobre o REST

A Transferência de Estado Representacional (REST) é uma arquitetura que permite interagir com um serviço através de um protocolo de Internet, como HTTP/HTTPS. O REST é independente do software em execução no servidor ou no cliente. A API REST pode ser chamada de qualquer plataforma que suporte HTTP/HTTPS. Você pode escrever um aplicativo que seja executado em um Mac, Windows, Linux, um telefone ou tablet Android, iPhone, iPod ou site e usar a mesma API REST para todas essas plataformas.

Uma chamada para a API REST consiste em uma solicitação feita pelo cliente e uma resposta retornada pelo serviço. Na solicitação, você envia uma URL com informações sobre qual operação deseja chamar, o recurso no qual agir, quaisquer parâmetros e cabeçalhos de consulta e, dependendo da operação que foi chamada, uma carga de dados. A resposta do serviço inclui um código de status, um conjunto de cabeçalhos de resposta e, dependendo da operação que foi chamada, uma carga útil de dados.

Sobre o aplicativo de exemplo

O aplicativo de exemplo lista os contêineres em uma conta de armazenamento. Depois de entender como as informações na documentação da API REST se correlacionam com seu código real, outras chamadas REST são mais fáceis de descobrir.

Se você examinar a API REST do Serviço de Blob, verá todas as operações que pode ser executada no armazenamento de blobs. As bibliotecas de cliente de armazenamento são wrappers em torno das APIs REST, facilitando o acesso aos recursos de armazenamento sem usar as APIs REST diretamente. Às vezes, no entanto, você pode querer usar a API REST em vez de uma biblioteca de cliente de armazenamento.

Operação Listar contêineres

Este artigo concentra-se na operação Listar contêineres . As informações a seguir ajudam você a entender alguns dos campos na solicitação e na resposta.

Método de solicitação: GET. Este verbo é o método HTTP especificado como uma propriedade do objeto de solicitação. Outros valores para esse verbo incluem HEAD, PUT e DELETE, dependendo da API que você está chamando.

Solicitar URI:https://myaccount.blob.core.windows.net/?comp=list . O URI de solicitação é criado a partir do ponto de extremidade https://myaccount.blob.core.windows.net da conta de armazenamento de blob e da cadeia de caracteres /?comp=listde recurso.

Parâmetros de URI: Há parâmetros de consulta adicionais que você pode usar ao chamar ListContainers. Alguns desses parâmetros são o tempo limite para a chamada (em segundos) e o prefixo, que é usado para filtragem.

Outro parâmetro útil é maxresults: se houver mais contêineres disponíveis do que esse valor, o corpo da resposta conterá um elemento NextMarker que indica o próximo contêiner a ser retornado na próxima solicitação. Para usar esse recurso, forneça o valor NextMarker como o parâmetro de marcador no URI quando fizer a próxima solicitação. Ao usar esse recurso, ele é análogo à paginação através dos resultados.

Para usar parâmetros adicionais, acrescente-os à cadeia de caracteres de recurso com o valor, como este exemplo:

/?comp=list&timeout=60&maxresults=100

Cabeçalhos de solicitação: esta seção lista os cabeçalhos de solicitação obrigatórios e opcionais. Três dos cabeçalhos são necessários: um cabeçalho de autorização , x-ms-date (contém a hora UTC para a solicitação) e x-ms-version (especifica a versão da API REST a ser usada). A inclusão de x-ms-client-request-id nos cabeçalhos é opcional. Você pode definir o valor desse campo como qualquer coisa, e ele é gravado nos logs de análise de armazenamento quando o registro em log está habilitado.

Corpo da solicitação: Não há nenhum corpo de solicitação para ListContainers. Request Body é usado em todas as operações PUT ao carregar blobs, incluindo SetContainerAccessPolicy. O Corpo da Solicitação permite que você envie uma lista XML de políticas de acesso armazenadas a serem aplicadas. As políticas de acesso armazenado são discutidas no artigo Usando assinaturas de acesso compartilhado (SAS).

Código de status da resposta: informa sobre todos os códigos de status que você precisa saber. Neste exemplo, um código de status HTTP de 200 é ok. Para obter uma lista completa de códigos de status HTTP, confira Definições de código de status. Para ver códigos de erro específicos para as APIs REST de armazenamento, consulte Códigos de erro comuns da API REST

Cabeçalhos de resposta: incluem Tipo de conteúdo; x-ms-request-id, que é o ID de solicitação que você passou; x-ms-version, que indica a versão do serviço de Blob usada; e a Data, que está em UTC e informa a que horas o pedido foi feito.

Corpo da resposta: Este campo é uma estrutura XML que fornece os dados solicitados. Neste exemplo, a resposta é uma lista de contêineres e suas propriedades.

Criando a solicitação REST

Para segurança ao executar em produção, use sempre HTTPS em vez de HTTP. Para os fins deste exercício, usamos HTTP para que você possa visualizar os dados de solicitação e resposta. Para visualizar as informações de solicitação e resposta nas chamadas REST reais, você pode baixar o Fiddler ou um aplicativo semelhante. Na solução Visual Studio, o nome da conta de armazenamento e a chave são codificados na classe. O método ListContainersAsyncREST passa o nome da conta de armazenamento e a chave da conta de armazenamento para os métodos usados para criar os vários componentes da solicitação REST. Em um aplicativo do mundo real, o nome e a chave da conta de armazenamento residiriam em um arquivo de configuração, variáveis de ambiente ou seriam recuperados de um Cofre de Chaves do Azure.

Em nosso projeto de exemplo, o código para criar o cabeçalho Authorization está em uma classe separada. A ideia é que você possa pegar toda a aula e adicioná-la à sua própria solução e usá-la "como está". O código de cabeçalho Authorization funciona para a maioria das chamadas de API REST para o Armazenamento do Azure.

Para criar a solicitação, que é um objeto HttpRequestMessage, vá para ListContainersAsyncREST em Program.cs. As etapas para criar a solicitação são:

  • Crie o URI a ser usado para chamar o serviço.
  • Crie o objeto HttpRequestMessage e defina a carga útil. A carga útil é nula para ListContainersAsyncREST porque não estamos passando nada.
  • Adicione os cabeçalhos de solicitação para x-ms-date e x-ms-version.
  • Obtenha o cabeçalho de autorização e adicione-o.

Algumas informações básicas que você precisa:

  • Para ListContainers, o método é GET. Esse valor é definido ao instanciar a solicitação.
  • O recurso é a parte de consulta do URI que indica qual API está sendo chamada, portanto, o valor é /?comp=list. Como observado anteriormente, o recurso está na página de documentação de referência que mostra as informações sobre a API ListContainers.
  • O URI é construído criando o ponto de extremidade do serviço Blob para essa conta de armazenamento e concatenando o recurso. O valor para URI de solicitação acaba sendo http://contosorest.blob.core.windows.net/?comp=list.
  • Para ListContainers, requestBody é null e não há cabeçalhos extras.

APIs diferentes podem ter outros parâmetros para transmitir, como ifMatch. Um exemplo de onde você pode usar ifMatch é ao chamar PutBlob. Nesse caso, você define ifMatch como uma eTag e ela só atualiza o blob se a eTag fornecida corresponder à eTag atual no blob. Se outra pessoa tiver atualizado o blob desde a recuperação da eTag, a alteração não será substituída.

Primeiro, defina o e o urirequestPayload.

// Construct the URI. It will look like this:
//   https://myaccount.blob.core.windows.net/resource
String uri = string.Format("http://{0}.blob.core.windows.net?comp=list", storageAccountName);

// Provide the appropriate payload, in this case null.
//   we're not passing anything in.
Byte[] requestPayload = null;

Em seguida, instancie a solicitação, definindo o método e GET fornecendo o URI.

// Instantiate the request message with a null payload.
using (var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, uri)
{ Content = (requestPayload == null) ? null : new ByteArrayContent(requestPayload) })
{

Adicione os cabeçalhos de solicitação para x-ms-date e x-ms-version. Este lugar no código também é onde você adiciona quaisquer cabeçalhos de solicitação adicionais necessários para a chamada. Neste exemplo, não há cabeçalhos adicionais. Um exemplo de uma API que passa cabeçalhos extras é a operação set Container ACL. Esta chamada de API adiciona um cabeçalho chamado "x-ms-blob-public-access" e o valor para o nível de acesso.

// Add the request headers for x-ms-date and x-ms-version.
DateTime now = DateTime.UtcNow;
httpRequestMessage.Headers.Add("x-ms-date", now.ToString("R", CultureInfo.InvariantCulture));
httpRequestMessage.Headers.Add("x-ms-version", "2017-07-29");
// If you need any additional headers, add them here before creating
//   the authorization header.

Chame o método que cria o cabeçalho de autorização e adicione-o aos cabeçalhos de solicitação. O cabeçalho de autorização é criado posteriormente no artigo. O nome do método é GetAuthorizationHeader, que você pode ver neste trecho de código:

// Get the authorization header and add it.
httpRequestMessage.Headers.Authorization = AzureStorageAuthenticationHelper.GetAuthorizationHeader(
    storageAccountName, storageAccountKey, now, httpRequestMessage);

Neste ponto, httpRequestMessage contém a solicitação REST completa com os cabeçalhos de autorização.

Enviar o pedido

Agora que você construiu a solicitação, pode chamar o método SendAsync para enviá-la ao Armazenamento do Azure. Verifique se o valor do código de status da resposta é 200, o que significa que a operação foi bem-sucedida. Em seguida, analise a resposta. Nesse caso, você obtém uma lista XML de contêineres. Vamos examinar o código para chamar o método GetRESTRequest para criar a solicitação, executar a solicitação e, em seguida, examinar a resposta para a lista de contêineres.

    // Send the request.
    using (HttpResponseMessage httpResponseMessage =
      await new HttpClient().SendAsync(httpRequestMessage, cancellationToken))
    {
        // If successful (status code = 200),
        //   parse the XML response for the container names.
        if (httpResponseMessage.StatusCode == HttpStatusCode.OK)
        {
            String xmlString = await httpResponseMessage.Content.ReadAsStringAsync();
            XElement x = XElement.Parse(xmlString);
            foreach (XElement container in x.Element("Containers").Elements("Container"))
            {
                Console.WriteLine("Container name = {0}", container.Element("Name").Value);
            }
        }
    }
}

Se você executar um sniffer de rede, como o Fiddler , ao fazer a chamada para o SendAsync, poderá ver as informações de solicitação e resposta. Vamos dar uma vista de olhos. O nome da conta de armazenamento é contosorest.

Pedido:

GET /?comp=list HTTP/1.1

Cabeçalhos de solicitação:

x-ms-date: Thu, 16 Nov 2017 23:34:04 GMT
x-ms-version: 2014-02-14
Authorization: SharedKey contosorest:1dVlYJWWJAOSHTCPGiwdX1rOS8B4fenYP/VrU0LfzQk=
Host: contosorest.blob.core.windows.net
Connection: Keep-Alive

Código de status e cabeçalhos de resposta retornados após a execução:

HTTP/1.1 200 OK
Content-Type: application/xml
Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: 3e889876-001e-0039-6a3a-5f4396000000
x-ms-version: 2017-07-29
Date: Fri, 17 Nov 2017 00:23:42 GMT
Content-Length: 1511

Corpo da resposta (XML): Para a operação Listar Contêineres, isso mostra a lista de contêineres e suas propriedades.

<?xml version="1.0" encoding="utf-8"?>
<EnumerationResults
  ServiceEndpoint="http://contosorest.blob.core.windows.net/">
  <Containers>
    <Container>
      <Name>container-1</Name>
      <Properties>
        <Last-Modified>Thu, 16 Mar 2017 22:39:48 GMT</Last-Modified>
        <Etag>"0x8D46CBD5A7C301D"</Etag>
        <LeaseStatus>unlocked</LeaseStatus>
        <LeaseState>available</LeaseState>
      </Properties>
    </Container>
    <Container>
      <Name>container-2</Name>
      <Properties>
        <Last-Modified>Thu, 16 Mar 2017 22:40:50 GMT</Last-Modified>
        <Etag>"0x8D46CBD7F49E9BD"</Etag>
        <LeaseStatus>unlocked</LeaseStatus>
        <LeaseState>available</LeaseState>
      </Properties>
    </Container>
    <Container>
      <Name>container-3</Name>
      <Properties>
        <Last-Modified>Thu, 16 Mar 2017 22:41:10 GMT</Last-Modified>
        <Etag>"0x8D46CBD8B243D68"</Etag>
        <LeaseStatus>unlocked</LeaseStatus>
        <LeaseState>available</LeaseState>
      </Properties>
    </Container>
    <Container>
      <Name>container-4</Name>
      <Properties>
        <Last-Modified>Thu, 16 Mar 2017 22:41:25 GMT</Last-Modified>
        <Etag>"0x8D46CBD93FED46F"</Etag>
        <LeaseStatus>unlocked</LeaseStatus>
        <LeaseState>available</LeaseState>
        </Properties>
      </Container>
      <Container>
        <Name>container-5</Name>
        <Properties>
          <Last-Modified>Thu, 16 Mar 2017 22:41:39 GMT</Last-Modified>
          <Etag>"0x8D46CBD9C762815"</Etag>
          <LeaseStatus>unlocked</LeaseStatus>
          <LeaseState>available</LeaseState>
        </Properties>
      </Container>
  </Containers>
  <NextMarker />
</EnumerationResults>

Agora que você entende como criar a solicitação, chamar o serviço e analisar os resultados, vamos ver como criar o cabeçalho de autorização.

Criando o cabeçalho de autorização

Gorjeta

O Armazenamento do Azure dá suporte à integração do Microsoft Entra para blobs e filas. O Microsoft Entra ID oferece uma experiência muito mais simples para autorizar uma solicitação ao Armazenamento do Azure. Para obter mais informações sobre como usar o Microsoft Entra ID para autorizar operações REST, consulte Autorizar com o Microsoft Entra ID. Para obter uma visão geral da integração do Microsoft Entra com o Armazenamento do Azure, consulte Autenticar o acesso ao Armazenamento do Azure usando a ID do Microsoft Entra.

Para saber mais sobre conceitos de autorização, consulte Autorizar solicitações para o Armazenamento do Azure.

Vamos destilar esse artigo até exatamente é necessário e mostrar o código.

Primeiro, use a autorização de chave compartilhada. O formato do cabeçalho de autorização tem esta aparência:

Authorization="SharedKey <storage account name>:<signature>"  

O campo de assinatura é um código de autenticação de mensagem baseado em hash (HMAC) criado a partir da solicitação e calculado usando o algoritmo SHA256 e, em seguida, codificado usando a codificação Base64.

Este trecho de código mostra o formato da cadeia de caracteres de assinatura de chave compartilhada:

StringToSign = VERB + "\n" +  
               Content-Encoding + "\n" +  
               Content-Language + "\n" +  
               Content-Length + "\n" +  
               Content-MD5 + "\n" +  
               Content-Type + "\n" +  
               Date + "\n" +  
               If-Modified-Since + "\n" +  
               If-Match + "\n" +  
               If-None-Match + "\n" +  
               If-Unmodified-Since + "\n" +  
               Range + "\n" +  
               CanonicalizedHeaders +  
               CanonicalizedResource;  

Para armazenamento de Blob, especifique VERB, md5, comprimento do conteúdo, Cabeçalhos Canonicalizados e Recurso Canonicalizado. Você pode deixar os outros em branco para este exemplo, mas colocar \n para especificar que eles estão em branco.

A canonização é um processo de padronização de dados que tem mais de uma representação possível. Nesse caso, você está padronizando os cabeçalhos e o recurso. Os cabeçalhos canonicalizados são os cabeçalhos que começam com "x-ms-". O recurso canonicalizado é o URI do recurso, incluindo o nome da conta de armazenamento e todos os parâmetros de consulta (como ?comp=list). O recurso canonicalizado também inclui quaisquer parâmetros de consulta adicionais que você possa ter adicionado, como timeout=60, por exemplo.

Vamos começar com os dois campos canonicalizados, porque eles são necessários para criar o cabeçalho Authorization.

Cabeçalhos canonicalizados

Para criar esse valor, recupere os cabeçalhos que começam com "x-ms-" e classifique-os e, em seguida, formate-os em uma cadeia de ocorrências, concatenadas em uma cadeia de [key:value\n] caracteres. Neste exemplo, os cabeçalhos canonicalizados têm esta aparência:

x-ms-date:Fri, 17 Nov 2017 00:44:48 GMT\nx-ms-version:2017-07-29\n

Aqui está o código usado para criar essa saída:

private static string GetCanonicalizedHeaders(HttpRequestMessage httpRequestMessage)
{
    var headers = from kvp in httpRequestMessage.Headers
        where kvp.Key.StartsWith("x-ms-", StringComparison.OrdinalIgnoreCase)
        orderby kvp.Key
        select new { Key = kvp.Key.ToLowerInvariant(), kvp.Value };

    StringBuilder headersBuilder = new StringBuilder();

    foreach (var kvp in headers)
    {
        headersBuilder.Append(kvp.Key);
        char separator = ':';

        // Get the value for each header, strip out \r\n if found, then append it with the key.
        foreach (string headerValue in kvp.Value)
        {
            string trimmedValue = headerValue.TrimStart().Replace("\r\n", string.Empty);
            headersBuilder.Append(separator).Append(trimmedValue);

            // Set this to a comma; this will only be used
            // if there are multiple values for one of the headers.
            separator = ',';
        }

        headersBuilder.Append("\n");
    }

    return headersBuilder.ToString();
}

Recurso canonicalizado

Esta parte da cadeia de caracteres de assinatura representa a conta de armazenamento direcionada pela solicitação. Lembre-se de que o URI de solicitação é http://contosorest.blob.core.windows.net/?comp=list, com o nome real da conta (contosorest neste caso). Neste exemplo, isso é retornado:

/contosorest/\ncomp:list

Se você tiver parâmetros de consulta, este exemplo também incluirá esses parâmetros. Aqui está o código, que também lida com parâmetros de consulta adicionais e parâmetros de consulta com vários valores. Lembre-se de que você está criando esse código para funcionar para todas as APIs REST. Você deseja incluir todas as possibilidades, mesmo que o método ListContainers não precise de todas elas.

private static string GetCanonicalizedResource(Uri address, string storageAccountName)
{
    // The absolute path will be "/" because for we're getting a list of containers.
    StringBuilder sb = new StringBuilder("/").Append(storageAccountName).Append(address.AbsolutePath);

    // Address.Query is the resource, such as "?comp=list".
    // This ends up with a NameValueCollection with 1 entry having key=comp, value=list.
    // It will have more entries if you have more query parameters.
    NameValueCollection values = HttpUtility.ParseQueryString(address.Query);

    foreach (var item in values.AllKeys.OrderBy(k => k))
    {
        sb.Append('\n').Append(item.ToLower()).Append(':').Append(values[item]);
    }

    return sb.ToString();
}

Agora que as cadeias de caracteres canonicalizadas estão definidas, vamos ver como criar o próprio cabeçalho de autorização. Você começa criando uma cadeia de caracteres da assinatura de mensagem no formato de StringToSign exibido anteriormente neste artigo. Este conceito é mais fácil de explicar usando comentários no código, então aqui está, o método final que retorna o cabeçalho de autorização:

internal static AuthenticationHeaderValue GetAuthorizationHeader(
    string storageAccountName, string storageAccountKey, DateTime now,
    HttpRequestMessage httpRequestMessage, string ifMatch = "", string md5 = "")
{
    // This is the raw representation of the message signature.
    HttpMethod method = httpRequestMessage.Method;
    String MessageSignature = String.Format("{0}\n\n\n{1}\n{5}\n\n\n\n{2}\n\n\n\n{3}{4}",
                method.ToString(),
                (method == HttpMethod.Get || method == HttpMethod.Head) ? String.Empty
                  : httpRequestMessage.Content.Headers.ContentLength.ToString(),
                ifMatch,
                GetCanonicalizedHeaders(httpRequestMessage),
                GetCanonicalizedResource(httpRequestMessage.RequestUri, storageAccountName),
                md5);

    // Now turn it into a byte array.
    byte[] SignatureBytes = Encoding.UTF8.GetBytes(MessageSignature);

    // Create the HMACSHA256 version of the storage key.
    HMACSHA256 SHA256 = new HMACSHA256(Convert.FromBase64String(storageAccountKey));

    // Compute the hash of the SignatureBytes and convert it to a base64 string.
    string signature = Convert.ToBase64String(SHA256.ComputeHash(SignatureBytes));

    // This is the actual header that will be added to the list of request headers.
    AuthenticationHeaderValue authHV = new AuthenticationHeaderValue("SharedKey",
        storageAccountName + ":" + signature);
    return authHV;
}

Quando você executa esse código, o MessageSignature resultante se parece com este exemplo:

GET\n\n\n\n\n\n\n\n\n\n\n\nx-ms-date:Fri, 17 Nov 2017 01:07:37 GMT\nx-ms-version:2017-07-29\n/contosorest/\ncomp:list

Aqui está o valor final para AuthorizationHeader:

SharedKey contosorest:Ms5sfwkA8nqTRw7Uury4MPHqM6Rj2nfgbYNvUKOa67w=

O AuthorizationHeader é o último cabeçalho colocado nos cabeçalhos da solicitação antes de postar a resposta.

Isso abrange tudo o que você precisa saber para montar uma classe com a qual você pode criar uma solicitação para chamar as APIs REST dos Serviços de Armazenamento.

Exemplo: Listar blobs

Vamos ver como alterar o código para chamar a operação List Blobs para contêiner-1. Esse código é quase idêntico ao código para listar contêineres, as únicas diferenças são o URI e como você analisa a resposta.

Se você examinar a documentação de referência para ListBlobs, descobrirá que o método é GET e o RequestURI é:

https://myaccount.blob.core.windows.net/container-1?restype=container&comp=list

Em ListContainersAsyncREST, altere o código que define o URI para a API para ListBlobs. O nome do contêiner é container-1.

String uri =
    string.Format("http://{0}.blob.core.windows.net/container-1?restype=container&comp=list",
      storageAccountName);

Em seguida, onde você manipula a resposta, altere o código para procurar blobs em vez de contêineres.

foreach (XElement container in x.Element("Blobs").Elements("Blob"))
{
    Console.WriteLine("Blob name = {0}", container.Element("Name").Value);
}

Ao executar este exemplo, você obtém resultados como os seguintes:

Cabeçalhos canonicalizados:

x-ms-date:Fri, 17 Nov 2017 05:16:48 GMT\nx-ms-version:2017-07-29\n

Recurso canonicalizado:

/contosorest/container-1\ncomp:list\nrestype:container

Assinatura da mensagem:

GET\n\n\n\n\n\n\n\n\n\n\n\nx-ms-date:Fri, 17 Nov 2017 05:16:48 GMT
  \nx-ms-version:2017-07-29\n/contosorest/container-1\ncomp:list\nrestype:container

Cabeçalho de autorização:

SharedKey contosorest:uzvWZN1WUIv2LYC6e3En10/7EIQJ5X9KtFQqrZkxi6s=

Os seguintes valores são do Fiddler:

Pedido:

GET http://contosorest.blob.core.windows.net/container-1?restype=container&comp=list HTTP/1.1

Cabeçalhos de solicitação:

x-ms-date: Fri, 17 Nov 2017 05:16:48 GMT
x-ms-version: 2017-07-29
Authorization: SharedKey contosorest:uzvWZN1WUIv2LYC6e3En10/7EIQJ5X9KtFQqrZkxi6s=
Host: contosorest.blob.core.windows.net
Connection: Keep-Alive

Código de status e cabeçalhos de resposta retornados após a execução:

HTTP/1.1 200 OK
Content-Type: application/xml
Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: 7e9316da-001e-0037-4063-5faf9d000000
x-ms-version: 2017-07-29
Date: Fri, 17 Nov 2017 05:20:21 GMT
Content-Length: 1135

Corpo da resposta (XML): esta resposta XML mostra a lista de blobs e suas propriedades.

<?xml version="1.0" encoding="utf-8"?>
<EnumerationResults
    ServiceEndpoint="http://contosorest.blob.core.windows.net/" ContainerName="container-1">
    <Blobs>
        <Blob>
            <Name>DogInCatTree.png</Name>
            <Properties><Last-Modified>Fri, 17 Nov 2017 01:41:14 GMT</Last-Modified>
            <Etag>0x8D52D5C4A4C96B0</Etag>
            <Content-Length>419416</Content-Length>
            <Content-Type>image/png</Content-Type>
            <Content-Encoding />
            <Content-Language />
            <Content-MD5 />
            <Cache-Control />
            <Content-Disposition />
            <BlobType>BlockBlob</BlobType>
            <LeaseStatus>unlocked</LeaseStatus>
            <LeaseState>available</LeaseState>
            <ServerEncrypted>true</ServerEncrypted>
            </Properties>
        </Blob>
        <Blob>
            <Name>GuyEyeingOreos.png</Name>
            <Properties>
                <Last-Modified>Fri, 17 Nov 2017 01:41:14 GMT</Last-Modified>
                <Etag>0x8D52D5C4A25A6F6</Etag>
                <Content-Length>167464</Content-Length>
                <Content-Type>image/png</Content-Type>
                <Content-Encoding />
                <Content-Language />
                <Content-MD5 />
                <Cache-Control />
                <Content-Disposition />
                <BlobType>BlockBlob</BlobType>
                <LeaseStatus>unlocked</LeaseStatus>
                <LeaseState>available</LeaseState>
                <ServerEncrypted>true</ServerEncrypted>
            </Properties>
            </Blob>
        </Blobs>
    <NextMarker />
</EnumerationResults>

Resumo

Neste artigo, você aprendeu como fazer uma solicitação para a API REST de armazenamento de blob. Com a solicitação, você pode recuperar uma lista de contêineres ou uma lista de blobs em um contêiner. Você aprendeu como criar a assinatura de autorização para a chamada da API REST e como usá-la na solicitação REST. Finalmente, você aprendeu como examinar a resposta.

Próximos passos