Introduction
Many of us come from an SQL background; when we want to connect to an SQL Server, usually we need to have a username and password. You need to do more than that to connect and run queries in CosmosDB. But CosmosDB needs some more parameters to connect to it.
Once you create the Cosmos DB account on Azure and navigate to the keys section on the left pane, you will see two types of tabs on the Keys. There are two types of keys. One type of user having the Key can Read and Write. Other types of users having the key can only Read.
Different terms used while making a connection to Cosmos DB
Let’s understand the different terms used while making a connection to Cosmos DB
Master Keys are keys created when the Cosmos DB Account is created. This key can be regenerated by clicking on the refresh icon to regenerate it in the Azure portal. When you are using the Cosmos DB emulator, you won’t be able to generate it. These keys are very sensitive ones and provide access to administrative resources. We should be very careful when we need to store them. The recommended way is to use Read-Only Keys as much as we can.
Resource Tokens are responsible for providing access to specific containers, documents, attachments, stored procedures, triggers, and UDFs. Each user must have a resource token. It is mandatory that every application needs to use a resource token to call Cosmos DB API.
Users are specific to Cosmos DB databases. You can attach specific permissions or roles to each user like the way we do in SQL server.
Cosmos DB API
As I mentioned earlier, we have many options to access to CosmosDB. Rest API is one of these options, and it is the low-level access way to Cosmos DB. Most of the features supported with SDK are available, and you can customize all options of CosmosDB by using REST API. To customize the calls and pass the required authorization information, you need to use http headers.
In the following example, I am going to try to create a database in the CosmosDB emulator by using the REST API. First, let’s look at the required header fields for this request. These requirement applies to all other REST API calls too.
- x-ms-version: As the name indicates, this is the version of the REST API. You can find the available versions here. If you are confused about what to use, always use the latest one.
- x-ms-date: This is the date of your request. It must be formatted by Coordinated Universal Time. (ex: Sun, 30 June 2019 05:00:23 GMT)
- x-ms-session-token: It is required if you want to use session consistency. For each of your new write requests in Session consistency, CosmosDB assigns a new SessionToken to the calls. You need to track the right session token and use it in this header property to keep using the same session. SDK does this for you in the background. If you want to use the REST API, you need to do this manually.
- Authorization: This one is the most important and tricky one. This needs to get generated for each of your calls to Cosmos DB. It must be in the following format
How to Call APIs with Postman?
To call Cosmos DB directly from POSTMAN, you need to get the Cosmosdb account URL we need to use. If you are using the emulator, you can get it from the local environment, which should be like https://localhost:8081. I will be using the account created in the Azure portal.
One other thing you need to set up is the environment variable. As you see, we are using some of the configured variables in the script. You can create a new environment variable using Postman by navigating to environments and adding a new environment with configured variables.
Create environments
Configured variables
we need to look at the documentation of CosmosDB Rest API. You can find all URL locations from this link. Since I am trying to list the databases inside a collection, I am going to use the following path.
https://postmandemo.documents.azure.com:443/
Also, the documentation tells us that this must be a GET Http Action. In Postman, I pick the GET and type the URL to the URL section in the following example.
As the Next step, we need to create an environment in Postman to store some variables. As connecting to Cosmos DB needs a token, we need to generate a token for CosmosDB and get the current date to fill the header named x-ms-date. I am going to use variables in Environment to store the values. To Create an environment. Click on the gears icon and click on Add.
The below example shows the environment variables that we will frequently use to test Cosmos DB API.
As we are requesting to get the list of databases, we are ready to add values to the headers section. Click on the Headers link, and add the following headers. These are the required HTTP headers for all CosmosDB REST API calls.
- x-ms-version : 2019-06-30: (This is the latest version. You can find the other versions here.)
- x-ms-date: {{utcDate}}: (This is the parameter we just created in the POSTMAN Environment. We are going to generate its value in the script.)
- authorization: {{authToken}}: (This is the other parameter we just created. We are going to generate its value in the script.)
- Accept application/json.(This is required since this is going to be a GET Http Action.)
Your screen should look like this.
Next, we need to generate an authorization token and the date in the required format. To do that, We need to use o use the Pre-request Script section. POSTMAN will run this script before each request. This will be the part where we will generate authToken and utcDate parameters. Copy and Paste the code to the Pre-Request Script tab.
//store our master key for documentdb
var mastKey = postman.getEnvironmentVariable("CosmosDBMasterKey");
console.log("mastKey = " + mastKey);
// Store our date as RFC1123 format for the request
var today = new Date();
var UTCstring = today.toUTCString();
postman.setEnvironmentVariable("RFC1123time", UTCstring);
// Grab the request URL
var url = request.url.trim();
console.log("request URL = " + url);
// Strip the URL of the hostname and leading slash
var strippedurl = url.replace(new RegExp('^https?://[^/]+/'), '/');
console.log("stripped URL = " + strippedurl);
// Push the parts down into an array to determine if the call is on a specific item or a resource
var strippedparts = strippedurl.split("/");
var truestrippedcount = strippedparts.length - 1;
console.log(truestrippedcount);
// Define resourceId/Type now based on the amount of levels
var resourceId = "";
var resType = "";
// It's odd (resource request)
if (truestrippedcount % 2) {
console.log("odd");
// Assign the resource type to the last part we found
resType = strippedparts[truestrippedcount];
console.log(resType);
if (truestrippedcount > 1) {
// Now pull out the resource id by searching for the last slash and substringing to it
var lastPart = strippedurl.lastIndexOf("/");
resourceId = strippedurl.substring(1, lastPart);
console.log(resourceId);
}
} else { // It's even (item request on resource)
console.log("even");
// Assign the resource type to the part before the last we found (last is the resource id)
resType = strippedparts[truestrippedcount - 1];
console.log(resType);
// Finally, remove the leading slash which we used to find the resource if it was only one level deep
strippedurl = strippedurl.substring(1);
console.log(strippedurl);
// Assign our resourceId
resourceId = strippedurl;
console.log(resourceId);
}
// Assign our verb
var verb = request.method.toLowerCase();
// Assign our RFC 1123 date
var date = UTCstring.toLowerCase();
// Parse our master key as base64 encoding
var key = CryptoJS.enc.Base64.parse(mastKey);
console.log("key = " + key);
// Build up the request text for the signature to sign it along with the key
var text = (verb || "").toLowerCase() + "\n" +
(resType || "").toLowerCase() + "\n" +
(resourceId || "") + "\n" +
(date || "").toLowerCase() + "\n" +
"" + "\n";
console.log("text = " + text);
// Create the signature from the build-up request text
var signature = CryptoJS.HmacSHA256(text, key);
console.log("sig = " + signature);
// Convert back to base64 bits
var base64Bits = CryptoJS.enc.Base64.stringify(signature);
console.log("base64bits = " + base64Bits);
// Format our authentication token and URI encode it
var MasterToken = "master";
var TokenVersion = "1.0";
auth = encodeURIComponent("type=" + MasterToken + "&ver=" + TokenVersion + "&sig=" + base64Bits);
console.log("auth = " + auth);
// Set our auth token environmental variable
postman.setEnvironmentVariable("authToken", auth);
We are done with all the things needed to get the list of databases. Click on the send button to see the list of databases as a response.
Great! Look at all that information we received back in the body of the Response.
This is the way to test Cosmos DB API with POSTMAN. You can try different APIs with the simple collection we’ve created here. Now it becomes easy for developers to leverage the Cosmos DB api and to play around with it.