{"id":13509901,"url":"https://github.com/nanopack/mist","last_synced_at":"2026-01-12T02:41:51.376Z","repository":{"id":47028139,"uuid":"45631123","full_name":"nanopack/mist","owner":"nanopack","description":"A distributed, tag-based pub-sub service for modern web applications and container-driven cloud.","archived":false,"fork":false,"pushed_at":"2023-09-27T12:52:08.000Z","size":326,"stargazers_count":665,"open_issues_count":6,"forks_count":47,"subscribers_count":21,"default_branch":"master","last_synced_at":"2024-11-15T11:07:14.388Z","etag":null,"topics":["developer-tools","devtools","golang","messaging","nanobox","nanopack","pub-sub","tcp-client","websocket-client"],"latest_commit_sha":null,"homepage":null,"language":"Go","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/nanopack.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-11-05T18:32:02.000Z","updated_at":"2024-09-18T08:54:22.000Z","dependencies_parsed_at":"2024-06-18T20:10:31.456Z","dependency_job_id":"edd94275-d1bb-45a4-9a82-eb8af210bb6d","html_url":"https://github.com/nanopack/mist","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nanopack%2Fmist","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nanopack%2Fmist/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nanopack%2Fmist/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nanopack%2Fmist/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nanopack","download_url":"https://codeload.github.com/nanopack/mist/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246338555,"owners_count":20761402,"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":["developer-tools","devtools","golang","messaging","nanobox","nanopack","pub-sub","tcp-client","websocket-client"],"created_at":"2024-08-01T02:01:16.490Z","updated_at":"2026-01-12T02:41:51.361Z","avatar_url":"https://github.com/nanopack.png","language":"Go","funding_links":[],"categories":["5. Transport","Go","Go (134)","Message brokers","Capabilities","golang"],"sub_categories":["Events \u0026 Problems","Messaging"],"readme":"# Mist\n\n[![Build Status](https://travis-ci.org/nanopack/mist.svg)](https://travis-ci.org/nanopack/mist)\n\nMist is a simple pub/sub based on the idea that messages are tagged. To subscribe, a client simply constructs a list of tags that it is interested in, and all messages that are tagged with *all* of those tags are sent to that client.\n\nA client can not only be a subscriber (with multiple active subscriptions), but also a publisher. Clients will receive messages for any tags they are subscribed, *except message publish by themselves*.\n\n## Available Commands\nMist comes with two sets of available commands out of the box. Basic commands and Admin commands. It also has the ability to accept custom commands and handlers.\n\nYou can connect to mist with something like netcat; once connected you can simply type commands:\n\n```\n\u003e\u003e nc 127.0.0.1 1445\n{\"command\":\"publish\", \"tags\":[\"hello\"], \"data\":\"world!\"}\n```\n\n#### Basic Commands\nBasic command are what provide the core functionality of mist. They allow you subscribe to and publish messages, see all of your active subscriptions and also unsubscribe from any tags you no longer want to receive messages for.\n\n| Command | Description | Example |\n| --- | --- | --- |\n| `auth` | authenticate with the server to enter \"admin\" mode | `{\"command\":\"auth\", \"data\":\"TOKEN\"}` |\n| `ping` | ping the server to test for an active connection | `{\"command\":\"ping\"}` |\n| `subscribe` | subscribe to messages for *all* `tags` in a group | `{\"command\":\"subscribe\", \"tags\":[\"hello\"]}` |\n| `unsubscribe` | unsubscribe from *exact* `tags` provided| `{\"command\":\"unsubscribe\", \"tags\":[\"hello\"]}` |\n| `publish` | publish `data` to the list of `tags` | `{\"command\":\"publish\", \"tags\":[\"hello\"], \"data\":\"world!\"}` |\n| `list` | list all active subscriptions for client | `{\"command\":\"list\"}` |\n\n#### Admin Commands\nIf mist is started with an `authenticator` and a `token` then a client has the chance to validate that token on connect. Once validated mist adds some additional admin commands that allow the creation of `token`/`tag` combos that provide a layer of authentication when using basic commands.\n\n| Command | Description | Example |\n| --- | --- | --- |\n| `register` | register a `token` with a set of `tags` | `{\"command\":\"register\", \"tags\":[\"hello\"], \"data\":\"TOKEN\"}` |\n| `unregister` | removes a `token` from mist completely | `{\"command\":\"unregister\", \"data\":\"TOKEN\"}` |\n| `set` | adds a set of `tags` to a `token` | `{\"command\":\"set\", \"tags\":[\"hello\"], \"data\":\"TOKEN\"}` |\n| `unset` | removes a set of `tags` from a `token` | `{\"command\":\"unset\", \"tags\":[\"hello\"], \"data\":\"TOKEN\"}` |\n| `tags` | show `tags` that are associated with a `token` | `{\"command\":\"tags\", \"data\":\"TOKEN\"}` |\n\n## Messages\n\nAll communications within mist are sent and received as JSON encoded/decoded messages:\n```go\nMessage struct {\n  Command string   `json:\"command\"`\n  Tags    []string `json:\"tags\"`\n  Data    string   `json:\"data,omitempty\"`\n  Error   string   `json:\"error,omitempty\"`\n}\n```\n\nEach Message has a set of `tags` and `data`. Tags can take any form you like, as they are just an array of strings.\n\n``` json\n{\n  \"tags\": [\"company:pagodabox\", \"product:mist\", \"repo:#nanopack\"],\n  \"data\": \"Mist is awesome!\"\n}\n```\n\n### Subscribing / Publishing\n\nThink of `tags` as a way to filter out messages you don't want to receive; the more tags that are added to a subscription the more direct a message has to be:\n\n| Subscribed tags | Messages received from tags |\n| --- | --- |\n| `[\"onefish\"]` | `[\"onefish\"]`, `[\"onefish\",\"twofish\"]`, `[\"onefish\",\"twofish\",\"redfish\"]` |\n| `[\"onefish\", \"twofish\"]` | `[\"onefish\",\"twofish\"]`, `[\"onefish\",\"twofish\",\"redfish\"]` |\n| `[\"onefish\", \"twofish\", \"redfish\"]` | `[\"onefish\",\"twofish\",\"redfish\"]` |\n\nMessage that are published to clients as the result of a subscription are delivered in this format:\n\n`{\"command\":\"\u003ccommand\u003e\", \"tags\":[\"\u003ctag\u003e\", \"\u003ctag\u003e\"], \"data\":\"\u003cdata\u003e\"}`\n\nA few things to not about how mist handles data:\n\n* Data flowing through mist is *not touched or verified in anyway*, however, it **MUST NOT** contain a newline character as this will break the mist protocol.\n\n* Messages are not guaranteed to be delivered, if the client is running behind on processing messages, newer messages could be dropped.\n\n* Messages are not stored, if no client is available to receive the message, then it is dropped.\n\n## Listeners\n\nOut of the box mist supports three different types of servers (`TCP`, `HTTP`, and `Websocket`). **By default, when mist starts, it will start one of each.**\n\n```\nTCP server listening at '127.0.0.1:1445'...\nHTTP server listening at '127.0.0.1:8080'...\nWS server listening at '127.0.0.1:8888'...\n```\n\nWhen starting mist, you can specify any number and type of server you'd like as long as it follows the string URI protocol (If a listener is passed that mist doesn't support it will skip).\n\nAlso, if mist doesn't support a server you need it allows you to register custom servers that can be used on startup.\n\n#### Available listeners:\n\n`(scheme:[//[user:pass@]host[:port]][/]path[?query][#fragment])`\n\n| Listener | URI scheme |\n| --- | --- |\n| tcp | `tcp://127.0.0.1:1445` |\n| http | `http://127.0.0.1:8080` |\n| websocket | `ws://127.0.0.1:8888` |\n\n##### Example\n```\n./mist --server --listeners \"tcp://127.0.0.1:1445\", \"http://127.0.0.1:8080\", \"ws://127.0.0.1:8888\"\n```\n\n## Authenticators\n\nMist also provides support for authentication. This means that during startup you can provide mist with an `authenticator` and a `token`. Once enabled, any client that connects to the server has an opportunity (as the first command) to provide the authentication token to \"unlock\" admin commands for that connection.\n\n```\n./mist --server --authenticator memory:// --token TOKEN\n```\n\nNotice that when an authenticator is provided, *a token must also be provided otherwise the server will not start*.\n\n#### Available authenticators\n\nLike `listeners`, mist allows for the registration of custom `authenticators`.\n\n`(scheme:[//[user:pass@]host[:port]][/]path[?query][#fragment])`\n\n| Authenticator | URI scheme | description\n| --- | --- | --- |\n| memory | `memory://` | an in memory store |\n| [scribble](https://github.com/nanobox-io/golang-scribble) | `scribble://?db=/tmp` | a tiny JSON database |\n| postgres | `postgres://postgres@127.0.0.1:5432?db=postgres` | n/a |\n\n#### Connecting to an authenticated server\n\nWhen connecting to an authenticated server, to enter \"admin\" mode, the very first communication across the wire **must** be the `auth` command.\n\n```\n\u003e\u003e nc 127.0.0.1 1445\n{\"command\":\"auth\", \"data\":\"TOKEN\"}\n```\n\nFailing to authenticate will still allow the connection to proceed, however no \"admin\" commands will be allowed on the connection.\n\n## Clients:\n\nOut of the box mist provides a CLI, a TCP client, and the ability to connect via Websocket Clients\n\n#### CLI:\n\nThe CLI provides a built-in TCP client that can be used to connect with any running mist\n\n```\nUsage:\n  mist [flags]\n  mist [command]\n\nAvailable Commands:\n  ping        Ping a running mist server\n  subscribe   Subscribe tags\n  publish     Publish a message\n\nFlags:\n      --authenticator string   Setting enables authentication, storing tokens in the authenticator provided\n      --config string          Path to config file\n      --listeners value        A comma delimited list of servers to start (default [tcp://127.0.0.1:1445,ws://127.0.0.1:8888])\n      --log-level string       Output level of logs (TRACE, DEBUG, INFO, WARN, ERROR, FATAL) (default \"INFO\")\n      --server                 Run mist as a server\n      --token string           Auth token for connections\n  -v, --version                Display the current version of this CLI\n\nUse \"mist [command] --help\" for more information about a command.\n```\n\n#### TCP Client\n\nHere is an example of a TCP client written in Golang that will connect with mist and handle messages:\n\n```golang\npackage main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"time\"\n\n\t\"github.com/nanopack/mist/clients\"\n)\n\nfunc main() {\n\tclient, err := clients.New(\"127.0.0.1:1445\")\n\tif err != nil {\n\t\tos.Exit(1)\n\t}\n\n\t// example commands (not handling errors for brevity)\n\tclient.Ping()\n\tclient.Subscribe([]string{\"hello\"})\n\tclient.Publish([]string{\"hello\"}, \"world\")\n\tclient.List()\n\t// client.Unsubscribe([]string{\"hello\"})\n\n\t// do stuff with messages\n\tfor {\n\t\tselect {\n\t\tcase msg := \u003c-client.Messages():\n\t\t\tfmt.Printf(\"MSG: %#v\\n\", msg)\n\t\tcase \u003c-time.After(time.Second * 1):\n\t\t\t// do something if messages are taking too long\n\t\t}\n\t}\n\n\t// do stuff with messages (alternate)\n\t// for msg := range client.Messages() {\n\t// \tfmt.Printf(\"MSG: %#v\\n\", msg)\n\t// }\n}\n```\n\n#### Websocket Client\n\nSince mist just uses a JSON message protocol internally, sending messages via websocket is easy.\n\nNOTE: If authentication is enabled you'll need to provide a token when connecting the websocket:\n\n* As a Header: `X-AUTH-TOKEN: token`\n* As a query param: `x-auth-token=token`\n\nNOTE: If using WSS you'll need to accept the generated cert via the browser `https://localhost:8082/subscribe/websocket`\nprior to chrome console letting you run the following javascript.\n\n##### Example\n\n``` javascript\n\n  // connect the websocket\n  var ws = new WebSocket(\"ws://localhost:8080/subscribe/websocket?x-auth-token=token\")\n\n  // handle responses from the server\n  ws.onmessage = function(me){\n    console.log(\"Response!\", me.data)\n  }\n\n  // ping\n  ws.send(JSON.stringify({\"command\": \"ping\"}))\n\n  // subscribe\n  ws.send(JSON.stringify({\"command\": \"subscribe\", \"tags\": [\"hello\", \"world\"]}))\n\n  // unsubscribe\n  ws.send(JSON.stringify({\"command\": \"unsubscribe\", \"tags\": [\"hello\", \"world\"]}))\n\n  // list\n  ws.send(JSON.stringify({\"command\": \"list\"}))\n```\n\n## Running mist:\n\nTo run mist as a server, using the following command will start mist as a daemon:\n\n`mist --server`\n\nIf you need to override any default config options you can pass the path to a config file:\n\n`mist --config /path/to/config`\n\n##### example config\n\n```yml\nauthenticator: memory://\nlisteners:\n  - tcp://127.0.0.1:1445\nlog-level: INFO\ntoken: TOKEN\nserver: true\n```\n\nOr you can just pass any configuration options as flags:\n\n`mist --server --log-level DEBUG`\n\n## Contributing\n\nContributions to mist are welcome and encouraged. Mist is a [Nanobox](https://nanobox.io) project and contributions should follow the [Nanobox Contribution Process \u0026 Guidelines](https://docs.nanobox.io/contributing/).\n\n[![open source](http://nano-assets.gopagoda.io/open-src/nanobox-open-src.png)](http://nanobox.io/open-source)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnanopack%2Fmist","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnanopack%2Fmist","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnanopack%2Fmist/lists"}