This tutorial shows how to start using ZebraStream as a basic relay in a few minutes. We only use curl as a command line HTTP client to showcase the data transmission functions, but any HTTP client or library can work.
Create Stream Access Tokens
This step assumes, that you have completed the setup and a working zebrastream-cli
.
With the Management API key, we can now issue permissions for stream addresses. We select an example stream address called /mystream
and start with a simple pair of access tokens, one for writing to the stream and one for reading from the stream. Make sure, that the path starts with a root /
:
zebrastream-cli create-token --path /mystream --access-mode write --expires 2027-12-31
If successful correctly, the program returns the access token like this
Created Access Token
Token ID: key_eengeu0xeiphaiXi
Path: /userspace/mystream
Token:Chohph3meephith7caecoohi
You see that the returned stream address is prefixed by the account's private namespace. The full address is needed for data transfer. Save the key token in a secret place.
We do the same for the reading token, just by replacing the mode "write" with "read".
zebrastream-cli create-token --path /mystream --access-mode read --expires 2027-12-31
We get a second token in return that refers to the same stream path.
Created Access Token
Token ID: key_Ahg5pohighoothoo
Path: /userspace/mystream
Token: kie0EesheiV3Aewoh4utiYah
In a real world application, we could hand over those access tokens to the parties that exchange data via the stream address.
List Access Tokens
Double check by listing the created access tokens
zebrastream-cli list-tokens
which should return the following
Access Tokens:
Token ID, Path, Access Mode, Recursive, Expires
key_Ahg5pohighoothoo, /userspace/mystream, read,✗, 2027-12-31 00:00:00
key_eengeu0xeiphaiXi, /userspace/mystream, write, ✗, 2027-12-31 00:00:00
Example Workflow
Since producing and consuming data is done via HTTP requests, we can also use curl here. Before transitioning to streams, it's typically easiest to start with a simple file transfer. We assume the sender has a local file called data.json
for the receiver.
Data Producer
The sender issues a one-line data producer curl command, providing the write token in the authorization header.
curl --request PUT --upload-file data.json --no-buffer --http1.1 --expect100-timeout 180 --header 'Authorization: Bearer Chohph3meephith7caecoohi' 'https://data.zebrastream.io/v0/userspace/mystream'
Basically, this command tells curl to
- output relay status messages instantly on the command line
- transfer the data via HTTP/1.1 protocol
- wait for the server when it is ready to receive the payload data for 3 minutes
- authorize with the generated writer access token
Most of these settings are optional, but it's best practice to state them explicitly.
Data Consumer
While the producer is waiting, the the receiver can connect similarly with the read token.
curl --request GET --header 'Authorization: Bearer kie0EesheiV3Aewoh4utiYah' --output data-received.json 'https://data.zebrastream.io/v0/userspace/mystream'
As you can see, the consumer command is much simpler, in fact, we could just do
curl 'https://data.zebrastream.io/v0/userspace/mystream?accesstoken=kie0EesheiV3Aewoh4utiYah'
The latter is the form for systems that don't allow you to specify custom headers. You could also just paste that URL into a web browser to download the file.
Wrap-up
This walk-through shows how easy it is to implement a simple data exchange channel using ZebraStream and HTTP. Just exchange the stream address and access token with the other side. Think of a stream path as the analog of a filesystem path, where the stream object is the filename at the end. If you are familiar with UNIX named pipes, you will feel quite comfortable. Stream access can also be granted in recursive mode (like a folder). Therefore, you can create stream folders to isolate different applications in namespaces and tune access permissions for producers and consumers.
A Note About Timing
The mechanism here only uses the core relay functionality. This means, that it relies on correct synchronization of sender and receiver when connecting. If one side is waiting for the other to connect, and it doesn't show up, the relay will terminate the connection. This is acceptable for situations, in which the transfer is triggered by an observable event, like wall clock time. For more complex scenarios, like push and pull workflows, we offer our Connect API.