There are many pros and cons for both [GraphQL](https://graphql.org/)GraphQL and REST APIs, but one of the areas where GraphQL really shines is API composition. Taking data from multiple APIs and combining them to make something new is a key part of delivering a useful service.
Today, we're going to take a look at [StepZen](https://stepzen.com/)StepZen, a product that allows you to build GraphQL APIs composed of REST, Database, and other GraphQL sources. We'll use it to build an API endpoint that shows the price of an item in a user's local currency based on their IP address. GraphQL remains an emerging technology, and adoption is still lagging behind RESTful APIs. Kong provides the [degraphql](https://docs.konghq.com/hub/kong-inc/degraphql/)degraphql plugin which allows us to convert the GraphQL API we build with StepZen back into a REST API, which may be more comfortable for users of our API.
The schema tab in GraphQL Studio allows you to see the data available from each API. I'd like to call your attention to the *priceInCountry* field in the *IpApi_Location* type. *priceInCountry* is defined as a *materializer*, which is a custom StepZen directive that acts like a function. *priceInCountry* takes arguments provided by the caller and combines them with the currency field in the current schema by calling the *frankfurter_convertedAmount** query* to calculate a local price.
The materializer definition is included in the schema itself inside type Query, and uses JavaScript to call an API and transform the data:
frankfurter_convertedAmount(
amount: Float!
from: String!
to: String!
): Float
@rest(
cel:"""
function transformREST(s) { var data = JSON.parse(s)
let toCurrency = get('to')
let amount = get('amount')
let convertedAmount = (data["rates"][toCurrency]||1.00) * amount
return JSON.stringify(convertedAmount)
}"""
endpoint:"https://api.frankfurter.app/latest?from=$from" )
We're going to use this materializer to build a query that accepts an amount, source currency, and IP address and returns the identified country code and price in that country:
We'll walk through how to run this query in the next section, but first, we need to deploy our new API.
## Deploying your API
GraphQL Studio is great, but it's not intended for production deployments. To ship our API, we need to import it as a data source into our own StepZen account using the CLI. The GraphQL endpoint URL is available in the top bar in GraphQL Studio.
To do this, we run stepzen import graphql to tell StepZen that we want to build a new API on top of an existing GraphQL API. This will generate some schema files locally based on the GraphQL endpoint URL that you provide.
stepzen import graphql
? What would you like your endpoint to be called? demo/converter
? What is the GraphQL endpoint URL? https://graphqldd.stepzen.net/api/dd1cf47f51ac830fe21dc00ec80cee65/__graphql? Prefix to add to all generated type names (leave blank for none)
? Add an HTTP header, e.g. Header-Name: header value (leave blank for none)
Starting... done
Successfully imported schema graphql from StepZen
However, if I visit that URL I can see that my requests need to be authenticated. We want to make this a public API, but only if it's accessed through our API gateway. We can automatically add an authentication header, but first, we need to run Kong Gateway.
## Running Kong Gateway
The quickest way to get started with Kong Gateway is to run the following command (you'll need docker installed):
curl -Ls https://get.konghq.com/quickstart | sh -s -- -i kong-gateway
This will create two Docker containers – a database to store configuration and Kong Gateway itself. Once you see the "✔ Kong is ready!" message, we can configure a route that proxies requests through to StepZen.
> Port 8001 is the administration port for Kong Gateway, while port 8000 is used to proxy requests to their destination
First, run *stepzen whoami –apikey* to fetch your StepZen credentials. Configure the Request Transformer plugin with the StepZen key using the *config.append.headers* setting:
Everything we've done up until now can be done with the free version of Kong, but we're about to move on to some enterprise features. If you want to code along, make sure to apply your license to your locally running instance:
export KONG_LICENSE_DATA='{"my":"license"}'
curl -X POST localhost:8001/licenses -d payload=$KONG_LICENSE_DATA
## Convert GraphQL to REST
As I mentioned earlier, our existing customers are used to consuming REST APIs and aren't too familiar with how to write GraphQL queries. In order to keep things simple for them, we'll use Kong Gateway to convert our StepZen GraphQL API to a REST API using the [degraphql](https://docs.konghq.com/hub/kong-inc/degraphql/)degraphql plugin.
The degraphql plugin allows you to create traditional REST-based routing rules, map them to GraphQL queries, and forward the queries to a server. Before installing the plugin, we need to modify the existing graphql-demo service, setting the target URL to the domain-only portion of our StepZen URL.
Once this is done, we can activate the degraphql plugin on our service by providing the path to our demo endpoint in the *graphql_server_path* configuration option:
Once degraphql is activated, requests to our/price endpoint will return a 404 response rather than proxying to the upstream server. This is because we haven't mapped any REST requests to an underlying GraphQL query yet.
To map a path to a query, we can make a POST request to* /degraphql/routes*:
curl -X POST http://localhost:8001/services/graphql-demo/degraphql/routes \--data uri="/gbp/:ip/:amount" \
--data query='query($amount:Float!,$ip:String!){converted:ipApi_location(ip:$ip){countryCode price:priceInCountry(amount:$amount,from:"GBP")}}'
Note how the *:ip* and *:amount* entries in the *uri* parameter start with a colon. This means that the values in these segments will be passed into the query as named parameters. We can now make a normal GET request and watch as Kong makes a GraphQL request on our behalf:
Our customers can now interact with our upstream GraphQL endpoint as though it was a REST API, but there's just one thing about the response that's bothering me. GraphQL responses always contain a data key, but in our example, there's only a single key inside the data.
Let's use Kong's jq plugin to perform some post-processing on the response before responding to our caller. The [jq plugin](https://docs.konghq.com/hub/kong-inc/jq/)jq plugin allows you to transform JSON data on request and response objects. We'll use a short jq operation to return everything inside the *.data key:*
We set out to compose an API from multiple different sources, then expose that as a simple REST endpoint for consumers. Using a combination of StepZen's materializers and Kong Gateway plugins, we've managed to deliver exactly what our consumers need without adding a single line of code to our application.
We're pleased to announce the launch of Standard Webhooks! Kong has been part of the Technical Committee of this standard with other great companies like Svix (the initiator of the project), Ngrok, Zapier, Twillio, Lob, Mux, and Supabase. This was
Modern software design relies heavily on distributed systems architecture, requiring all APIs to be robust and secure. GraphQL is no exception and is commonly served over HTTP, subjecting it to the same management concerns as any REST-based API. In
There are many different ways to deploy Kong Gateway. In this post, Viktor Gamov (Principal Developer Advocate at Kong) walks through the four most popular ways. Depending on your particular use case, you may find that one or more of these is a goo
Kong Enterprise provides customers with the fastest, most scalable and flexible API management solution in the market. One of Kong's main advantages is the ability to quickly deploy and integrate with a customer's ecosystem of already-deployed solut
Routing Tricks and Tips Kong is very easy to get up and running: start an instance, configure a service, configure a route pointing to the service, and off it goes routing requests, applying any plugins you enable along the way. But Kong can do a lo
Traditional agreement processes were slow and heavily manual. Documents were often created in office tools, shared through email, printed, signed physically, and stored across multiple systems. Tracking the status of agreements required manual follo
Imagine you have a single Service, order-api . You want to apply a strict rate limit to most traffic, but you want to bypass that limit—or apply a different one—if the request contains a specific X-App-Priority: High header. Previously, you had t