The Guild LogoThe Guild Monogram
GraphQL Mesh

GraphQL Mesh

Query anything, run anywhere.

Contact Us

OpenAPI / Swagger#

image

This handler allows you to load remote or local OpenAPI (2/3) and Swagger schemas. Based on OpenAPI-to-GraphQL .

You can import it using remote/local .json or .yaml.

To get started, install the handler library:

yarn add @graphql-mesh/openapi

Now, you can use it directly in your Mesh config file:

sources: - name: MyOpenapiApi handler: openapi: source: ./my-schema.json

 


 

Overriding default Query/Mutation operations#

By default, OpenAPI-to-GraphQL will place all GET operations into Query fields and all other operations into Mutation fields; with this option, you can manually override this process. To switch between Query and Mutation operations, and vice versa, you need to define a rule per override, consisting of the OAS title, the path of the operation, the method of the operation and finally, the destination type (e.g., Query or Mutation). See the example below:

sources: - name: MyOpenapiApi handler: openapi: source: ./my-schema.json selectQueryOrMutationField: - title: "Weather Service v1" # OAS title path: /weather/current # operation path method: post type: Query # switch method POST from default Mutation into Query - title: "Weather Service v1" # OAS title path: /weather/forecast # operation path method: get type: Mutation # switch method GET from default Query into Mutation

 


 

Dynamic Header Values#

Mesh can take dynamic values from the GraphQL Context or the environmental variables. For example, if you use mesh dev or mesh start, GraphQL Context will be the incoming HTTP request.

The expression inside dynamic values should be as in JS.

 

From Context (HTTP Header for mesh dev or mesh start)#

sources: - name: MyGraphQLApi handler: openapi: source: ./my-schema.json operationHeaders: # Please do not use capital letters while getting the headers Authorization: Bearer {context.headers['x-my-api-token']} # You can also access to the cookies like below; # Authorization: Bearer {context.cookies.myApiToken}

And for mesh dev or mesh start, you can pass the value using x-my-graphql-api-token HTTP header.

 

From Environmental Variable#

MY_API_TOKEN is the name of the environmental variable you have the value.

sources: - name: MyGraphQLApi handler: openapi: source: ./my-schema.json operationHeaders: Authorization: Bearer {env.MY_API_TOKEN}

 


 

Advanced cookies handling#

When building a web application, cookies are often used for authentication for security reasons. On the other end, mobile applications tend to use an HTTP header.

This section shows how to configure GraphQL Mesh to accept either and use GraphQL Mesh to set/unset cookies on the login & logout mutations.

 

Accepting one of the cookies, header, or context value#

We want to accept one of the following:

  • an accessToken cookie
  • an Authorization header
  • an authorization value available in context (e.g. set by a GraphQL auth plugin)

And transmit it to the Rest API as an Authorization header. GraphQL Mesh does not allow dynamic selection in the meshrc.yaml file, but that's fine! We can use a bit of trickery.

sources: - name: Rest handler: openapi: source: ./openapi.yaml baseUrl: "{env.REST_URL}/api/" operationHeaders: Authorization-Header: "{context.headers.authorization}" Authorization-Cookie: Bearer {context.cookies.accessToken} customFetch: ./src/custom-fetch.js

Here in the meshrc.yaml configuration we store the cookie in Authorization-Cookie, and the header in Authorization-Header. To introduce the logic needed to generate the proper Authorization header for the Rest API, we need to implement a customFetch. It will replace the fetch used by GraphQL Mesh to call the Rest API.

const fetch = require('node-fetch') module.exports = (url, args, context) => { // Set Authorization header dynamically to context value, or input cookie, or input header args.headers['authorization'] = context.authorization || args.headers['authorization-cookie'] || args.headers['authorization-header']; // Clean up headers forwarded to the Rest API delete args.headers['authorization-cookie']; delete args.headers['authorization-header']; // Execute the fetch with the new headers return fetch(url, args) }

Of course, node-fetch needs to be added to your project:

yarn add node-fetch

 

Of course, using GraphQL Mesh as a Gateway for both the mobile application and web application is excellent. Still, there's one thing missing: the setting of the cookie for the web application.

We need to access the HTTP response that is sent back to the client. Luckily, we can do so in additionalResolvers. So we need to create two new resolvers, one for login and one for logout, and manage the cookie in their code.

The first step is to edit the meshrc.yaml file, add this at the end:

additionalTypeDefs: | extend type Mutation { login(credentials: Credentials!): String logout: Boolean } additionalResolvers: - ./src/additional-resolvers.js

Then manage the cookie in the new resolvers:

// lifespan of our cookie const oneYear = 365 * 24 * 3600 const resolvers = { Mutation: { async login(root, args, context, info) { // Call the Rest API's login operation const result = await context.Rest.Mutation.accountLogin({ root, args: { credentials: args.credentials }, context, info }) // if `result` contains a JWT token, you could instead decode it and set `Expires` // to the JWT token's expiration date res.set('Set-Cookie', `accessToken=${result}; Path=/; Secure; HttpOnly; Max-Age=${oneYear};`) return result }, logout(root, args, { res }) { // use old date to unset cookie res.set('Set-Cookie', `accessToken=logout; Path=/; Secure; HttpOnly; Expires=Thu, 1 Jan 1970 00:00:00 GMT;`) return true }, }, } module.exports = { resolvers }

 


 

Examples#

We have a lot of examples for OpenAPI Handler;

 


 

Config API Reference#

  • source (type: Any, required) - A pointer to your API source - could be a local file, remote file or url endpoint
  • sourceFormat (type: String (json | yaml)) - Format of the source file
  • operationHeaders (type: JSON) - JSON object representing the Headers to add to the runtime of the API calls
  • schemaHeaders (type: JSON) - If you are using a remote URL endpoint to fetch your schema, you can set headers for the HTTP request to fetch your schema.
  • baseUrl (type: String) - Specifies the URL on which all paths will be based on. Overrides the server object in the OAS.
  • qs (type: JSON) - JSON object representing the query search parameters to add to the API calls
  • customFetch (type: Any) - W3 Compatible Fetch Implementation
  • includeHttpDetails (type: Boolean) - Include HTTP Response details to the result object
  • addLimitArgument (type: Boolean) - Auto-generate a 'limit' argument for all fields that return lists of objects, including ones produced by links
  • genericPayloadArgName (type: Boolean) - Set argument name for mutation payload to 'requestBody'. If false, name defaults to camelCased pathname
  • selectQueryOrMutationField (type: Array of Object) - Allows to explicitly override the default operation (Query or Mutation) for any OAS operation:
    • title (type: String) - OAS Title
    • path (type: String) - Operation Path
    • type (type: String (query | mutation | Query | Mutation)) - Target Root Type for this operation
    • method (type: String) - Which method is used for this operation
  • provideErrorExtensions (type: Boolean) - Overwrite automatic wrapping of errors into GraphqlErrors
  • operationIdFieldNames (type: Boolean) - Field names can only be sanitized operationIds

By default, query field names are based on the return type type name and mutation field names are based on the operationId, which may be generated if it does not exist.

This option forces OpenAPI handler to only create field names based on the operationId.