All posts

Announcing the preview of Synadia Cloud's HTTP Gateway

Synadia
May 7, 2024
Announcing the preview of Synadia Cloud's HTTP Gateway

There is no question the most ubiquitious protocol application developers interact with every day is HTTP. Whether it is cURL'ing an asset off the Web, using the fetch JavaScript API in the browser, or interacting with cloud provider APIs, nearly every developer understands enough HTTP to be productive and HTTP clients exist in virtually every environment.

At Synadia, we still believe NATS continues to be the best way for "building scalable distributed systems without the cruft." But just like how NATS natively supports MQTT, enabling connectivity of IoT clients, a NATS-designed distributed application does not live in a vacuum.

As such, we are thrilled to announce a new core capability of Synadia Cloud we call HTTP Gateway! 🎉 The HTTP Gateway provides an HTTP interface to NATS capabilities including key-value, object store, services, and messaging.

Today we are releasing a preview of key-value and messaging. The other APIs will be released in subsequent weeks. Note, the APIs may be refined during this preview period based on feedback.

Why would you use this?

For those who are familiar with NATS' native WebSocket support and client library, you may be thinking why is HTTP Gateway necessary?

An important distinction between NATS and HTTP, is that HTTP is inherently designed to have stateless interactions between the client and server. For example, a request against an API that returns a JSON representation of a resource. The connection only needs to exist for the duration of that exchange. There are certainly optimizations to amortize the setup cost of the connection such as keep-alive and pipelining many requests for assets, but the model is a once-and-done exchange.

NATS, on the other hand, was designed for long-lived connections enabling high-throughput and low-latency M:N exchange of messages and data and the choice of synchronous or asynchronous interactions. Supporting WebSockets as a transport enabled running a NATS client in the browser, but it still assumes a long-lived connection.

The two predominant motivations driving the development of this component were:

  • enabling access to NATS data services (key-value and object store) and invocation of NATS microservices on the backend via an HTTP API
  • acknowledging there are constrained environments where only an HTTP client is available and there is no ability to install a NATS client

The outcome we wanted was a first-class HTTP interface to NATS without needing to explicitly learn NATS or use a NATS client.

However, being powered by NATS within Synadia Cloud means data and services can be transparently accessible across all major geos, the three major cloud providers, and out to an edge you define without any additional infrastructure or integrations.

How does it work?

Unlike a NATS connection to Synadia Cloud where a user credentials file is used containing the seed and user JWT, interacting with the HTTP Gateway requires an API token which is associated with a user. The token is much more ergonomic to use for HTTP clients.

Check out the short clip to see how to make your first token 👇

With the token created, we can start making requests! Check out the full API documentation, but here are a few example cURL requests to get started.

First let's define the token as a variable to be used below (be sure to use the token you copied).

Terminal window
TOKEN=nhg_M6YAsbwyF4jsRbkJ_GEWWL7NkEUUqhPtvaCbBwRKz2SNyLhs3t94pk7WdqHEV

To create a bucket named users, provide a JSON payload setting the bucket parameters such as the max_bytes (required) and history.

Terminal window
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"max_bytes": 1048576, "history": 10}' \
https://api.ngs.global/v1/kvm/buckets/users

To put a key-value entry with key john.doe, supply the data which will be the associated value.

Terminal window
curl -X PUT \
-H "Authorization: Bearer $TOKEN" \
-d '{"color": "blue"}' \
https://api.ngs.global/v1/kv/users/john.doe

Given a service that listens on greeter which we can simulate using the NATS CLI:

Terminal window
nats --creds cloud.creds \
--server tls://connect.ngs.global \
reply --command='echo hello {{.Request}}' greeter

A request can be sent via the HTTP API to greeter with a body joe doe. The output will be hello john doe.

Terminal window
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Accept: text/plain" \
-H "Content-Type: text/plain" \
-d 'john doe' \
https://api.ngs.global/v1/nats/subjects/greeter

Finally, given a service that is publishing events to ticker, which we can simulate using the NATS CLI:

Terminal window
nats --creds cloud.creds \
--server tls://connect.ngs.global \
pub --count 200 --sleep 1s ticker '{{Count}}'

We can then subscribe via the HTTP API which leverages server-send events (SSE):

Terminal window
curl -X GET \
-H "Authorization: Bearer $TOKEN" \
-H "Accept: text/event-stream" \
https://api.ngs.global/v1/nats/subjects/ticker

JavaScript Client

cURL is great, but a lightweight client library is even more convenient. Today we are also releasing a JavaScript client for the HTTP gateway.

Given the above examples, here are the equivalent calls in JavaScript.

Terminal window
1
import { newNHG } from "@synadiaorbit/nhgc"
2
3
// Initialize the client passing the root URL and the token.
4
const nhg = newNHG("https://api.ngs.global", "<TOKEN>");
5
6
// Create a bucket named "users".
7
const users = await nhg.kvm.add("users", { max_bytes: 1024 * 1024, history: 10 })
8
9
// Put a key-value entry to for `john.doe`.
10
let rev = await users.put("john.doe", `{"color": "blue"}`);
11
12
// Perform a request-reply to subject `greeter`.
13
const rep = await nhg.nats.request("greeter", "john doe");
14
15
// Subscribe to subject `ticker`.
16
const sub = await nhg.nats.subscribe("ticker", (err, msg) => {
17
// Handle error or the message...
18
})

For install instructions and examples check out the GitHub repo.

What's next?

In the coming weeks, the object store and services APIs will be released. Additional examples will be added to the Synadia docs.

We can't wait to see what you build with this new connectivity layer! Please reach out in the #synadia channel in NATS.io Slack if you have questions or feedback!