• Stars
    star
    177
  • Rank 215,985 (Top 5 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created over 6 years ago
  • Updated 6 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A friendly siege weapon to get 2-way communication through tough firewalls and bad mobile networks

trebuchet-client

A friendly siege weapon to get 2-way communication through tough firewalls and bad mobile networks

Why?

  • "IT professionals" who believe they can secure their company by blocking WebSockets haven't retired yet.
  • A WebSocket doesn't guarantee a long-lived connection.
  • A WebSocket with a ping doesn't guarantee a message will get delivered.

What's it do?

  • Establishes a 2-way communication with a client no matter what
  • Uses a heartbeat to keep the connection open
  • Creates a new connection if closed without reason (e.g. a firewall ends a long-running connection or the server restarts)
  • Stop future connections if closed with reason (e.g. kicked off, blacklisted in real-time, etc.)
  • Queues unsent messages
  • Provides a clean API to let the user know they've been disconnected or reconnected
  • Supports WebSockets, WebRTC, and SSE. SSE will always work (barring a MITM attack). See Browser Support
  • Uses thunks for tree-shaking so you don't import trebuchets that you don't use
  • Supports custom encoding (ie binary data) where possible (SSE does not support binary)
  • Supports reliable messaging so you can be sure clients get the message

Installation

yarn add @mattkrick/trebuchet-client

API

  • getTrebuchet(thunks): given an array of trebuchets, it tries them in order & returns the first that works
  • SocketTrebuchet({getUrl, encode, decode, batchDelay}): a constructor to establish a websocket connection
    • encode: An encoding mechanism, defaults to JSON.stringify
    • decode: A decoding mechanism, defaults to JSON.parse
    • batchDelay: default is -1 (no delay), pass 0 or higher to wrap in a setTimeout (0 waits until next tick, highly recommended, if the server supports it)
  • SSETrebuchet({getUrl, fetchData, fethcPing, fetchReliable}): a constructor to establish server-sent events

Example

import getTrebuchet, {SocketTrebuchet, SSETrebuchet, WRTCTrebuchet} from '@mattkrick/trebuchet-client'

const trebuchets = [
  () => new SocketTrebuchet({getUrl:  () => 'wss://my-server.co', enocde: msgpack.encode, decode: msgpack.decode, batchDelay: 10}),
  () => {
    const getUrl = () => 'https://my-server.co'
    const fetchReliable = (connectionId, data) => fetch(`/sse/?reliable=true&id=${connectionId}`)
    const fetchPing = (connectionId) => fetch(`/sse/?ping=true&id=${connectionId}`)
    const fetchData = (data, connectionId) => fetch('/dataRoute', {
      method: 'POST',
      headers: {
        'content-type': 'application/json',
        'x-correlation-id': connectionId || ''
      },
      body: JSON.stringify(data)
    })
    return new SSETrebuchet({getUrl, fetchData, fetchPing, fetchReliable})
  },
  () => {
    const fetchSignalServer = (signal) => fetch(`/rtc`, {method: 'POST', body: JSON.stringify(signal)})
    return new WRTCTrebuchet({fetchSignalServer})
  }
]

const siege = async () => {
  const trebuchet = await getTrebuchet(trebuchets)
  if (trebuchet) {
    trebuchet.send('it works!')
    trebuchet.on('data', () => {
      console.log('the walls have fallen')
    })
    trebuchet.on('disconnected', () => {
      console.log('the firewall tore us apart')
    })
    trebuchet.on('reconnected', () => {
      console.log('but our bond cannot be broken')
    })
    trebuchet.on('close', ({code, reason}) => {
      if (reason) {
        console.log(`I lied. It's not you, it's the server: ${reason}`)
      }
    })
  } else {
    console.log('the siege failed, try adding more trebuchets!')
  }
}

Details

  • The ping is a single byte arraybuffer sent from the server. The client must reply within 10 seconds
  • Reliable messages include an ACK and REQ which are 4 byte payloads each.
    • If the server sends a reliable message, it will include a message id. The client will reply with an ACK that includes the message id.
    • If the id is not the previous id + 1, the client will queue that message & send a REQ for the first missing message. This guarantees message ordering.

Browser Support

Some browsers, namely IE11 and Edge, do not support EventSource (SSE) natively. To fix that, you'll need to polyfill it. See @mattkrick/event-source-polyfill.

More Repositories

1

meatier

🍔 like meteor, but meatier 🍔
JavaScript
3,059
star
2

redux-optimistic-ui

a reducer enhancer to enable type-agnostic optimistic updates
JavaScript
693
star
3

cashay

💰 Relay for the rest of us 💰
JavaScript
453
star
4

redux-operations

Solves challenging redux problems in a clean, understandable, debuggable fasion.
JavaScript
125
star
5

fast-rtc-swarm

A full-mesh WebRTC swarm built on top of fast-rtc-peer
TypeScript
101
star
6

lolliclock

A material design timepicker based on clockpicker
JavaScript
40
star
7

fast-rtc-peer

a small RTC client for connecting 2 peers
TypeScript
34
star
8

fast-bitset

A fast bitset with some nice methods
JavaScript
34
star
9

cashay-playground

The playground for exploring what's possible with Cashay
JavaScript
33
star
10

EdmondsBlossom

Edmond's maximum weighted matching algorithm (Blossom algorithm) in O(n^3)
JavaScript
30
star
11

redux-socket-cluster

A socket-cluster state snatcher
JavaScript
30
star
12

dataloader-warehouse

A class for sharing dataloaders across GraphQL subscriptions
TypeScript
29
star
13

rich

A decentralized collaborative rich text editor powered by DOM mutations, CRDT, and WebRTC
TypeScript
22
star
14

sanitize-svg

a small script to prevent stored XSS attacks and detect script tags in SVGs
TypeScript
19
star
15

redux-operations-counter-example

An example of solving current redux shortcoming using redux-operations
JavaScript
16
star
16

graphql-trebuchet-client

A graphql client to get your subscriptions through tough firewalls and unreliable mobile networks
TypeScript
14
star
17

react-portal-hoc

A stupid HOC to make a stupid portal so you can make stupid modals
JavaScript
14
star
18

event-source-polyfill

A minimum immplementation of EventSource for IE11 and Edge
TypeScript
13
star
19

react-githubish-mentions

A wrapper for a textarea to offers autocomplete suggestions when triggered by @ or # or whatever
JavaScript
13
star
20

json-deduper

Compress JSON trees by deduplicating nested objects, strings, and numbers
TypeScript
11
star
21

react-hotkey-hoc

mousetrap wrapper for react
JavaScript
10
star
22

dynamic-serializer

crawls a JSON tree replacing dynamic values with a deterministic integer
JavaScript
9
star
23

react-async-hoc

a hoc for async globals
JavaScript
6
star
24

meteor-leaflet-maps

Leaflet, now with lazy loading & namespacing!
JavaScript
6
star
25

relay-linear-publish-queue

Publish changes in the order they're received.
TypeScript
4
star
26

surviveJS-redux

A redux version of the awesome surviveJS tutorial for react & webpack.
JavaScript
3
star
27

hungarian-on3

The hungarian (Kuhn-Munkres) algorithm solved in O(n^3) time
JavaScript
3
star
28

rethinkdb-ts-migrate

Migrations for rethinkdb-ts
TypeScript
3
star
29

meteor-vital-signs

JavaScript
2
star
30

meteorTooltips

Meteor tooltips that turn any template into a tooltip
JavaScript
2
star
31

visage

Signaling + SFU for turnkey WRTC (WIP)
TypeScript
2
star
32

event-target-polyfill

EventTarget polyfill for IE11 and Edge from https://developer.mozilla.org/en-US/docs/Web/API/EventTarget#Example
TypeScript
2
star
33

hepha

Aphrodite for global styles
JavaScript
1
star
34

performant-material-input

A feature-rich material design input box with hardware acceleration
CSS
1
star
35

todo-modern-subs

JavaScript
1
star