Advanced Configurations in Optic

Optic setup

api init and the setup process should get you started. The following topics cover advanced configuration to tweak your setup and take advantage of more features in Optic. If you run into difficulties during install, please reach out to us with an issue so we can help you get situated. You don't have to resolve setup issues on your own!

Optic Command Wrapper task mode#

When you first setup Optic, a start task is added to your optic.yml file:

name: Todo API
tasks:
start:
command: npm run server-start
inboundUrl: 'http://localhost:3005' # alias: baseUrl

The task start in the above example is run using:

api start

If your framework expects to take a parameter to define its port when starting, Optic provides the PORT environment variable to your process. You can pass that in the command parameter. If the PORT environment variable is already being used for some other reason in your environment and it causes conflicts with Optic's port assignment, you can use the alternative OPTIC_API_PORT if necessary:

name: Todo API
tasks:
start:
command: npm run server-start --port $PORT
inboundUrl: 'http://localhost:3005' # alias: baseUrl

You may also want a quick way to run your API tests, a Postman collection, etc. through Optic. To make this simple, Optic lets you define as many custom tasks as you'd like:

name: Todo API
tasks:
start:
command: npm run server-start
inboundUrl: 'http://localhost:3005' # alias: baseUrl
test:
command: npm run testAPI
inboundUrl: 'http://localhost:3005' # alias: baseUrl

Each custom task can be run with:

api run <task name>

Proxy task mode#

For most local documentation, we recommend starting your API application directly with an Optic task, also known as Command Wrapper mode. This allows Optic to start your project and a new capture session to organize observed requests. Sometimes, this isn't feasible - such as when your API is always deployed in a Serverless architecture and cannot be run locally. In this case, the Optic Proxy mode will let you configure your downstream and upstream URLs.

Setting up the Local CLI in Proxy mode#

All configuration items for local capture live in the optic.yml file. Create a new task to use the Proxy mode:

  • Create a new task start-proxy at the same level of indent as start (the default task).
  • inboundUrl (alias baseUrl) is the URL configuration where the application we're observing should expect to live. When using Optic to observe traffic, Optic adopts this URL to intercept traffic and pass it along to the application under observation. That way, your clients or tests can still run exactly as they have in the past.
  • targetUrl tells us the target for the observed traffic, our application under observation. We'll need to run the application on this URL so that Optic can pass traffic along to the target application.
  • The command field is for process wrapping, and isn't necessary for the proxy configuration. Leave that out.

The tasks section of the optic.yml file will look something like this:

tasks:
start:
...
start-proxy:
inboundUrl: http://localhost:<port>
targetUrl: http://<your application>:<port>

Note: if not specified the targetUrl will assume ports based on the protocol (80 for http, 443 for https). It may be optionally omitted in these cases.

Next, run:

api check start-proxy

This will validate that the configuration is correct. Once the configuration check passes, you can document your API with:

api run start-proxy
  • The local dashboard will be available, with observed diffs.
  • The Optic CLI will listen on localhost at the port defined in inboundUrl.
  • Traffic sent to the Optic CLI will be forwarded to the defined targetUrl - assure that is already running, or if not, start it before sending any traffic.

Starting a new Capture Session in Poxy task mode#

When Optic is started in Proxy task mode, it is not watching the application lifecycle and does not currently capture rebuild events of the application under observation. To start fresh with a new capture session, stop the current Optic proxy and restart with api run start-proxy. This will create a new capture session in the Optic dashboard and allow you to observe traffic sent to the most recent build of the application under observation.

Transparent Proxy mode#

Optic forwards all requests sent to the localhost inboundUrl to the targetUrl by default. This is not a one-size-fits-all solution. For example, if you are testing a UI and it makes requests to a CDN for assets, the default behavior will not work. Optic can run in Transparent Proxy mode that allows you to forward all requests transparently. To enable this mode, invoke a proxy task with:

api run --transparent-proxy start-proxy

You will need to set up your app to use Optic explicitly as a proxy. All traffic will flow through the Optic proxy, and can be filtered in the dashboard for relevant API traffic. The following optic.yml sets up a proxy task and a dependent task (see below) to start the Chrome browser with proxy settings. In this case, api run --transparent-proxy ui-proxy would start up the start proxy definition, and open a new Chrome browser (on MacOS) with the appropriate flags to proxy traffic through Optic:

tasks:
start:
targetUrl: https://api.example.com
inboundUrl: https://localhost:4000
ui-proxy:
useTask: start
command: /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --ignore-certificate-errors --proxy-server="https://localhost:4000" --user-data-dir="/tmp/optic" https://api.example.com/api/docs

Dependent tasks#

A task can depend on another task. For example, say you need to start your API service with a task, then want to run test traffic against that service through Optic. First, define the task to start your API service with Optic. Then, define a new task with the command parameter to run your test script and the useTask parameter specifying your service start task. The example below runs a Newman test against the start-proxy task above:

tasks:
start:
...
start-proxy:
inboundUrl: http://localhost:<port>
targetUrl: http://<your application>:<port>
run-tests:
useTask: start-proxy
command: newman run collection.json --environment environment.json

Dependencies can only go one level deep. Dependent tasks cannot define inboundUrls or targetUrls, as dependent tasks expect the API start command to start the Optic proxy and handle these configurations. The dependent task command will run after the API start command starts and the service is responsive. There's no need to add any sleep delays if the service itself takes time to warm up.

Ignoring API Paths#

As you use Optic, you will probably find there are some paths you would like Optic to ignore. These can be identified individually in the undocumented endpoint review page in the UI. For ignoring routes in bulk by some characteristic, you can directly edit the project's ignore rules. Examples include ignoring all OPTIONS requests, .html, .js, .css files, or everything in your /public folder. Many of these are provided by default, and can be removed if necessary.

You can add ignore rules to your .optic/ignore file:

# Default Ignore Rules
# Learn to configure your own at http://localhost:4000/docs/using/advanced-configuration#ignoring-api-paths
OPTIONS *
HEAD *
GET (.*).htm
GET (.*).html
GET (.*).css
GET (.*).js
...

Rules follow the following format:

METHOD(s) path
  1. The methods component can be:
    • a single method GET
    • multiple methods GET POST PUT
    • omitted -> which is interpreted as ALL
  2. The path component follows the path-to-regex format. The library has a lot of advanced features that you can use, but most use cases can probably be accomplished with the following patterns:
    • Want to ignore an absolute path? Just write it ie /users/profile
    • Want to ignore a file type? ie (.*).png (.*).js
    • Want to ignore a path and its children? /public/(.*)
    • Need something more advanced? Try creating your pattern in the path-to-regex-sandbox
  3. Scalar values in YAML cannot start with a special character ([] {} > | * & ! % # ` @ ,). If you need to start a value with *, wrap the value in double quotes.

Examples#

OPTIONS (.*) # Ignores all Options requests
/public/(.*) # Ignores all Requests to public/**
GET (.*).js # Ignores all GET requests to a resource ending in .js
GET POST PUT /resource #Ignores all GET, POST, PUT requests to /resource