Many users have requested adding support for Request Variables in HTTP files in Visual Studio. With Request Variables, you can send an HTTP request and then use data from the response, or request, in any subsequent request that is sent from the HTTP file. We have also added support for a shared environment, $shared, which enables you to share variables across different environments. In this post we will outline the new support which has been added for Request Variables and more. All the features listed in this post are included in Visual Studio 2022 17.12+.
Request Variables
When working with APIs it’s common to get a value from an endpoint and then use that value in a subsequent request. This can be achieved by using Request Variables. We have docs for Request Variables, but we will go over everything here as well. One of the more common scenarios for using Request Variables is when you call into an endpoint to authenticate to the APIs and get a token back which can be used for future requests. The sample request below is for David Fowler’s TodoApi sample. The API has an endpoint where you can create a new user by supplying the username and password. This is the endpoint that we are making a request to.
@username = bloguser
# login and save the response as "login"
# @name login
POST {{TodoApi_HostAddress}}/users/token
Content-Type: application/json
{
"username": "{{username}}",
"password": "{{password}}"
}
###
In this case the username is defined in the HTTP file, but the password is stored securely using HTTP Environments. The request below is to the /users/token endpoint, and we pass in the username and password as a part of the body of the HTTP request. The special sauce that makes this a Request Variable, sometimes referred to as Named Request, is the line immediately above the comment.
# @name login
After sending this request in Visual Studio you can then get values from the response, or the request. In snippet below, you can see how we use the login Request Variable to access the token which was returned as a part of the response when it was submitted. The login response body contained a single value, token. Now that we have logged in, we can create a TODO item with the request below.
# Create a TODO item
# @name todo1
POST {{TodoApi_HostAddress}}/todos
Authorization: Bearer {{login.response.body.$.token}}
Content-Type: application/json
{
"title": "Write blog post"
}
###
In this request we extract the token value and use it to specify the value for the Authorization header. The syntax {{login.response.body.$.token}}. Let’s take a closer look at the syntax.
{{login.response.body.$.token}}
Below is a table summarizing the syntax for using values from Request Variables.
Element | Description |
requestVarName (login in this case) | Request Variable which is being referenced. |
response|request | Whether the value will be extracted from the response or the request. |
body|headers | Whether the value will be extracted from the headers or body of the request or response (as specified in response|request). |
*|JSONPath|XPath|Header | The expression that will be evaluated to extract the result.
For a request returning a JSON body, use a JSONPath expression. For a request returning an XML body, use XPath. * will return the entire result. * cannot be used when extracting from headers. |
For the sample request above, we are extracting the token from the response and passing it in as a header for the request to the /todos endpoint. After we send this request, the result that is returned is shown below.
{
"id": 36,
"title": "Write blog post",
"isComplete": false
}
Now that we have created a TODO item, we can update that item with the request below. If you noticed the request above has declared a Request Variable named todo1, so we can refer to values from the response, or request, using that. Let’s update the title to add “ today” at the end of the current title. The request below will update the TODO item. We will use PUT since this is an update to an existing item.
PUT {{TodoApi_HostAddress}}/todos/{{todo1.response.body.$.id}}
Authorization: Bearer {{login.response.body.$.token}}
Content-Type: application/json
{
"id": {{todo1.response.body.$.id}},
"title": {{todo1.response.body.$.title}} today,
"isComplete": {{todo1.response.body.$.isComplete}}
}
###
In this request we use data from the original todo1 request to populate the body of the PUT request. Notice that the title property appends “ today” to the end of the existing title. After sending this request, the result was.
{
"id": 36,
"title": "Write blog post today",
"isComplete": false
}
Here you can see that the title of the blog post was successfully updated. In these examples I have shown working with “flat” JSON results, but you can use any JSONPath expression to extract the data from the response, or request, body. If your endpoints are returning XML, use an XPath expression instead of JSONPath. Let’s move on to discuss the support for $shared.
$shared Environment
When working with HTTP environments you can define multiple different environments for your HTTP requests. For example, you may create a dev environment which refers to your API which is running locally and a test environment when you want to send request to a remote test environment. In these cases you may want to declare a variable which is made available to all environments. This is exactly what the new $shared environment is for. HTTP environments are defined in a file named http-client.env.json, also http-client.env.json.user. If you create an environment named $shared, the variables will be made available in any environment. If a variable is declared in both $shared and standard environments, the value defined in the standard environment will win. Below is an example HTTP environment file containing a $shared environment and two standard environments.
{
"$shared": {
"message": "Default msg from Shared",
"username": "httpfile-user",
"hosturl": "http://example.com/api/sample"
},
"dev": {
"hosturl": "http://localhost:5000/api/sample"
},
"prod": {
"message": "Message from prod environment"
}
}
This is a very basic HTTP environment file where we have a dev and prod environment defined in addition to the $shared. In the dev environment the value for hosturl has been customized to point to localhost and the prod environment has customized the message value. To show how this works we will use a third-party open-source website httpbin.org. httpbin.org is a great tool for API developers. We will create an HTTP file that makes request to httpbin.org and have it return the values which were provided. We will use the /headers endpoint so that httpbin will echo the headers that we send to it. Below is the request that we will send.
GET https://httpbin.org/headers
X-Message: {{message}}
X-User: {{username}}
X-Hosturl: {{hosturl}}
###
This request will use the variables defined in the HTTP environment in the request sent to httpbin.org. Reminder that you can select the environment in the dropdown in the top right of HTTP file editor. I’ve set the environment to dev, and the result from httpbin.org is shown below.
{
"headers": {
"X-Hosturl": "http://localhost:5000/api/sample",
"X-Message": "Default msg from Shared",
"X-User": "httpfile-user"
}
}
In the response I removed some irrelevant headers. We can see that the values are being populated as expected. The value for hosturl is localhost as specified in the dev environment and the other values come from the $shared. When we switch the environment to prod and send the same request the response is as follows.
{
"headers": {
"X-Hosturl": "http://example.com/api/sample",
"X-Message": "Message from prod environment",
"X-User": "httpfile-user"
}
}
The values for both hosturl and message have changed. The value for hosturl and username are coming from the $shared and message is coming from the value provided in the prod environment. If you send a request without an environment selected, values from $shared will be available. Now we have covered the new support for $shared, we will close out the blog post now.
Closing
In this post we have covered two new features for HTTP files, Request Variables and $shared in HTTP environments. With Request Variable support you can now create “chained” requests which take values from previous requests. This should enable you to exercise your APIs more in realistic ways than before. In addition, with $shared you can now share variables across environments making it easier for you to work with HTTP environments. If you are new to HTTP files take a look at the docs for more info.
The updates in this post were inspired by feedback from users like yourself. You can share feedback with us via Developer Community: report any bugs or issues via report a problem and share your suggestions for new features or improvements to existing ones.