The state of http request management feels a bit disappointing to this developer. Postman is closed source, has an intrusive account requirement and an increasingly complex UI. Insomnia is open source, uses non-standard UI, and is missing features like inherited authentication. Thunder Client, while raising a bit of excitement this year, is closed source and intends to go commercial similar to the others.

All of these applications hide requests and configuration internally, forcing a developer to import and export data to and out of these walled gardens. In this post, I’ll explain how httpyac breaks a developer free of these restrictions and greatly improves http request management.

httpyac

httpyac is both a CLI tool for executing http requests and a vscode extension that lets you execute the same requests from within vscode. The key features that I like about httpyac are:

  • Requests are just files that can be shared and diffed like any regular text file
  • OAuth 2.0 Implicit Grant flow is supported and (in vscode) auth sessions are cached
  • Environments can be configured and can inherit from a global environment
  • GraphQL/REST supported
  • Hooks and plugin approach allows easy extensibility - also it’s opensource

These features complement each other such that I’ve included httpyac in my daily development process to:

  • Replace Postman/Insomnia
  • Automate token authentication when generating types for GraphQL
  • Generate requests where otherwise collections do not exist

File Format

httpyac uses .http or .rest files to specify requests. An example .http for a GraphQL request might look like this:

POST https://api.spacex.land/graphql
Content-Type: application/json

query launches_query($limit: Int) {
  launches(limit: $limit) {
    details
    id
    launch_success
    launch_year
    mission_name
  }
}

{
  "limit": 2
}

This approach means what other tools call Collections are just directories. Each .http file in our directory can contain one or more requests.

By default, httpyac supports dotenv variable configuration. These are also just files located in our directories and using them allows us have the same requests targeting different environments like so:

# myRequest.http
GET {{host}}/search?q={{query}}
# .env
query=abc123
# .dev
host=http//dev.api.com/
# .prd
host=http//prod.api.com/

Because we’re using the file system to store requests and environment configuration, we don’t need to import/export this data in and out of the tool - we just edit the file system directly - say, with vscode. This makes requests and environments easy to understand, write, generate, diff, commit and share.

CLI or IDE

Once our requests and environment configuration is ready, we can execute requests and see their results. For the following request:

# spacex.http
POST https://api.spacex.land/graphql
Content-Type: application/json

query company_query {
  company {
    coo
    founded
    headquarters {
      address
      city
      state
    }
  }
}

We can run the following command in our terminal:

httpyac spacex.http --all

And see the following results:

---------------------

