Stoplight's spotlight on open-source this October is an excellent opportunity for us to take a closer look at Prism - a handy two-in-one command-line tool for API mocking and API contract testing. Along with Spectral, an API linter and validator, and Elements, a tool for embedded API documentation, it is one of the three open-source tools that Stoplight provides and maintains for the community.
This article will discuss the two modes of operation for Prism and how you can leverage them in your API lifecycle. We'll also talk briefly about how this tool works under the hood, how it fits into the other Stoplight products, and how you can contribute or support its development.
Getting Started with Prism
Prism is a command-line tool that runs on all platforms and requires NodeJS version 12 or higher. You can install it through either of the popular NodeJS package managers - npm or yarn. To make it globally available on your system, run one of the following commands, depending on which package manager you use:
npm install -g @stoplight/prism-cli
yarn global add @stoplight/prism-cli
You can also look at the Prism documentation for further installation options, such as binaries or a Docker container. After installing Prism, you can launch it with the `prism` command. As mentioned before, Prism has two modes:
- With `prism mock`, you can start a mock server from an OpenAPI file
- With `prism proxy`, you can set up a validation proxy server with an OpenAPI file and the original endpoint
We'll discuss these two features in detail in the following sections.
Running a Mock server
When following an API Design First approach, you create an OpenAPI document for your API before building the backend implementation. This workflow allows you to collect feedback from the various stakeholders and integrate change requests to your API early, before writing any implementation code. Changing an API definition is faster and, thus, more cost-effective than refactoring your code.
However, when you're building a complete application with front-end and back-end or various microservices, and those components connect through APIs, you have a dependency problem. Your API design exists so the consuming team can start writing integration code, but they cannot test against the API yet because it hasn't been built. That's where mocking comes in. A mock server is a server that mimics the endpoints and behavior of the original API, so you can write consumer code and run tests against the API. Instead of backend code, all you need is your OpenAPI document to get started. The consuming team can work with the API, provide feedback, and your product can go through multiple quick iterations. In each cycle, you continuously refine the API definition again, even before the backend implementation starts. Once the specification seems stable, you can parallelize development and have two developers or development teams work on the frontend and backend simultaneously.
With Prism, you can launch such a mock server with an API definition in a single command. In your command prompt, type the following and replace `openapi.yaml` with the actual filename of your OpenAPI document:
prism mock openapi.yaml
If you need your mock server to listen on a specific port, add the `-p` option to the command:
prism mock -p 8080 openapi.yaml
Assuming you have provided a valid OpenAPI document, Prism will print a list of all the operations found in the paths element. The mock server is now listening to requests for these endpoints. You can interact with the server by opening an additional command-line tab or window and running the `curl` command with one of the URLs from the list. While you're hitting the mock server, Prism's command-line output shows detailed log information about the requests it received and whether they were valid or not.
How does the mock server know how to respond? Well, Prism tries gathering as much information as possible from the JSON schemas in the OpenAPI file. For instance, it uses examples or default values if available. There is an HTTP Mocking guide in Prism documentation where you can read all the details about the response generation algorithm. Generally speaking, the better your API document, the closer the results are to the actual API. Therefore, using Prism provides additional motivation to add proper examples, data ranges, and other validation keywords to your schemas.
When you're writing an API client, getting the same data back all the time can lead to building brittle interfaces which only handle that sample data. For example, what happens if a name is really long or a certain value is missing? Using dynamic responses you can start Prism with the `-d` option to generate dynamic responses. In that mode, Prism leverages the Faker.js library to create values. If you use mocking a lot, you can add the custom `x-faker` property to your schemas to trigger specific functions in Faker.js, for example, to generate names. Again, you can refer to the HTTP Mocking guide in Prism documentation for more details.
You can launch your mock servers in either of the following ways:
- Running Prism directly from the command line, as shown here.
- Deploying Prism in the cloud, for example, as a Netlify function, as demonstrated in “How to Generate Serverless HTTP API Mocking Using Prism”
- As part of the Stoplight Studio desktop application.
- As a hosted service as part of the Platform.
Now that we have covered the mock feature, let's talk about Prism's other mode of operation, the validation proxy.
Running a validation proxy
You can think about mock servers as a tool for API consumers to write integration code for an API that doesn't exist yet, as explained earlier in this article. On the other hand, a validation proxy is a tool that enters the picture during or after the API implementation. With Prism, you can test an API and ensure it matches the contract that it’s supposed to: the OpenAPI definition. There are various stakeholders that can benefit from a validation proxy. We’ll discuss them in a moment after looking at the feature itself.
In proxy mode, Prism forwards API requests to the upstream server, which can be your API's development or production server, and delivers the responses back to the client. Unlike most proxies, however, Prism's validation proxy looks at both requests and responses to determine whether they match the operation and schema descriptions from the OpenAPI file.
In other words, Prism does both input and output validation. As such, testing your API during development through Prism is helpful even if you already have OpenAPI-driven input validation in your backend. For example, backend stubs generated with Swagger Codegen come with input validation, but the framework doesn't enforce that your API responses fulfill the contract. Prism can step in and offer that additional output validation so you can find errors before the API consumers receive something unexpected.
The backend developers who are working on the API implementation and testing their implementation throughout are obvious users for the validation proxy. However, the frontend developers can also deploy the proxy for themselves. They can switch the mock server with the proxy server and, if their code breaks at this point, will find it easier to debug if the cause is on their side or if the API diverges from the expectations set by the mock. Finally, even a QA team can inject Prism in a test scenario if the developers haven’t, since it’s independent from either implementation, as long as you can change the URLs. That way, any stakeholder can observe and validate the API interactions happening in the test environment. You could even use this to check the quality of third-party APIs. With all that possibilities, let’s see how we can launch an API proxy.
To Prism in proxy mode, run the following command (replacing
openapi.yaml with the actual filename of your API definition file and
http://example.com/ with the real API server):
prism proxy openapi.yaml http://example.com/
Note that you can also use the
-p option similar to the mock command. Also, note that you always have to provide both parameters. Prism will not try to figure out the API server from the servers array in the OpenAPI definition. After launching the server, try requesting it with curl or another HTTP client. Just as in mock mode, you'll see detailed log output. Valid requests and responses pass the proxy as they are. Invalid requests are stopped and logged.
You can even use Prism as a validation proxy with your production environment. In this case, you should launch it with the
`-m` option, which separates CLI and server into two processes for better proxy performance.
Prism and Stoplight
Now that we’ve covered both features of Prism, let’s talk about how this tool fits into other Stoplight products. As mentioned in the mock section, Prism is a part of Stoplight Studio and Stoplight Platform, and you can benefit from Prism's mock server feature when you use these products.
As a stand-alone open-source tool, it is entirely autonomous of any commercial software or cloud platform, and you can use it in your API design and development lifecycle whether you use Stoplight or not. Being a command-line application, it is a versatile building block for any vendor-independent OpenAPI-driven toolchain.
Contributing to Prism
While Stoplight maintains Prism, the open-source repository is open to contributions from the wider API community. The latest versions of Prism are 100% TypeScript, so any TypeScript developer should be able to find their way into the codebase. Like most open-source tools, Prism couldn't exist without the incredible work behind other open-source libraries. You can see a list in the Thanks section in the README file.
Both repository and issue tracker are on GitHub, and there's a guide that outlines the process of contributing to Prism. If you enjoy the tool and want to give back, checking issues tagged with "help wanted" is an excellent way to start.
Also, have a look at our initial Open Source October post for more information about how we’re giving back. For any contributions this month, Stoplight will be planting trees through Ecologi to fight against climate change.