{"id":15290922,"url":"https://github.com/azure/azure-relay-node","last_synced_at":"2025-10-20T03:31:02.747Z","repository":{"id":12660529,"uuid":"68422923","full_name":"Azure/azure-relay-node","owner":"Azure","description":"☁️Node.js library for Azure Relay Hybrid Connections","archived":false,"fork":false,"pushed_at":"2023-12-24T09:14:59.000Z","size":1474,"stargazers_count":12,"open_issues_count":31,"forks_count":15,"subscribers_count":20,"default_branch":"dev","last_synced_at":"2024-09-25T21:52:47.149Z","etag":null,"topics":["azure","https","hybrid-connections","hyco-websocket","relay","websocket"],"latest_commit_sha":null,"homepage":"https://docs.microsoft.com/en-us/azure/service-bus-relay/relay-what-is-it","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Azure.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-09-17T00:20:37.000Z","updated_at":"2022-11-28T22:50:01.000Z","dependencies_parsed_at":"2024-06-21T13:06:22.204Z","dependency_job_id":"97607c93-9296-4a15-9e27-aef3be06de5d","html_url":"https://github.com/Azure/azure-relay-node","commit_stats":{"total_commits":69,"total_committers":13,"mean_commits":"5.3076923076923075","dds":0.6956521739130435,"last_synced_commit":"bd25250777b7c8be80d88310f3c7b9d6a6cdbdf9"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Azure%2Fazure-relay-node","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Azure%2Fazure-relay-node/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Azure%2Fazure-relay-node/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Azure%2Fazure-relay-node/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Azure","download_url":"https://codeload.github.com/Azure/azure-relay-node/tar.gz/refs/heads/dev","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219877408,"owners_count":16554881,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["azure","https","hybrid-connections","hyco-websocket","relay","websocket"],"created_at":"2024-09-30T16:10:08.415Z","updated_at":"2025-10-20T03:30:57.333Z","avatar_url":"https://github.com/Azure.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"relay.png\" alt=\"Microsoft Azure Relay\" width=\"100\"/\u003e\n\u003c/p\u003e\n\n# Azure Relay Hybrid Connections Clients for Node.JS\n\n![build status](https://ci.appveyor.com/api/projects/status/github/Azure/azure-relay-node?branch=master\u0026svg=true)\n\n|Package|Status|\n|------|-------------|\n|hyco-ws|[![npm version](https://badge.fury.io/js/hyco-ws.svg)](https://badge.fury.io/js/hyco-ws)|\n|hyco-websocket|[![npm version](https://badge.fury.io/js/hyco-websocket.svg)](https://badge.fury.io/js/hyco-websocket)|\n|hyco-https|[![npm version](https://badge.fury.io/js/hyco-https.svg)](https://badge.fury.io/js/hyco-https)|\n\nThis repository contains Node packages and samples for the Hybrid Connections feature of the \nMicrosoft Azure Relay, a capability pillar of the Azure Service Bus platform.\n\nHybrid Connections is a secure, open-protocol evolution of the existing Service Bus Relay \nservice that has been available in Azure since the beginning and handles millions of connections \ndaily. \n\nHybrid Connections allows establishing bi-directional, binary stream communication between \ntwo networked applications, whereby either or both of the parties can reside behind NATs or \nFirewalls. Hybrid Connections is based on HTTP(S) and WebSockets.\n\n## How to provide feedback\n\nSee our [Contribution Guidelines](./.github/CONTRIBUTING.md).\n\n## Samples\n\nFor Relay Hybrid Connections samples, see the [azure/azure-relay](https://github.com/Azure/azure-relay/tree/master/samples/Hybrid%20Connections) service repository.\n\n## How it works\n\nFor Node, the code in the repository allows a **publicly discoverable and reachable** WebSocket \nserver to be hosted on any machine that has outbound access to the Internet, and \nspecifically to the Microsoft Azure Relay service in the chosen region, via HTTPS port 443. \n  \nThe WebSocket server code will look instantly familiar as it is directly based on and integrated \nwith two of the most popular existing WebSocket packages in the Node universe: \"ws\" and \"websocket\". \n\n``` JS\nrequire('ws') ==\u003e require('hyco-ws')\nrequire('websocket') ==\u003e require('hyco-websocket')\n```\n\nAs you create a WebSocket server using either of the alternate \"hyco-ws\" and \"hyco-websocket\" \npackages from this repository, the server will not listen on a TCP port on the local network, \nbut rather delegate listening to a configured Hybrid Connection path the Azure Relay service \nin Service Bus. The delegation happens by ways of opening and maintaining a \"control connection\"\nWebSocket that remains opened and reconnects automatically when dropped inadvertently. This \nlistener connection is automatically TLS/SSL protected without you having to juggle any certificates.\n\n### Servers\n\nThe snippet below shows the \"ws\"/\"hyco-ws\" variant of creating a server. The API usage is \ncompletely \"normal\" except for using the \"hyco-ws\" package and creating an instance of the\n*RelayedServer* instead of *Server*. The default underlying *Server* class remains fully available \nwhen using \"hyco-ws\" instead of \"ws\", meaning you can host a relayed and a local WebSocket \nserver side-by-side from within the same application. The \"websocket\"/\"hyco-websocket\" \nexperience is analogous and explained in the package's README.   \n\n``` JS\n    var WebSocket = require('hyco-ws');\n\n    var uri = WebSocket.createRelayListenUri(ns, path);\n    var wss = WebSocket.RelayedServer(\n        {\n            server : uri,\n            token: function() { return WebSocket.createRelayToken(uri, keyrule, key); }\n        });\n\n    wss.on('connection', function (ws) {\n        console.log('connection accepted');\n        ws.onmessage = function (event) {\n            console.log(JSON.parse(event.data));\n        };\n        ws.on('close', function () {\n            console.log('connection closed');\n        });       \n    });\n\n    wss.on('error', function(err) {\n        console.log('error: ' + err);\n    });\n```\n\nUp to 25 WebSocket listeners can listen concurrently on the same Hybrid Connection path on the \nRelay; if two or more listeners are connected, the service will automatically balance incoming \nconnection requests across the connected listeners which also provides an easy failover capability. \nYou don't have to do anything to enable this, just have multiple listeners share the same path.   \n\nClients connect to the server through the Relay service on the same path the listener is listening \non. The client uses the regular WebSocket protocol. WebSocket subprotocols and extensions can \nbe negotiated between client and the Web Socket server end-to-end as you would without the Relay.\n\nWhat happens under the covers, as you can find if you poke around in the code of the two packages, is \nthat any connection that is from a client to the Relay service will be announced to the Listener \nwith a control message over the open control channel. The control message contains information about \na \"rendezvous endpoint\" that is valid for a brief period. The server framework will decide whether\nto accept the incoming connection, potentially including calling some extensibility hooks, and\nthen open an outbound WebSocket to the rendezvous endpoint. The client WebSocket and this \"data\"\nWebSocket are then bound into a single end-to-end connection by the Relay service, behaving like\na single WebSocket.    \n\n### Clients\n\nIf the Relay requires a sender token (which is the default), that token can be included either \nas a query parameter ('sb-hc-token') or with the 'ServiceBusAuthorization' HTTP header. The latter is\npreferred; mostly since URLs end up in many logs.  \n\n``` JS\n  var WebSocket = require('hyco-ws');\n\n  var opt = { headers : { 'ServiceBusAuthorization' : token}};\n  var address = WebSocket.createRelaySendUri(ns, path),\n\n  var client = new WebSocket(address, null, opt);\n  client.on('open', function() {\n       client.send(\"Hi!\"); \n  });  \n\n```\n\nThe standard WebSocket client that is built into current browsers doesn't support setting \nthe headers for the HTTP handshake, so you'll have to use the query string parameter. The \nsnippet below is from the modified \"serverstats\" sample included in this repo that leans \non the similar sample from the \"ws\" package. The placeholders in the WebSocket URI are \nreplaced with the correct values for namespace, path, and token using a template engine. \n\n``` HTML\n   \u003cscript\u003e\n      function updateStats(memuse) {\n        document.getElementById('rss').innerHTML = memuse.rss;\n        document.getElementById('heapTotal').innerHTML = memuse.heapTotal;\n        document.getElementById('heapUsed').innerHTML = memuse.heapUsed;\n      }\n\n      var host = window.document.location.host.replace(/:.*/, '');\n      var ws = new WebSocket('wss://{{ns}}:443/$hc/{{path}}?'+\n                                'sb-hc-action=connect\u0026sb-hc-token={{token}}');\n      ws.onmessage = function (event) {\n        updateStats(JSON.parse(event.data));\n      };\n    \u003c/script\u003e\n``` \n\n## packages\n\nThe README documents for the two includes packages discuss the particular additions made \nto accomodate support for Hybrid Connections. What's common for both libraries is that \nyou can use the 'hyco-ws' and the 'hyco-websocket' packages instead of the 'ws' and 'websocket'\nwithout losing any existing functionality. Both packages contain and expose the full and unaltered\nfunctionality of their respective base packages.\n\n* [README for hyco-ws](./hyco-ws/README.md)\n* [README for hyco-websocket](./hyco-websocket/README.md)    \n\n## Examples \n\nThe repo contains local examples at the package level and a few global examples. \n[The global samples in /examples](/examples/README.md) use the latest, public, npm-published versions\nof the packages and require that you install all dependencies with \"npm install\". \n\nThe local examples under [hyco-ws](./hyco-ws) and [hyco-websocket](./hyco-websocket) reference the \ncode in your checked out repo.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fazure%2Fazure-relay-node","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fazure%2Fazure-relay-node","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fazure%2Fazure-relay-node/lists"}