POST https://api.spacex.land/graphql
accept: */*
accept-encoding: gzip, deflate, br
content-length: 175
content-type: application/json
user-agent: httpyac

{"query":"query company_query {\n  company {\n    coo\n    founded\n    headquarters {\n      address\n      city\n      state\n    }\n  }\n}","operationName":"company_query"}

HTTP/1.1 200  - OK
access-control-allow-origin: *
connection: close
content-length: 143
content-type: application/json; charset=utf-8
date: Wed, 01 Dec 2021 12:13:09 GMT
etag: W/"8f-5axl0s+FsWkU3eTR2jd/wM7KgZc"
server: Cowboy
via: 1.1 vegur
x-powered-by: Express

{
  "data": {
    "company": {
      "coo": "Gwynne Shotwell",
      "founded": 2002,
      "headquarters": {
        "address": "Rocket Road",
        "city": "Hawthorne",
        "state": "California"
      }
    }
  }
}

In vscode, with the httpyac extension, we click send and get a similar result:

httpyac vscode extension sending spacex request

Managing Authentication

Some requests need a valid authentication token to be supplied and some older applications may still be using the deprecated OAuth 2.0 Implicit Flow to do this. In .http files we can set Authorization: openid implicit and using the variables listed below, httpyac will start a server and listen on the port and host specified in oauth2_redirectUri. At request time, httpyac will open a browser to start the authentication flow, receive the token from the redirect, and substitute this token in as our Authorization header.

# graph.http
@oauth2_clientId=ff65611b-482f-42c9-aec4-132c99c33f08
@oauth2_authorizationEndpoint=https://login.microsoftonline.com/3f11a75a-4ea2-4944-ac03-08b05efbbfad/oauth2/v2.0/authorize
@oauth2_tokenEndpoint=https://login.microsoftonline.com/3f11a75a-4ea2-4944-ac03-08b05efbbfad/oauth2/v2.0/token
@oauth2_redirectUri=http://localhost:3000

GET https://graph.microsoft.com/v1.0/me
Authorization: openid implicit
httpyac graph.http --all -o body

---------------------

{
  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity",
  "businessPhones": [
    "4258828080"
  ],
  "displayName": "Stafford Williams",
  "givenName": "Stafford",
  "jobTitle": null,
  "mail": "staff0rd@lpdw.onmicrosoft.com",
  "mobilePhone": null,
  "officeLocation": null,
  "preferredLanguage": null,
  "surname": "Williams",
  "userPrincipalName": "staff0rd@lpdw.onmicrosoft.com",
  "id": "70f82f3d-fa74-4c5d-8bbb-a65ce1a811e8"
}

Every time we call httpyac from the CLI like the above, the browser will pop open and the token is extracted. A benefit of the vscode-httpyac extension is session caching - once the token is cached in the session, it does not need to pop the browser and request another token unless it becomes invalid.

httpyac vscode extension caching session token

In the above example we specify the the oauth2_* variables directly in the request, however we can move these to a test.env or similar environment file and pass them to any request with something like:

httpyac graph.http --all --env test

This authentication feature means we can use httpyac to help us retrieve the token for usage in other workflows. The following command will invoke the auth approach on our request above and echo the resulting token:

httpyac graph.http --all --json -o headers | jq -r .requests[0].response.request.headers.authorization

Because httpyac exports most of its functionality, we can add even add a token-getting-feature to our own packages or nodejs scripts programmatically:

const { variables: httpyac } = require("httpyac");

const getToken = async (resourceId) => {
  const variables = {
    oauth2_authorizationEndpoint:
      "https://login.microsoftonline.com/3f11a75a-4ea2-4944-ac03-08b05efbbfad/oauth2/v2.0/authorize",
    oauth2_clientId: "ff65611b-482f-42c9-aec4-132c99c33f08",
    oauth2_tokenEndpoint:
      "https://login.microsoftonline.com/3f11a75a-4ea2-4944-ac03-08b05efbbfad/oauth2/v2.0/token",
    oauth2_redirectUri: "http://localhost:3000/",
  };

  const response = await httpyac.replacer.getOAuth2Response(
    "implicit",
    "oauth2",
    { variables }
  );

  return response.accessToken;
};

Generating Collections

In the case of GraphQL endpoints, introspection lets us discover the shape of queries and what parameters they need. From this information we can create what other tools call Collections. A collection should include at least one example of each request and the parameters it needs to execute. Tools like Apollo Studio Explorer can help us build these requests manually, but I’d prefer to generate them.

To this end, I’ve built httpyac-codegen-graphql which is a preset for GraphQL Code Generator that generates httpyac requests for GraphQL endpoints. We can configure the schema and optionally specify any parameter values to generate along with requests.

From an empty directory, add GraphQL Code Generator and the preset:

npm i -D @graphql-codegen/cli httpyac-codegen-graphql

Then, configure the generator like so:

# codegen.yml
schema: https://api.spacex.land/graphql
generates:
  spacex:
    preset: httpyac-codegen-graphql
    presetConfig:
      host: https://api.spacex.land/graphql
      variables:
        ship_query:
          id: HAWK
        cores_query:
          id: B1034

And to generate the requests execute:

npx graphql-codegen

The result is ~100 .http files generated - one for each of the operations specified in the schema. Requests can be immediately executed in vscode-httpyac or via the CLI:

httpyac spacex/ship_query.http --all

Conclusion

httpyac’s features, and the request generation approach above, move the management of http requests out of commercial tools and onto the filesystem. The vscode-httpyac extension let’s us execute requests inside our editor and turns a request or environment configuration into just another file within our repo. As files in a repository, we get the collaboration features we’re familiar with as developers. As open source projects, bug fixes or new features in httpyac and httpyac-codegen-graphql are just a pull request away.