{"id":15653129,"url":"https://github.com/willsewell/pusher-http-rust","last_synced_at":"2026-03-11T14:37:45.146Z","repository":{"id":32248801,"uuid":"35823124","full_name":"WillSewell/pusher-http-rust","owner":"WillSewell","description":"[Unsupported] HTTP Pusher Rust Library","archived":false,"fork":false,"pushed_at":"2024-06-18T04:37:08.000Z","size":2992,"stargazers_count":31,"open_issues_count":12,"forks_count":16,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-19T07:47:03.335Z","etag":null,"topics":["pusher","rust","rust-library"],"latest_commit_sha":null,"homepage":"https://docs.rs/pusher/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/WillSewell.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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-05-18T14:36:56.000Z","updated_at":"2025-03-23T05:02:33.000Z","dependencies_parsed_at":"2024-04-14T23:22:35.426Z","dependency_job_id":"e08d2c95-f5c3-4440-bed4-b012f3754e8d","html_url":"https://github.com/WillSewell/pusher-http-rust","commit_stats":null,"previous_names":["pusher/pusher-http-rust"],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WillSewell%2Fpusher-http-rust","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WillSewell%2Fpusher-http-rust/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WillSewell%2Fpusher-http-rust/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WillSewell%2Fpusher-http-rust/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/WillSewell","download_url":"https://codeload.github.com/WillSewell/pusher-http-rust/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251749106,"owners_count":21637455,"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":["pusher","rust","rust-library"],"created_at":"2024-10-03T12:44:46.377Z","updated_at":"2026-03-11T14:37:45.107Z","avatar_url":"https://github.com/WillSewell.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Pusher HTTP Rust Library\n\n\u003e [!WARNING]  \n\u003e **This library is unsupported**. I (the maintainer) do not currently have the bandwidth to review PRs, address security issues etc. Forks are encouraged.\n\n[![Build Status](https://github.com/pusher-community/pusher-http-rust/workflows/Tests/badge.svg)](https://github.com/pusher-community/pusher-http-rust/actions)\n[![Crates Badge](https://img.shields.io/crates/v/pusher)](https://crates.io/crates/pusher)\n[![Docs.rs Badge](https://docs.rs/pusher/badge.svg)](https://docs.rs/pusher/)\n\nThe Rust library for interacting with the Pusher HTTP API.\n\nThis package lets you trigger events to your client and query the state of your Pusher channels. When used with a server, you can validate Pusher webhooks and authenticate private- or presence-channels.\n\nThe functions that make HTTP requests are [async](https://rust-lang.github.io/async-book/), so you will need to run them with an executer like [tokio](https://tokio.rs/). The library is a wrapper around the [hyper](https://hyper.rs/) client.\n\nIn order to use this library, you need to have a free account on \u003chttp://pusher.com\u003e. After registering, you will need the application credentials for your app.\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Getting Started](#getting-started)\n- [Configuration](#configuration)\n  - [Additional options](#additional-options)\n- [Usage](#usage)\n  - [Triggering events](#triggering-events)\n  - [Excluding event recipients](#excluding-event-recipients)\n  - [Authenticating Channels](#authenticating-channels)\n  - [Application state](#application-state)\n  - [Webhook validation](#webhook-validation)\n- [Feature Support](#feature-support)\n- [Developing the Library](#developing-the-library)\n  - [Running the tests](#running-the-tests)\n- [License](#license)\n\n## Installation\n\nAdd to your `Cargo.toml`:\n\n```rust\npusher=\"*\"\n```\n\n## Supported platforms\n\n- Rust versions 1.39 and above\n\n## Getting Started\n\n```rust\nextern crate pusher; // imports the `pusher` module\n\nuse pusher::PusherBuilder; // brings the PusherBuilder into scope\n\n// the functions are async, so we need a reactor running (e.g. tokio)\n// this example uses \"current_thread\" for simplicity\n#[tokio::main(flavor = \"current_thread\")]\nasync fn main() {\n  // initializes a Pusher object with your app credentials\n  let pusher = PusherBuilder::new(\"APP_ID\", \"KEY\", \"SECRET\").finalize();\n\n  // triggers an event called \"my_event\" on a channel called \"test_channel\", with the payload \"hello world!\"\n  let result = pusher.trigger(\"test_channel\", \"my_event\", \"hello world!\").await;\n  match result {\n    Ok(events) =\u003e println!(\"Successfully published: {:?}\", events),\n    Err(err) =\u003e println!(\"Failed to publish: {}\", err),\n  }\n}\n```\n\n## Configuration\n\nThere easiest way to configure the library is by creating a new `Pusher` instance:\n\n```rust\nlet pusher = PusherBuilder::new(\"id\", \"key\", \"secret\").finalize();\n```\n\n`PusherBuilder::new` returns a `PusherBuilder`, on which to chain configuration methods, before calling `finalize()`.\n\n### Additional options\n\n#### Instantiation From URL\n\n```rust\nPusherBuilder::from_url(\"http://key:secret@api.host.com/apps/id\").finalize();\n```\n\n#### Instantiation From Environment Variable\n\n```rust\nPusherBuilder::from_env(\"PUSHER_URL\").finalize();\n```\n\nThis is particularly relevant if you are using Pusher as a Heroku add-on, which stores credentials in a `\"PUSHER_URL\"` environment variable.\n\n#### HTTPS\n\nTo ensure requests occur over HTTPS, call `secure()` before `finalize()`.\n\n```rust\nlet pusher = PusherBuilder::new(\"id\", \"key\", \"secret\").secure().finalize();\n```\n\n#### Changing Host\n\nCalling `host()` before `finalize()` will make sure requests are sent to your specified host.\n\n```rust\nlet pusher = PusherBuilder::new(\"id\", \"key\", \"secret\").host(\"foo.bar.com\").finalize();\n```\n\nBy default, this is `\"api.pusherapp.com\"`.\n\n#### Changing the underlying `hyper::client::connect::Connect`\n\nThe above functions have equivalent functions that also allow a custom [`Connect`](https://docs.rs/hyper/0.13.1/hyper/client/connect/struct.Connected.html) to be provided. E.g.:\n\n```rust\nlet pusher = PusherBuilder::new_with_client(my_client, \"id\", \"key\", \"secret\").host(\"foo.bar.com\").finalize();\n```\n\n## Usage\n\n### Triggering events\n\nIt is possible to trigger an event on one or more channels. Channel names can contain only characters which are alphanumeric, `_` or `-`` and have to be at most 200 characters long. Event name can be at most 200 characters long too.\n\n\n#### Single channel\n\n##### `async fn trigger\u003cS: serde::Serialize\u003e(\u0026self, channel: \u0026str, event: \u0026str, payload: S)`\n\n|Argument   |Description   |\n|:-:|:-:|\n|channel `\u0026str`   |The name of the channel you wish to trigger on.   |\n|event `\u0026str` | The name of the event you wish to trigger |\n|data `S: serde::Serialize` | The payload you wish to send. Must be marshallable into JSON. |\n\n|Return Value|Description|\n|:-:|:-:|\n|result `Result\u003cTriggeredEvents, String\u003e` | If the trigger was successful and you are connected to certain clusters, an object containing the `event_ids` field will be returned as part of a `Result`. An `Err` value will be returned if any errors were encountered.  |\n\n###### Example\n\n```rust\nlet mut hash_map = HashMap::new();\nhash_map.insert(\"message\", \"hello world\");\n\npusher.trigger(\"test_channel\", \"my_event\", \u0026hash_map).await;\n```\n\n#### Multiple channels\n\n##### `async fn trigger_multi\u003cS: serde::Serialize\u003e(\u0026self, channels: \u0026[\u0026str], event: \u0026str, payload: S)`\n\n|Argument | Description |\n|:-:|:-:|\n|channels `\u0026[\u0026str]`| A vector of channel names you wish to send an event on. The maximum length is 10.|\n|event `\u0026str` | As above.|\n|data `S: serde::Serialize` |As above.|\n\n|Return Value|Description|\n|:-:|:-:|\n|result `Result\u003cTriggeredEvents, String\u003e` | As above. |\n\n###### Example\n\n```rust\nlet channels = vec![\"test_channel\", \"test_channel2\"];\n\npusher.trigger_multi(\u0026channels, \"my_event\", \"hello\").await;\n```\n\n### Excluding event recipients\n\n`trigger_exclusive` and `trigger_multi_exclusive` follow the patterns above, except a `socket_id` is given as the last parameter.\n\nThese methods allow you to exclude a recipient whose connection has that `socket_id` from receiving the event. You can read more [here](http://pusher.com/docs/duplicates).\n\n#### Examples\n\n**On one channel**:\n\n```rust\npusher.trigger_exclusive(\"test_channel\", \"my_event\", \"hello\", \"123.12\").await;\n```\n\n**On multiple channels**:\n\n```rust\nlet channels = vec![\"test_channel\", \"test_channel2\"];\npusher.trigger_multi_exclusive(\u0026channels, \"my_event\", \"hello\", \"123.12\").await;\n```\n\n### Authenticating Channels\n\nApplication security is very important so Pusher provides a mechanism for authenticating a user’s access to a channel at the point of subscription.\n\nThis can be used both to restrict access to private channels, and in the case of presence channels notify subscribers of who else is also subscribed via presence events.\n\nThis library provides a mechanism for generating an authentication signature to send back to the client and authorize them.\n\nFor more information see our [docs](http://pusher.com/docs/authenticating_users).\n\n#### Private channels\n\n##### `fn authenticate_private_channel(\u0026self, channel_name: \u0026str, socket_id: \u0026str)`\n\n|Argument|Description|\n|:-:|:-:|\n|channel_name `\u0026str`| The channel name in the request sent by the client|\n|socket_id `\u0026str`| The socket id in the request sent by the client|\n\n|Return Value|Description|\n|:-:|:-:|\n|Result `\u003cString, \u0026str\u003e` | The `Ok` value will be the response to send back to the client, carrying an authentication signature. An `Err` value will be a string describing any errors generated |\n\n###### Example using hyper\n\n```rust\nasync fn pusher_auth(req: Request\u003cBody\u003e) -\u003e Result\u003cResponse\u003cBody\u003e, Error\u003e {\n  let body = to_bytes(req).await.unwrap();\n  let params = parse(body.as_ref()).into_owned().collect::\u003cHashMap\u003cString, String\u003e\u003e();\n  let channel_name = params.get(\"channel_name\").unwrap();\n  let socket_id = params.get(\"socket_id\").unwrap();\n  let auth_signature = pusher.authenticate_private_channel(channel_name, socket_id).unwrap();\n  Ok(Response::new(auth_signature.into()))\n}\n```\n\n#### Authenticating presence channels\n\nUsing presence channels is similar to private channels, but in order to identify a user, clients are sent a user_id and, optionally, custom data.\n\n##### `fn authenticate_presence_channel(\u0026self, channel_name: \u0026str, socket_id: \u0026str, member: \u0026Member)`\n\n|Argument|Description|\n|:-:|:-:|\n|channel_name `\u0026str`| The channel name in the request sent by the client|\n|socket_id `\u0026str`| The socket id in the request sent by the client|\n|member `\u0026pusher::Member`| A struct representing what to assign to a channel member, consisting of a `user_id` and any custom `user_info`. See below |\n\n###### Custom Types\n\n**pusher::Member**\n\n```rust\npub struct Member\u003c'a\u003e {\n  pub user_id: \u0026'a str,\n  pub user_info: Option\u003cHashMap\u003c\u0026'a str, \u0026'a str\u003e\u003e,\n}\n```\n\n###### Example using hyper\n\n```rust\nasync fn pusher_auth(req: Request\u003cBody\u003e) -\u003e Result\u003cResponse\u003cBody\u003e, Error\u003e {\n  let body = to_bytes(req).await.unwrap();\n  let params = parse(body.as_ref()).into_owned().collect::\u003cHashMap\u003cString, String\u003e\u003e();\n  let channel_name = params.get(\"channel_name\").unwrap();\n  let socket_id = params.get(\"socket_id\").unwrap();\n\n  let mut member_data = HashMap::new();\n  member_data.insert(\"twitter\", \"jamiepatel\");\n  let member = pusher::Member{user_id: \"4\", user_info: Some(member_data)};\n\n  let auth_signature = pusher.authenticate_presence_channel(channel_name, socket_id, \u0026member).unwrap();\n  Ok(Response::new(auth_signature.into()))\n}\n```\n\n### Application state\n\nThis library allows you to query our API to retrieve information about your application's channels, their individual properties, and, for presence-channels, the users currently subscribed to them.\n\n#### Get the list of channels in an application\n\n##### `async fn channels(\u0026self)`\n\nRequesting a list of application channels without any query options.\n\n|Return Value|Description|\n|:-:|:-:|\n|result `Result\u003cChannelList, String\u003e`| The `Ok` value will be a struct representing the list of channels. See below. An `Err` value will represent any errors encountered.|\n\n##### `async fn channels_with_options(\u0026self, params: QueryParameters)`\n\nAdding options to your `channels` request.\n\n|Argument|Description|\n|:-:|:-:|\n|params `QueryParameters`| A vector of tuples with query options. Where the first value of a tuple is `\"filter_by_prefix\"`, the API will filter the returned channels with the second value. To get number of users subscribed to a presence-channel, specify an `\"info\"` value in a tuple with a corresponding `\"user_count\"` value. |\n\n|Return Value|Description|\n|:-:|:-:|\n|result `Result\u003cChannelList, String\u003e`| As above.|\n\n###### Custom Types\n\n**pusher::ChannelsList**\n\n```rust\npub struct ChannelList {\n  pub channels: HashMap\u003cString, Channel\u003e,\n}\n```\n\n**pusher::Channel**\n\n```rust\npub struct Channel {\n  pub occupied: Option\u003cbool\u003e,\n  pub user_count: Option\u003ci32\u003e,\n  pub subscription_count: Option\u003ci32\u003e,\n}\n\n```\n###### Example\n\n**Without options**:\n\n```rust\npusher.channels().await;\n//=\u003e Ok(ChannelList { channels: {\"presence-chatroom\": Channel { occupied: None, user_count: None, subscription_count: None }, \"presence-notifications\": Channel { occupied: None, user_count: None, subscription_count: None }} })\n```\n\n**With options**:\n\n```rust\nlet channels_params = vec![(\"filter_by_prefix\", \"presence-\"), (\"info\", \"user_count\")];\npusher.channels_with_options(channels_params).await;\n//=\u003e Ok(ChannelList { channels: {\"presence-chatroom\": Channel { occupied: None, user_count: Some(92), subscription_count: None }, \"presence-notifications\": Channel { occupied: None, user_count: Some(29), subscription_count: None }} })\n```\n\n#### Get the state of a single channel\n\n##### `async fn channel(\u0026self, channel_name: \u0026str)`\n\nRequesting the state of a single channel without any query options.\n\n|Return Value|Description|\n|:-:|:-:|\n|result `Result\u003cChannel, String\u003e`| The `Ok` value will be a struct representing a channel. See above. An `Err` value will represent any errors encountered.|\n\n##### `async fn channel_with_options(\u0026self, channel_name: \u0026str, params: QueryParameters)`\n\nAdding options to your `channel` request.\n\n|Argument|Description|\n|:-:|:-:|\n|channel_name `\u0026str`| The name of the channel|\n|params `QueryParameters`| A vector of tuples with query options. To request information regarding user_count and subscription_count, a tuple must have an \"info\" value and a value containing a comma-separated list of attributes. An `Err` will be returned for any invalid API requests. |\n\n|Return Value|Description|\n|:-:|:-:|\n|result `Result\u003cChannel, String\u003e`| As above.|\n\n###### Example\n\n**Without options**:\n\n```rust\npusher.channel(\"presence-chatroom\").await;\n//=\u003e Ok(Channel { occupied: Some(true), user_count: None, subscription_count: None })\n```\n\n**With options**:\n\n```rust\nlet channel_params = vec![(\"info\", \"user_count,subscription_count\")];\npusher.channel_with_options(\"presence-chatroom\", channel_params).await;\n//=\u003e Ok(Channel { occupied: Some(true), user_count: Some(96), subscription_count: Some(96) })\n```\n\n#### Get a list of users in a presence channel\n\n##### `async fn channel_users(\u0026self, channel_name : \u0026str)`\n\n|Argument|Description|\n|:-:|:-:|\n|channel_name `\u0026str`| The channel name|\n\n|Return Value|Description|\n|:-:|:-:|\n|result `Result\u003cChannelUserList, String\u003e`| The `Ok` value will be a struct representing a list of the users subscribed to the presence-channel. See below. The `Err` value will represent any errors encountered. |\n\n###### Custom Types\n\n**pusher::ChannelUserList**\n\n```rust\npub struct ChannelUserList {\n  pub users: Vec\u003cChannelUser\u003e,\n}\n```\n\n**pusher::ChannelUser**\n\n```rust\npub struct ChannelUser {\n  pub id: String,\n}\n```\n\n###### Example\n\n```rust\npusher.channel_users(\"presence-chatroom\").await;\n//=\u003e Ok(ChannelUserList { users: [ChannelUser { id: \"red\" }, ChannelUser { id: \"blue\" }] })\n```\n\n### Webhook validation\n\nOn your [dashboard](http://app.pusher.com), you can set up webhooks to POST a payload to your server after certain events. Such events include channels being occupied or vacated, members being added or removed in presence-channels, or after client-originated events. For more information see \u003chttps://pusher.com/docs/webhooks\u003e.\n\nThis library provides a mechanism for checking that these POST requests are indeed from Pusher, by checking the token and authentication signature in the header of the request.\n\n##### `fn webhook(\u0026self, key: \u0026str, signature: \u0026str, body: \u0026str)`\n\n|Argument|Description|\n|:-:|:-:|\n|key `\u0026str` | The key supplied in the \"X-Pusher-Key\" header |\n|signature `\u0026str` | The signature supplied in the \"X-Pusher-Signature\" header |\n|body `\u0026str` | The body of the request |\n\n|Return Value|Description|\n|:-:|:-:|\n|result `Result\u003cWebhook, \u0026str\u003e`| If the webhook is valid, the `Ok` value will be a representation of that webhook that includes its timestamp and associated events. If the webhook is invalid, an `Err` value will be passed.|\n\n##### Custom Types\n\n**pusher::Webhook**\n\n```rust\npub struct Webhook {\n  pub time_ms: i64,\n  pub events: Vec\u003cHashMap\u003cString, String\u003e\u003e,\n}\n```\n\n##### Example\n\n```rust\npusher.webhook(\"supplied_key\", \"supplied_signature\", \"body\")\n```\n\n## Feature Support\n\nFeature                                    | Supported\n-------------------------------------------| :-------:\nTrigger event on single channel            | *\u0026#10004;*\nTrigger event on multiple channels         | *\u0026#10004;*\nExcluding recipients from events           | *\u0026#10004;*\nAuthenticating private channels            | *\u0026#10004;*\nAuthenticating presence channels           | *\u0026#10004;*\nGet the list of channels in an application | *\u0026#10004;*\nGet the state of a single channel          | *\u0026#10004;*\nGet a list of users in a presence channel  | *\u0026#10004;*\nWebHook validation                         | *\u0026#10004;*\nHeroku add-on support                      | *\u0026#10004;*\nDebugging \u0026 Logging                        | *\u0026#10004;*\nCluster configuration                      | *\u0026#10004;*\nHTTPS                                      | *\u0026#10004;*\nTimeouts                                   | *\u0026#10008;*\nHTTP Proxy configuration                   | *\u0026#10008;*\nHTTP KeepAlive                             | *\u0026#10008;*\n\n### Helper Functionality\n\nThese are helpers that have been implemented to to ensure interactions with the HTTP API only occur if they will not be rejected e.g. [channel naming conventions](https://pusher.com/docs/client_api_guide/client_channels#naming-channels).\n\nHelper Functionality                     | Supported\n-----------------------------------------| :-------:\nChannel name validation                  | \u0026#10004;\nLimit to 10 channels per trigger         | \u0026#10004;\nLimit event name length to 200 chars     | \u0026#10004;\n\n## Developing the Library\n\nFeel more than free to fork this repo, improve it in any way you'd prefer, and send us a pull request :)\n\n### Running the tests\n\nSimply type:\n\n```bash\n$ cargo test\n```\n\n## License\n\nThis code is free to use under the terms of the MIT license.\n\n## To Do\n\n* Review the use of different string types.\n* More test coverage\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwillsewell%2Fpusher-http-rust","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwillsewell%2Fpusher-http-rust","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwillsewell%2Fpusher-http-rust/lists"}