Zap = JSON message headers + WebSockets + Custom Events
Zap is a real-time WebSockets-based communication platform for the web. The optional client libraries compliment our managed socket servers to bring powerful new features with minimal fuss. Zap provides several features on top of raw sockets using a JSON-based header, but library-less raw WebSocket code works as well.
-
What does JSON have to do with Sockets?Zap uses JSON to prepend meta to a raw WebSocket message without altering or repacking the message data, allowing rapid message turnaround
-
Do I have to send everything in JSON?Not at all; the client library uses a small header to provide several handy features. Only the header is JSON, unless you pass a JS Object as data. This allows the zap server to inspect and react to data in the header without unpacking or even looking at the data itself. You can send strings, rich object data, even un-touched Blobs.
-
What does Zap do that plain WebSockets doesn't?
- custom event meta (JSON header) - instead of just plain string/binary data, rich details like filename can travel with raw data, and directives customize behavior
- custom named events - not just a generic data event but meaningful custom and built-in events
- presence events - fire when a user leaves or joins a channel so you know who's out there, compliments
.users
to provide instant ID checking - stronger data - seamless send and receive strongly-typed data when passing numbers, booleans, blobs, and objects, instead of WebSocket's string-only handling
- easy private (p2p) - easily send a message to just one device instead of the entire channel using a
_TO:[strIDs]
whitelist header directive - cross-channel messaging - send to other channels using a
_CHAN: strChanId
header directive, subscribe to others using.pipe(channel)
- cross-tab pipelines - run several realtime apps on multiple tabs/windows using a single socket connection instead of 1 or more per tab
- stability - auto-reconnect, sane defaults, gap-filling, and built-in error handling keeps your app connected and your users informed
- persistence - cache 128 messages per channel under string keys via
_KEY:name
header directive,.get()
it back later or elsewhere as a Promise resolve - archiving - Store any message forever via
_SAVE:str_index
directive, SELECT one or many back later using the built-in Promise-based.query()
interface
What languages are supported by the library?Javascript. The zap client library works with web browsers, web worker threads, and node.js (with ws and w3c-xmlhttprequest NPM packages). Other languages can use the simple HTTP APIs to send events, query saved data, fetch channel key/value cache, and make short one-time subscriptions to arbitrary events via delayed connection closing. A simple html FORM can broadcast events to socket-connect clients without javascript, so you know the http API is simple.What built-in events are provided by the client?- _READY: Fired when all init config has been sent and the socket is ready to use, complete with presence info
- _DATA: Fired when your client receives raw WebSocket data sent without using the zap client library, passed the raw event data as a String or Blob
- _OPEN: Fired when your client connects to the server, passed socket open event details
- _CLOSE: Fired when your client disconnects to the server, passed socket close event details
- _ERROR: Fired when your client has a WebSockets-based error, passed socket error event details
- _JOIN: Fired when you or another person joins the channel
- _LEAVE: Fired when another person leaves the channel
What JSON header directives can I use when sending events?- _TO: An array of device IDs that should get the message, to the exclusion of everyone else.
- _CHAN: A string channel name that over-rides the currently connected socket channel.
- _SAVE: A string index property that flags the entire message to be archived and available to the .query() Promise interface.
- _KEY: A string key name that flags the message to be temporarily stored as a simple one-deep key/value pair, available to the .get Promise interface
What JSON header directives can I utilize when receiving events?- _FROM: A string deviceID, set by someone sending you a message using a _TO directive. the _TO is replaced by _FROM, like an address in a BCC email.
- _CHAN: The channel sending the message, used to de-multiplex, log, and verify sending channels with this un-spoofable server-created value
- _ID: A high-resolution server-generated microsecond time-stamp guaranteed to unique within a channel, for identification and chronological sorting.
How are the events called, and what data are they passed?Custom event are called with 3 arguments:callBack( data, header, e)
- data Whatever was sent, be it a string, number, array, object, Blob/Buffer, etc.
- header The original JSON meta that was sent, possible modified by the server (ex: TO into FROM).
- e The original low-level socket event that triggered the custom event, contains raw e.data, link to e.target, etc.
What commands does zap provide?- send (name/meta, data) Sends an event and/or value to other clients in the channel. Locally rasies the event to so that send() hits every device, including the sender's.
- reconnect () Drop the connection (if any) and re-connects to the zap server. Results in a new zap.id being assigned.
- close() Drop the connection. If Zap.autoConnect is true, re-connects to the zap server.
- on (evtName(s), handler) Given a single or array of event names, bind the handler function to be invoked and passed data when the named event(s) fires.
- once (evtName(s), handler) Same as on(), but only hits the next time the named event(s) fires, then un-subscribes itself.
- off (eventName, handler) Given an event name and handler function, un-subscribes the handler from reacting to future event invocations.
- raise (name/meta, data, domEvent) Triggers an event without sending data over the socket.
- get (key) Given a single stored key, returns a promise to grab that value. Data is stored by using a _KEY : strName param on the message header.
- query() Retrieves data stored using _SAVE:strIndexName param on the message header. Uses a variety of filters and transforms via chain-able interface.
- pipe (channelName) Names another channel to pipe into the current Zap instance - lets you receive events on non-default channels, use _CHAN directive to send().
- unpipe (channelName) un-subscribes to non-defulat channel messages that were subscribed to via pipe().
What properties does zap provide?- readyState (number) Indicates connect state. 0=waiting to connect, 1=connected, 2=error.
- channel (string) The string name of the currect default channel, specified in new Zap() and/or the WebSocket URL.
- config.baseURL (string) The URL root segment of the current Zap server
- socket (WebSocket) A refernce to the actual WebSocket used by Zap. good to send() and listen outside of Zap for debugging or compatibility.
- id (string) The connection ID, a 10-char random that changes every re-connect, no good for user tracking, it's used internally by the Zap server.
- offset (number) The number of milliseconds that the user's clock is off compared to the Zap server.
- lag (number) An estimated round-trip time in milliseconds from user1-zap-user2.
- pipes (object) A simple key:value pair keyed by non-default channel name, value indicates currently active or not.
- users (object)Tracks the currently connected users/devices in a channel via connection ID.
What config options does zap provide?Zap provides the Zap.config object to configure options- config.baseURL (string) The URL root segment of the current Zap server
- config.useLocalEvents (boolean - false) If enabled, all zap channels on a single domain on a device will pipe events through a single socket instead of one-per-channel
- config.autoConnect (boolean - true) If disabled, sockets won't connect until open() is called, using http to send() data instead.
- config.httpPushEnabled (boolean - true) If disabled, Zap will not fallback to http is autoConnect is disabled, allows local-only events w/ useLocalEvents
What expansion options does zap provide?Zap provides three main paths of extending the functionality:- Zap.prototype All instance of Zap inherit from the prototype, allowing easy app-wide method creation.
- Plugins Loaded with the http client, plugins offer pre-built utils for audio feedback, compression, and desktop notifications.
- Hooks Zap provides several hooks to internal functionality, allow you to alter/cancel/overload/intercept the program flow where needed.
What internal hooks are available?Hooks allow outside functionality to be injected into the normally-concealed internal program flow.- create fires on instances just before the constructor returns, use to add new commands and/or edit functionality.
- message intercepts raw socket messages, before they are handed to the request parser. passed message, expects string or Blob return or null to abort.
- event fires on all events before user events, allows modification of header (via shared object access) and or data (via return) for normally-bound event handlers.
- send intercepts sends, allowing modification of data (return) and header (via shared object access) before sending.
- connect runs before connecting, return null to avoid connection, return true to go ahead and connect. can be used to schedule partial-day connections.
What kinds of plugins are available?When you load the zapjs client, you can also load one or many plugins on the same HTTP fetch. These plugins add features to zap, like indexedDB storage integration, random data generation, even a simple beep() command. See the list of plugins for more info.How much does the client library weigh?10kb before any minification or compression. It doesn't need any other scripts like jQuery to run, just the small lib or none at all if you prefer.Do I need to use the client library?No, you can just connect to a zap server in JavaScript, ex:var zap=new WebSocket(theURL);
. For mixed-use, note that messages sent by the zap client will have a JSON header on first line of the message, and the normal socket data thereafter. The client library cleans these up for you, and routes the event if needed. If none of your client use the lib, the zap server behave like a normal socket server.Who can see the messages I send?For broadcast messages, anyone in the channel (specified by the zap server URL's path, or on a per-message basis). For private messages (using a _TO magic header), only the clients you explicity white-list will get the message.How do I know who a private message is from?You can see a list of IDs of everyone in the channelzap.users
, and when sending a private message, the SERVER adds an un-fake-able _FROM: "your_ID" property to the outgoing message header.How do I connect non-browsers to the channel?There may be WebSocket tools for your platform, and there's likely JSON tools, so rolling your own client should be easy. Node.js can use the existing JS client, and everyone else can use the HTTP API options to send, subscribe, store, and fetch.