1.1.0 • Published 4 days ago

braid-http v1.1.0

Weekly downloads
-
License
-
Repository
github
Last release
4 days ago

Braid-HTTP

This polyfill library implements the Braid-HTTP v04 protocol in Javascript. It gives browsers a braid_fetch() drop-in replacement for the fetch() API, and gives nodejs an http plugin, allowing them to speak Braid in a simple way.

Developed in braid.org.

Installing

Browsers:

<script src="https://unpkg.com/braid-http/braid-http-client.js"></script>
<script>
  // To live on the cutting edge, you can now replace the browser's fetch() if desired:
  // window.fetch = braid_fetch
</script>

Node.js:

npm install braid-http
// Import with require()
require('braid-http').fetch       // A polyfill for require('node-fetch')
require('braid-http').http_client // A polyfill for require('http') clients
require('braid-http').http_server // A polyfill for require('http') servers

// Or as es6 module
import {fetch, http_client, http_server} from 'braid-http'

Using it in Browsers

This library adds a {subscribe: true} option to fetch(), and lets you access the result of a subscription with two new fields on the fetch response:

  • response.subscribe( update => ... )
  • response.subscription: an iterator that can be used with for await

Example Subscription with Promises

Here is an example of subscribing to a Braid resource using promises:

fetch('https://braid.org/chat', {subscribe: true}).then(
    res => res.subscribe(
        (update) => {
            console.log('We got a new update!', update)
            // {
            //   version: ["me"],
            //   parents: ["mom", "dad"],
            //   patches: [{unit: "json", range: ".foo", content: "3"}]
            //   body:    "3"
            // }
            //
            // Note that `update` will contain either patches *or* body
        }
    )
)

If you want automatic reconnections, this library add a {retry: true} option to fetch().

fetch('https://braid.org/chat', {subscribe: true, retry: true}).then(
    res => res.subscribe(
        (update) => {
            console.log('We got a new update!', update)
            // Do something with the update
        }
    )
)

For use in conjunction with {retry: true}, it's possible to make the parents param equal to a function, which will be called to get the current parents each time the fetch establishes a new connection.

fetch('https://braid.org/chat', {subscribe: true, retry: true, parents: () => {
        return current_parents
    }}).then(
    res => res.subscribe(
        (update) => {
            console.log('We got a new update!', update)
            // Do something with the update
        }
    )
)

Example Subscription with Async/Await

(await fetch('/chat', {subscribe: true, retry: true})).subscribe(
    (update) => {
        // We got a new update!
    })

Example Subscription with for await

var subscription_iterator = (await fetch('/chat',
    {subscribe: true, retry: true})).subscription
for await (var update of subscription_iterator) {
    // Updates might come in the form of patches:
    if (update.patches)
        chat = apply_patches(update.patches, chat)

    // Or complete snapshots:
    else
        // Beware the server doesn't send these yet.
        chat = JSON.parse(update.body)

    render_stuff()
}

Using it in Nodejs

Example Nodejs server with require('http')

Braidify adds these fields and methods to requests and responses:

  • req.subscribe
  • req.startSubscription({onClose: cb})
  • await req.parseUpdate()
  • res.sendUpdate()

Use it like this:

var braidify = require('braid-http').http_server
// or:
import {http_server as braidify} from 'braid-http'

require('http').createServer(
    (req, res) => {
        // Add braid stuff to req and res
        braidify(req, res)

        // Now use it
        if (req.subscribe)
            res.startSubscription({ onClose: _=> null })
            // startSubscription automatically sets statusCode = 209
        else
            res.statusCode = 200

        // Send the current version
        res.sendUpdate({
            version: ['greg'],
            body: JSON.stringify({greg: 'greg'})
        })
    }
).listen(9935)

Example Nodejs server with require('express')

With express, you can simply call app.use(braidify) to get braid features added to every request and response.

var braidify = require('braid-http').http_server
// or:
import {http_server as braidify} from 'braid-http'

var app = require('express')()

app.use(braidify)    // Add braid stuff to req and res

app.get('/', (req, res) => {
    // Now use it
    if (req.subscribe)
        res.startSubscription({ onClose: _=> null })
        // startSubscription automatically sets statusCode = 209
    else
        res.statusCode = 200

    // Send the current version
    res.sendUpdate({
        version: ['greg'],
        parents: ['gr','eg'],
        body: JSON.stringify({greg: 'greg'})
    })

    // Or you can send patches like this:
    // res.sendUpdate({
    //     version: ['greg'],
    //     parents: ['gr','eg'],
    //     patches: [{range: '.greg', unit: 'json', content: '"greg"'}]
    // })
})

require('http').createServer(app).listen(8583)

Example Nodejs client with require('http')

// Use this line if necessary for self-signed certs
// process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0

var https = require('braid-http').http_client(require('https'))
// or:
// import braid_http from 'braid-http'
// https = braid_http.http_client(require('https'))

https.get(
   'https://braid.org/chat',
   {subscribe: true},
   (res) => {
      res.on('update', (update) => {
          console.log('well we got one', update)
      })
   }
)

To get auto-reconnections use:

function connect () {
    https.get(
        'https://braid.org/chat',
        {subscribe: true},
        (res) => {
            res.on('update', (update) => {
                // {
                //   version: ["me"],
                //   parents: ["mom", "dad"],
                //   patches: [{unit: "json", range: ".foo", content: "3"}]
                //   body:    "3"
                // }
                //   // Update will contain either patches *or* body, but not both
                console.log('We got a new update!', update)
            })

            res.on('end',   e => setTimeout(connect, 1000))
            res.on('error', e => setTimeout(connect, 1000))
        })
}
connect()

Example Nodejs client with fetch()

var fetch = require('braid-http').fetch
// or:
import {fetch} from 'braid-http'

// process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0

fetch('https://localhost:3009/chat',
      {subscribe: true}).andThen(
          x => console.log('Got ', x)
      )

Note: the current version of node-fetch doesn't properly throw errors when a response connection dies, and thus you cannot attach a .catch() handler to automatically reconnect. (See issue #980 and #753.) We recommend using the http library (below) for requests on nodejs instead.

1.1.0

4 days ago

1.0.7

1 month ago

1.0.6

1 month ago

1.0.5

1 month ago

1.0.2

2 months ago

1.0.1

2 months ago

1.0.0

2 months ago

1.0.4

1 month ago

1.0.3

2 months ago

0.3.22

3 months ago

0.3.21

4 months ago

0.3.20

5 months ago

0.3.19

5 months ago

0.3.18

6 months ago

0.3.17

6 months ago

0.3.16

6 months ago

0.3.14

6 months ago

0.3.13

6 months ago

0.3.12

6 months ago

0.3.9

6 months ago

0.3.11

6 months ago

0.3.10

6 months ago

0.3.8

7 months ago

0.3.6

7 months ago

0.3.5

7 months ago

0.3.7

7 months ago

0.3.4

7 months ago

0.3.3

7 months ago

0.3.2

7 months ago

0.3.1

8 months ago

0.3.0

8 months ago

0.2.0

9 months ago

0.1.11

9 months ago

0.1.10

10 months ago

0.1.2

1 year ago

0.1.1

1 year ago

0.1.8

1 year ago

0.1.7

1 year ago

0.1.9

1 year ago

0.1.3

1 year ago

0.1.6

1 year ago

0.1.5

1 year ago

0.0.2

2 years ago

0.0.1

2 years ago