Webhooks as GraphQL Subscriptions using GraphQL Mesh

Arda Tanrikulu
Webhooks as GraphQL Subscriptions using GraphQL Mesh - The Guild Blog
Looking for experts? We offer consulting and trainings.
Explore our services and get in touch.

GraphQL Mesh lets you query any data source and protocol with GraphQL by using powerful handlers (Swagger/OpenAPI, gRPC, SOAP and others..) Today we are happy to announce that GraphQL Mesh now allows you to consume your existing HTTP Webhooks as GraphQL Subscriptions!

Not only that, but you could extend the GraphQL Subscriptions result so you could subscribe to a webhook and get back an enriched data result, with data from other sources that don’t have push communication abilities.

And it’s also possible even if your webhooks don't have any schema!

Let’s see how to create a GraphQL Subscription from a Webhook, once without a schema and once automatically from an OpenAPI schema.

We are already able to consume our existing REST APIs in GraphQL Mesh even if they don't have any schema by using our JSON Schema Handler. See more

Add a new field to our existing configuration for an HTTP Webhook

In the following example configuration, we have a regular GraphQL Mesh configuration for schemaless REST API.

sources:
  - name: Example
    handler:
      jsonSchema:
        baseUrl: http://localhost:4001
        operationHeaders:
          Content-Type: application/json
        operations:
          - type: Query
            field: todos
            path: /todos
            method: GET
            responseSample: ./todos.json
          - type: Mutation
            field: addTodo
            path: /todo
            method: POST
            requestSample: ./addTodo.json
            responseSample: ./todo.json
            responseTypeName: Todo

Assume that we point our REST API to send HTTP requests to our Mesh server’s /webhooks/todo_added path, so we need to configure Mesh to listen to that path.

serve:
  port: 4000
  handlers:
    - path: /webhooks/todo_added
      pubsubTopic: todoAdded

Under serve we define the port we want Mesh to listen to and add a handler in a declarative way without a single line of code. pubsubTopic is the unique name for that webhook. This topic will receive upcoming HTTP requests so that JSON Schema handler will consume it as a GraphQL Subscription.

Let’s define a new field under Subscription field under operations in the handler level;

operations:
  - type: Subscription
    field: todoAdded
    pubsubTopic: todoAdded
    responseSample: ./todo.json

Now we have a todoAdded field that listens to a webhook through Mesh’s PubSub instance and this field has a return type generated based on todo.json sample response.

You can start mesh serve and start listening for that webhook by the following GraphQL operation;

subscription {
  todoAdded {
    id
    title
    content
  }
}

You can find a complete working example on GitHub

Other methods for Subscriptions such as RabbitMQ or Kafka

It is possible to configure Mesh to handle other schemaless subscription solutions like RabbitMQ and Kafka using JSON Schema handler but this is the topic of another blog post.

Generating GraphQL Subscriptions from OpenAPI Callbacks

Mesh can listen to webhooks through a PubSub engine easily. Mesh will generate the necessary typings and subscriptions fields connected to your PubSub engine from the OpenAPI schema. You only need Mesh to know what path the server should listen to like below;

sources:
  - name: OpenAPICallbackExample
    handler:
      openapi:
        source: ./openapi.yml
        baseUrl: http://localhost:4001

serve:
  port: 4000
  handlers:
    - path: /callback
      pubsubTopic: http://localhost:4000/callback

In this example configuration, we assume that we have an API server running on 4001 port and it has a webhook that will forward requests from /callback path to http://localhost:4000/callback topic because OpenAPI Handler uses callback url as PubSub topic name. If you want to have a more customized way of handling incoming webhook requests, you can always write your own Express handler and define it instead of pubsubTopic. You will find Mesh’s PubSub engine under the request object as request.pubsub.

You can check this example for more

Now you

We would love to hear your use cases and feedback to make Mesh better and more powerful! Feel free to submit issues on GitHub to share your ideas or you can also join our community channel on Discord!