Skip to Content

Configure OpenAPI (REST) DataSource

Published: 2022-06-27

WunderGraph allows you to use REST (OpenAPI) APIs and add them to your "virtual" GraphQL API. This works by introspecing the OpenAPI Specification, parsing it and turning it into a GraphQL API on the fly. WunderGraph does this automatically, so don't worry about the process too much.

All you have to do is point the introspection to the yaml or json file containing the OAS. Once you have it introspected, pass it to the Application and you're good to go.

const jsonPlaceholder = introspect.openApi({
apiNamespace: "jsp",
source: {
kind: "file",
filePath: "jsonplaceholder.v1.yaml",
}
});
const openAPI = introspect.openApi({
apiNamespace: "users",
source: {
kind: "file",
filePath: "users_oas.json"
},
headers: builder => builder
.addStaticHeader("StaticToken","secret") // // inject a static token into all upstream requests
});

Once the configuration is updated, you're able to Query your REST API using GraphQL, how cool is that!?

If you're looking into more details on configuring static and dynamic upstream headers, have a look at the dedicated configuration section on configuring Headers for HTTP-based APIs.

Status-Code Unions: Mapping HTTP Status Codes to GraphQL Unions#

You will notice that the generated API, by default, ignores the fact that multiple responses with different status codes are defined in the OpenAPI Specification. This keeps the API lean and flat, but might not always be ideal.

In some scenarios,status codes returned from a REST API might have meaning, and you want to react to the different status codes accordingly.

However, mapping HTTP Status codes 1:1 from REST to GraphQL would result in an API that doesn't feel very GraphQL-ish. For that reason, we've decided to use Unions and map REST API responses to those.

When introspecting an OpenAPI Specification, set the (optional) field "statusCodeUnions" to true to enable the feature.

const fusionAuth = introspect.openApi({
apiNamespace: "auth",
source: {
kind: "file",
filePath: "fusionauth_v2.yml"
},
statusCodeUnions: true
})

For reference, here's the OpenAPI Specification:

openapi: 3.0.2
info:
title: FusionAuth API
version: 1.31.0
servers:
- url: 'http://localhost:8111'
paths:
/passwordless/start:
post:
requestBody:
content:
application/json:
schema:
type: object
properties:
applicationId:
type: string
loginId:
type: string
state:
type: object
additionalProperties: true
required:
- applicationId
- loginId
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
code:
type: string
'400':
description: BadRequest
content:
application/json:
schema:
type: object
properties:
fieldErrors:
type: object
properties:
applicationId:
type: string
loginId:
type: string

The resulting GraphQL Schema will look like this:

type Mutation {
auth_postPasswordlessStart(postPasswordlessStartInput: auth_postPasswordlessStartInput): auth_PostPasswordlessStartResponse
}
input auth_postPasswordlessStartInput {
applicationId: String!
loginId: String!
}
union auth_PostPasswordlessStartResponse = UnspecifiedHttpResponse | auth_PostPasswordlessStartOK | auth_PostPasswordlessStartBadRequest
type UnspecifiedHttpResponse {
statusCode: Int!
}
type auth_PostPasswordlessStartOK {
code: String
}
type auth_PostPasswordlessStartBadRequest {
fieldErrors: auth_FieldErrors
}
type auth_FieldErrors {
applicationId: String!
loginId: String!
}

Instead of returning on Object Type for the Mutation field, we're returning a Response JSON. For each status code, we're generating an Object Type Definition and add it to the response Union. If a status code is returned that wasn't specified by the OpenAPI Specification, the response type will be of type "UnspecifiedHttpResponse", returning the status code. This way, you're now able to use the inline fragment syntax to get the exact info about the status codes in your GraphQL response.

mutation ($application: String! $login: String!) {
Start: auth_postPasswordlessStart(
postPasswordlessStartInput: { applicationId: $application, loginId: $login }
) {
__typename
... on auth_PostPasswordlessStartOK {
code
}
... on auth_PostPasswordlessStartBadRequest {
fieldErrors
}
... on UnspecifiedHttpResponse {
statusCode
}
}
}

Override the baseURL from an Environment Variable#

In some cases, you might want to override the baseURL from an environment variable. This is useful, e.g. if you're deploying the same application to multiple environments.

Use the following code to override the baseURL:

const jsonPlaceholder = introspect.openApi({
apiNamespace: "jsp",
source: {
kind: "file",
filePath: "jsonplaceholder.v1.yaml",
},
baseURL: new EnvironmentVariable("JSP_BASE_URL"),
});

If the baseURL value is set, it will always take precedence over the URL present in the openAPI specification. If you're using an EnvironmentVariable, like in the example above, the baseURL value will always be loaded at runtime by the Gateway.

configuring mTLS / mutual TLS#

To configure mTLS for your GraphQL API, look at the configuration section on configuring mTLS.


Product

Comparisons

Subscribe to our newsletter!

Stay informed when great things happen! Get the latest news about APIs, GraphQL and more straight into your mailbox.

© 2022 WunderGraph