Templating your Optic Configuration with Handlebars

Nate Meyer 2023-11-17

Recently, we’ve introduced several changes to Optic Capture with the intention of making it simpler and faster to understand and use. As part of that, we added a way to describe requests and have Optic generate traffic to your API. A simple request might look something like,

config:
  ...
  requests:
    send:
	  - path: /
        headers:
		  content-type: application/json

While we think that’s pretty cool, it comes with a set of limitations—What if you have a more complicated API that requires authorization? Sure, you can add an authorization header to the example above, but you probably don’t want to actually include token portion—it’s secret.

Keeping secrets out of your Optic configuration

It was clear that we needed a way to handle secrets and configuration bits that didn’t feel correct to explicitly include into the configuration. We settled on using Handlebars (opens in a new tab) to add template support to the optic.yml file. So to extend our example above with an authorization header,

config:
  ...
  requests:
    send:
	  - path: /
        headers:
		  content-type: application/json
          authorization: bearer {{TOKEN}}

{{TOKEN}} will be replaced with the environment variable TOKEN. While you can set environment variables however you choose, Optic will optionally load variables from .optic.env, which is a typical dotenv file. You can place it next to your optic.yml, or in the root of your Git repo. You most likely will want to avoid committing this file to source control.

Since you can use variables anywhere within optic.yml, you can also use this with another new Optic feature (opens in a new tab) and set headers when resolving remote $refs in OpenAPI files!

external_refs:
  resolve_headers:
    - url_prefix: https://gitlab.com
      headers:
        authorization: bearer {{TOKEN}}

Codifying application environments

We’ve focused so far on using templates as a means to keep secrets out of our Optic configuration, but this just scratches the surface of the possibilities. You could also use templates to codify the differences between environments.

Say your dev and staging environments have infrastructural differences that could impact endpoint responses in some way. You might want flexibility to run Optic easily against both environments. Consider this example,

capture:
  openapi.yml:
    server:
	  command: {{SERVER_COMMAND}}
	  url: {{SERVER_URL}}

In dev, these values might be,

SERVER_COMMAND = "yarn run dev"
SERVER_URL = "http://localhost:3000"

While in staging, they could be,

SERVER_COMMAND = ""
SERVER_URL = "https://staging.example.com"

In staging’s values, setting SERVER_COMMAND to an empty string will cause Optic to not attempt to start the server, and instead assume it is already running—ideal for a persistent environment or something that’s started by another means.

Conclusion

We’ve taken a look at a few ways to take advantage of templates in your Optic configuration. There’s no doubt other uses we haven’t considered so if there’s something you’d like to see, create an issue (opens in a new tab) or hop into Discord (opens in a new tab) and let’s chat!

You can also read more about templating your Optic configuration in the docs (opens in a new tab).

Want to ship a better API?

Optic makes it easy to publish accurate API docs, avoid breaking changes, and improve the design of your APIs.

Try it for free