azureazure-functionsazure-storage-emulator

CosmosDB Emulator: The value for one of the HTTP headers is not in the correct format


I am writing/debugging an Azure Function with the Azure Storage Emulator on my local machine. Unfortunately, I'm not quite sure which API(s) I should use or the correct URLs for the storage. My code looks like this:

CosmosClient client = new CosmosClient(storageURL, authKeyString);
Database db = client.GetDatabase("devstoreaccount1");
container = db.GetContainer("leaderboard");
ItemResponse<StoredScore> resp = await container.CreateItemAsync<StoredScore>(newScore);

The inputs to the function are:

storageURL = "http://127.0.0.1:10002"
authKeyString = "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="

On the last line of the code above, I get an exception:

DocDBTrace Warning: 0 : initializeTask failed Microsoft.Azure.Documents.DocumentClientException: <?xml version="1.0" encoding="utf-8" standalone="yes"?>
<error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
  <code>InvalidHeaderValue</code>
  <message xml:lang="en-US">The value for one of the HTTP headers is not in the correct format.
RequestId:ed82efd8-6cb8-4a2e-a793-16a38b3c8f2a
Time:2019-12-20T20:07:19.9539313Z</message>
</error>
RequestUri: http://127.0.0.1:10002/;
RequestMethod: GET;
Header: x-ms-version Length: 10;
Header: User-Agent Length: 98;
Header: x-ms-date Length: 29;
Header: Authorization Length: 84;
, Request URI: /, RequestStats: , SDK: Windows/10.0.16299 cosmos-netstandard-sdk/3.4.2
   at Microsoft.Azure.Cosmos.GatewayStoreClient.ParseResponseAsync(HttpResponseMessage responseMessage, JsonSerializerSettings serializerSettings, DocumentServiceRequest request)
   at Microsoft.Azure.Cosmos.GatewayAccountReader.GetDatabaseAccountAsync(Uri serviceEndpoint)
   at Microsoft.Azure.Cosmos.Routing.GlobalEndpointManager.GetDatabaseAccountFromAnyLocationsAsync(Uri defaultEndpoint, IList`1 locations, Func`2 getDatabaseAccountFn)
   at Microsoft.Azure.Cosmos.GatewayAccountReader.InitializeReaderAsync()
   at Microsoft.Azure.Cosmos.CosmosAccountServiceConfiguration.InitializeAsync()
   at Microsoft.Azure.Cosmos.DocumentClient.InitializeGatewayConfigurationReaderAsync()
   at Microsoft.Azure.Cosmos.DocumentClient.GetInitializationTaskAsync(IStoreClientFactory storeClientFactory)
   at Microsoft.Azure.Cosmos.DocumentClient.EnsureValidClientAsync()
DocDBTrace Error: 0 : DocumentClientException with status code BadRequest, message: <?xml version="1.0" encoding="utf-8" standalone="yes"?>
<error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
  <code>InvalidHeaderValue</code>
  <message xml:lang="en-US">The value for one of the HTTP headers is not in the correct format.
RequestId:67e1f70a-c9c8-4aed-892c-964e8ff0f0e1
Time:2019-12-20T20:11:28.0006476Z</message>
</error>
RequestUri: http://127.0.0.1:10002/;
RequestMethod: GET;
Header: x-ms-version Length: 10;
Header: User-Agent Length: 98;
Header: x-ms-date Length: 29;
Header: Authorization Length: 82;
, inner exception: null, and response headers: {
"Server": "Microsoft-HTTPAPI/2.0",
"x-ms-request-id": "67e1f70a-c9c8-4aed-892c-964e8ff0f0e1",
"Date": "Fri, 20 Dec 2019 20:11:27 GMT",
}
DocDBTrace Information: 0 : Fail to reach global gateway http://127.0.0.1:10002/, Microsoft.Azure.Documents.DocumentClientException: <?xml version="1.0" encoding="utf-8" standalone="yes"?>
<error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
  <code>InvalidHeaderValue</code>
  <message xml:lang="en-US">The value for one of the HTTP headers is not in the correct format.
RequestId:67e1f70a-c9c8-4aed-892c-964e8ff0f0e1
Time:2019-12-20T20:11:28.0006476Z</message>
</error>
RequestUri: http://127.0.0.1:10002/;
RequestMethod: GET;
Header: x-ms-version Length: 10;
Header: User-Agent Length: 98;
Header: x-ms-date Length: 29;
Header: Authorization Length: 82;
, Request URI: /, RequestStats: , SDK: Windows/10.0.16299 cosmos-netstandard-sdk/3.4.2
   at Microsoft.Azure.Cosmos.GatewayStoreClient.ParseResponseAsync(HttpResponseMessage responseMessage, JsonSerializerSettings serializerSettings, DocumentServiceRequest request)
   at Microsoft.Azure.Cosmos.GatewayAccountReader.GetDatabaseAccountAsync(Uri serviceEndpoint)
   at Microsoft.Azure.Cosmos.Routing.GlobalEndpointManager.GetDatabaseAccountFromAnyLocationsAsync(Uri defaultEndpoint, IList`1 locations, Func`2 getDatabaseAccountFn)
Exception thrown: 'Microsoft.Azure.Documents.DocumentClientException' in System.Private.CoreLib.dll

The Azure Storage Emulator is running and I can manipulate it in Storage Explorer.

Can anyone help me figure out what I've done wrong? Am I using the 'best' API for this?


Solution

  • Based on your code, you want to use cosmosdb to store your StoredScore data. If so , you should use CosmosDB emulator on your side instead of storage Emulator.

    Pls follow steps below to make your code work :

    1. Install and run CosmosDB emulator

    2. Create a cosmos db with a collection on your local :

    enter image description here

    In this case , my cosmos db name is localdb and my container name is localcontainer

    You can find your cosmosdb host and key here : enter image description here

    3.Create a http trigged Azure function in VS locally, this is my code below :

    using System;
    using System.IO;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Extensions.Http;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.Logging;
    using Newtonsoft.Json;
    using Microsoft.Azure.Cosmos;
    
    namespace cosmostest
    {
        public static class Function1
        {
            [FunctionName("Function1")]
            public static async Task<IActionResult> Run(
                [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
                ILogger log)
            {
                CosmosClient client = new CosmosClient("https://localhost:8081/", "<your key here>");
                Database db = client.GetDatabase("<your local db name>");
                Container container = db.GetContainer("<your local container name>");
                var newScore = new StoredScore() { id ="1", name ="stan", score =100 };
                ItemResponse<StoredScore> resp = await container.CreateItemAsync<StoredScore>(newScore);
                return new OkObjectResult(resp.StatusCode);
            }
        }
    
        public class StoredScore
        {
    
            public string id { get; set; }
            public string name { get; set; }
            public int score { get; set; }
        }
    
    }
    

    Run the function and trigger it, if you get "201" as response, your data has been saved into you local cosmos DB successfully : enter image description here

    Data in local cosmos DB: enter image description here

    Hope it helps.