{"id":13366719,"url":"https://github.com/appleboy/Gorush","last_synced_at":"2025-03-12T18:31:17.218Z","repository":{"id":37821004,"uuid":"54453471","full_name":"appleboy/gorush","owner":"appleboy","description":"A push notification server written in Go (Golang).","archived":false,"fork":false,"pushed_at":"2024-04-25T10:33:43.000Z","size":5835,"stargazers_count":7756,"open_issues_count":51,"forks_count":826,"subscribers_count":194,"default_branch":"master","last_synced_at":"2024-05-21T07:34:59.744Z","etag":null,"topics":["android","apns","gcm","golang","gorush-server","ios","ios-alert-payload","ios-notification","notification-server"],"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/appleboy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"github":"appleboy","patreon":null,"open_collective":"gorush","ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":["https://www.paypal.me/appleboy46"]}},"created_at":"2016-03-22T07:15:20.000Z","updated_at":"2024-05-21T02:29:00.000Z","dependencies_parsed_at":"2023-02-17T14:46:04.617Z","dependency_job_id":"a56746d4-7496-4368-93f6-04f8684681fb","html_url":"https://github.com/appleboy/gorush","commit_stats":{"total_commits":939,"total_committers":55,"mean_commits":"17.072727272727274","dds":0.09691160809371668,"last_synced_commit":"2c3391e58a4f711dee9caa87dfc9e7f6d1d4166c"},"previous_names":["appleboy/gopush"],"tags_count":47,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/appleboy%2Fgorush","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/appleboy%2Fgorush/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/appleboy%2Fgorush/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/appleboy%2Fgorush/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/appleboy","download_url":"https://codeload.github.com/appleboy/gorush/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243271262,"owners_count":20264422,"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":["android","apns","gcm","golang","gorush-server","ios","ios-alert-payload","ios-notification","notification-server"],"created_at":"2024-07-30T00:01:30.379Z","updated_at":"2025-03-12T18:31:17.203Z","avatar_url":"https://github.com/appleboy.png","language":"Go","funding_links":["https://github.com/sponsors/appleboy","https://opencollective.com/gorush","https://www.paypal.me/appleboy46"],"categories":["消息"],"sub_categories":["高级控制台界面","高級控制台界面"],"readme":"# gorush\n\nA push notification micro server using [Gin](https://github.com/gin-gonic/gin) framework written in Go (Golang) and see the [demo app](https://github.com/appleboy/flutter-gorush).\n\n[![Run Lint and Testing](https://github.com/appleboy/gorush/actions/workflows/testing.yml/badge.svg)](https://github.com/appleboy/gorush/actions/workflows/testing.yml)\n[![GoDoc](https://godoc.org/github.com/appleboy/gorush?status.svg)](https://pkg.go.dev/github.com/appleboy/gorush)\n[![codecov](https://codecov.io/gh/appleboy/gorush/branch/master/graph/badge.svg)](https://codecov.io/gh/appleboy/gorush)\n[![Go Report Card](https://goreportcard.com/badge/github.com/appleboy/gorush)](https://goreportcard.com/report/github.com/appleboy/gorush)\n[![codebeat badge](https://codebeat.co/badges/0a4eff2d-c9ac-46ed-8fd7-b59942983390)](https://codebeat.co/projects/github-com-appleboy-gorush)\n[![Docker Pulls](https://img.shields.io/docker/pulls/appleboy/gorush.svg)](https://hub.docker.com/r/appleboy/gorush/)\n[![Netlify Status](https://api.netlify.com/api/v1/badges/8ab14c9f-44fd-4d9a-8bba-f73f76d253b1/deploy-status)](https://app.netlify.com/sites/gorush/deploys)\n[![Financial Contributors on Open Collective](https://opencollective.com/gorush/all/badge.svg?label=financial+contributors)](https://opencollective.com/gorush)\n\n## Contents\n\n- [gorush](#gorush)\n  - [Contents](#contents)\n  - [Support Platform](#support-platform)\n  - [Features](#features)\n  - [Memory Usage](#memory-usage)\n  - [Basic Usage](#basic-usage)\n    - [Install from homebrew](#install-from-homebrew)\n    - [Download a binary](#download-a-binary)\n    - [Install from source](#install-from-source)\n      - [Prerequisite Tools](#prerequisite-tools)\n      - [Fetch from GitHub](#fetch-from-github)\n    - [Command Usage](#command-usage)\n    - [Send Android notification](#send-android-notification)\n    - [Send Huawei (HMS) notification](#send-huawei-hms-notification)\n    - [Send iOS notification](#send-ios-notification)\n    - [Send Android or iOS notifications using Firebase Cloud Messaging](#send-android-or-ios-notifications-using-firebase-cloud-messaging)\n  - [Run gorush web server](#run-gorush-web-server)\n  - [Web API](#web-api)\n    - [GET /api/stat/go](#get-apistatgo)\n    - [GET /api/stat/app](#get-apistatapp)\n    - [GET /sys/stats](#get-sysstats)\n    - [GET /metrics](#get-metrics)\n    - [POST /api/push](#post-apipush)\n    - [Request body](#request-body)\n    - [iOS alert payload](#ios-alert-payload)\n    - [iOS sound payload](#ios-sound-payload)\n    - [Android notification payload](#android-notification-payload)\n    - [Huawei notification](#huawei-notification)\n    - [iOS Example](#ios-example)\n    - [Android Example](#android-example)\n    - [Huawei Example](#huawei-example)\n    - [Response body](#response-body)\n  - [Run gRPC service](#run-grpc-service)\n  - [Run gorush in Docker](#run-gorush-in-docker)\n  - [Run gorush in Kubernetes](#run-gorush-in-kubernetes)\n    - [Quick Start](#quick-start)\n    - [Create the Service Controller for AWS ELB](#create-the-service-controller-for-aws-elb)\n    - [Ingress Controller for AWS ALB](#ingress-controller-for-aws-alb)\n    - [Clean up the gorush](#clean-up-the-gorush)\n  - [Run gorush in AWS Lambda](#run-gorush-in-aws-lambda)\n    - [Build gorush binary](#build-gorush-binary)\n    - [Deploy gorush application](#deploy-gorush-application)\n    - [Without an AWS account](#without-an-aws-account)\n  - [Stargazers over time](#stargazers-over-time)\n  - [License](#license)\n\n## Support Platform\n\n- [APNS](https://developer.apple.com/documentation/usernotifications)\n- [FCM](https://firebase.google.com/)\n- [HMS](https://developer.huawei.com/consumer/en/hms/)\n\n[A live server on Netlify](https://gorush.netlify.app/) and get notification token on [Firebase Cloud Messaging web](https://fcm-demo-88b40.web.app/). You can use the token to send a notification to the device.\n\n```bash\ncurl -X POST \\\n     -H \"Content-Type: application/json\" \\\n     -d '{\n  \"notifications\": [\n    {\n      \"tokens\": [\n        \"your_device_token\"\n      ],\n      \"platform\": 2,\n      \"title\": \"Test Title\",\n      \"message\": \"Test Message\"\n    }\n  ]\n}' \\\n  https://gorush.netlify.app/api/push\n```\n\n## Features\n\n- Support [Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging) using [go-fcm](https://github.com/appleboy/go-fcm) library for Android.\n- Support [HTTP/2](https://http2.github.io/) Apple Push Notification Service using [apns2](https://github.com/sideshow/apns2) library.\n- Support [HMS Push Service](https://developer.huawei.com/consumer/en/hms/huawei-pushkit) using [go-hms-push](https://github.com/msalihkarakasli/go-hms-push) library for Huawei Devices.\n- Support [YAML](https://github.com/go-yaml/yaml) configuration.\n- Support command line to send single Android or iOS notification.\n- Support Web API to send push notification.\n- Support [HTTP/2](https://http2.github.io/) or HTTP/1.1 protocol.\n- Support notification queue and multiple workers.\n- Support `/api/stat/app` show notification success and failure counts.\n- Support `/api/config` show your [YAML](https://en.wikipedia.org/wiki/YAML) config.\n- Support store app stat to memory, [Redis](http://redis.io/), [BoltDB](https://github.com/boltdb/bolt), [BuntDB](https://github.com/tidwall/buntdb), [LevelDB](https://github.com/syndtr/goleveldb) or [BadgerDB](https://github.com/dgraph-io/badger).\n- Support `p8`, `p12` or `pem` format of iOS certificate file.\n- Support `/sys/stats` show response time, status code count, etc.\n- Support for HTTP, HTTPS or SOCKS5 proxy.\n- Support retry send notification if server response is fail.\n- Support expose [prometheus](https://prometheus.io/) metrics.\n- Support install TLS certificates from [Let's Encrypt](https://letsencrypt.org/) automatically.\n- Support send notification through [RPC](https://en.wikipedia.org/wiki/Remote_procedure_call) protocol, we use [gRPC](https://grpc.io/) as default framework.\n- Support running in Docker, [Kubernetes](https://kubernetes.io/) or [AWS Lambda](https://aws.amazon.com/lambda) ([Native Support in Golang](https://aws.amazon.com/blogs/compute/announcing-go-support-for-aws-lambda/))\n- Support graceful shutdown that workers and queue have been sent to APNs/FCM before shutdown service.\n- Support different Queue as backend like [NSQ](https://nsq.io/), [NATS](https://nats.io/) or [Redis streams](https://redis.io/docs/manual/data-types/streams/), defaut engine is local [Channel](https://tour.golang.org/concurrency/2).\n\nSee the default [YAML config example](config/testdata/config.yml):\n\n```yaml\ncore:\n  enabled: true # enable httpd server\n  address: \"\" # ip address to bind (default: any)\n  shutdown_timeout: 30 # default is 30 second\n  port: \"8088\" # ignore this port number if auto_tls is enabled (listen 443).\n  worker_num: 0 # default worker number is runtime.NumCPU()\n  queue_num: 0 # default queue number is 8192\n  max_notification: 100\n  # set true if you need get error message from fail push notification in API response.\n  # It only works when the queue engine is local.\n  sync: false\n  # set webhook url if you need get error message asynchronously from fail push notification in API response.\n  feedback_hook_url: \"\"\n  feedback_timeout: 10 # default is 10 second\n  feedback_header:\n  mode: \"release\"\n  ssl: false\n  cert_path: \"cert.pem\"\n  key_path: \"key.pem\"\n  cert_base64: \"\"\n  key_base64: \"\"\n  http_proxy: \"\"\n  pid:\n    enabled: false\n    path: \"gorush.pid\"\n    override: true\n  auto_tls:\n    enabled: false # Automatically install TLS certificates from Let's Encrypt.\n    folder: \".cache\" # folder for storing TLS certificates\n    host: \"\" # which domains the Let's Encrypt will attempt\n\ngrpc:\n  enabled: false # enable gRPC server\n  port: 9000\n\napi:\n  push_uri: \"/api/push\"\n  stat_go_uri: \"/api/stat/go\"\n  stat_app_uri: \"/api/stat/app\"\n  config_uri: \"/api/config\"\n  sys_stat_uri: \"/sys/stats\"\n  metric_uri: \"/metrics\"\n  health_uri: \"/healthz\"\n\nandroid:\n  enabled: true\n  key_path: \"\" # path to fcm key file\n  credential: \"\" # fcm credential data\n  max_retry: 0 # resend fail notification, default value zero is disabled\n\nhuawei:\n  enabled: false\n  appsecret: \"YOUR_APP_SECRET\"\n  appid: \"YOUR_APP_ID\"\n  max_retry: 0 # resend fail notification, default value zero is disabled\n\nqueue:\n  engine: \"local\" # support \"local\", \"nsq\", \"nats\" and \"redis\" default value is \"local\"\n  nsq:\n    addr: 127.0.0.1:4150\n    topic: gorush\n    channel: gorush\n  nats:\n    addr: 127.0.0.1:4222\n    subj: gorush\n    queue: gorush\n  redis:\n    addr: 127.0.0.1:6379\n    group: gorush\n    consumer: gorush\n    stream_name: gorush\n  redis:\n    addr: 127.0.0.1:6379\n    group: gorush\n    consumer: gorush\n    stream_name: gorush\n    with_tls: false\n    username: \"\"\n    password: \"\"\n\nios:\n  enabled: false\n  key_path: \"\"\n  key_base64: \"\" # load iOS key from base64 input\n  key_type: \"pem\" # could be pem, p12 or p8 type\n  password: \"\" # certificate password, default as empty string.\n  production: false\n  max_concurrent_pushes: 100 # just for push ios notification\n  max_retry: 0 # resend fail notification, default value zero is disabled\n  key_id: \"\" # KeyID from developer account (Certificates, Identifiers \u0026 Profiles -\u003e Keys)\n  team_id: \"\" # TeamID from developer account (View Account -\u003e Membership)\n\nlog:\n  format: \"string\" # string or json\n  access_log: \"stdout\" # stdout: output to console, or define log path like \"log/access_log\"\n  access_level: \"debug\"\n  error_log: \"stderr\" # stderr: output to console, or define log path like \"log/error_log\"\n  error_level: \"error\"\n  hide_token: true\n  hide_messages: false\n\nstat:\n  engine: \"memory\" # support memory, redis, boltdb, buntdb or leveldb\n  redis:\n    cluster: false\n    addr: \"localhost:6379\" # if cluster is true, you may set this to \"localhost:6379,localhost:6380,localhost:6381\"\n    username: \"\"\n    password: \"\"\n    db: 0\n  boltdb:\n    path: \"bolt.db\"\n    bucket: \"gorush\"\n  buntdb:\n    path: \"bunt.db\"\n  leveldb:\n    path: \"level.db\"\n  badgerdb:\n    path: \"badger.db\"\n```\n\n## Memory Usage\n\nMemory average usage: **28Mb** (the total bytes of memory obtained from the OS.)\n\n![memory usage](screenshot/memory.png)\n\nTest Command (We use [bat](https://github.com/astaxie/bat) as default cli tool.):\n\n```sh\nfor i in {1..9999999}; do bat -b.N=1000 -b.C=100 POST localhost:8088/api/push notifications:=@notification.json; sleep 1;  done\n```\n\n## Basic Usage\n\nHow to send push notification using `gorush` command? (Android or iOS)\n\n### Install from homebrew\n\n```sh\nbrew tap appleboy/tap\nbrew install gorush\n```\n\n### Download a binary\n\nThe pre-compiled binaries can be downloaded from [release page](https://github.com/appleboy/gorush/releases).\n\nWith `Go` installed\n\n```sh\ngo install github.com/appleboy/gorush\n```\n\nOn linux\n\n```sh\nwget https://github.com/appleboy/gorush/releases/download/v1.18.9/gorush-1.18.9-linux-amd64 -O gorush\n```\n\nOn macOS (Intel amd64)\n\n```sh\nwget -c https://github.com/appleboy/gorush/releases/download/v1.18.9/gorush-1.18.9-darwin-amd64 -O gorush\n```\n\nOn macOS (Apple arm64)\n\n```sh\nwget -c https://github.com/appleboy/gorush/releases/download/v1.18.9/gorush-1.18.9-darwin-arm64 -O gorush\n```\n\n### Install from source\n\n#### Prerequisite Tools\n\n- [Git](http://git-scm.com/)\n- [Go (at least Go 1.22)](https://go.dev/dl/)\n\n#### Fetch from GitHub\n\nGorush uses the Go Modules support built into Go 1.11 to build. The easiest way to get started is to clone Gorush in a directory outside of the GOPATH, as in the following example:\n\n```sh\nmkdir $HOME/src\ncd $HOME/src\ngit clone https://github.com/appleboy/gorush.git\ncd gorush\ngo install\n```\n\nor you can use the `go get` command to install the latest or specific version.\n\n**Note**: such go get installation aren't guaranteed to work. We recommend using binary installation.\n\n```sh\n# install stable version\ngo install github.com/appleboy/gorush\n\n# install latest version\ngo install github.com/appleboy/gorush@master\n```\n\n### Command Usage\n\n```sh\n  ________                              .__\n /  _____/   ____ _______  __ __  ______|  |__\n/   \\  ___  /  _ \\\\_  __ \\|  |  \\/  ___/|  |  \\\n\\    \\_\\  \\(  \u003c_\u003e )|  | \\/|  |  /\\___ \\ |   Y  \\\n \\______  / \\____/ |__|   |____//____  \u003e|___|  /\n        \\/                           \\/      \\/\n\nUsage: gorush [options]\n\nServer Options:\n    -A, --address \u003caddress\u003e          Address to bind (default: any)\n    -p, --port \u003cport\u003e                Use port for clients (default: 8088)\n    -c, --config \u003cfile\u003e              Configuration file path\n    -m, --message \u003cmessage\u003e          Notification message\n    -t, --token \u003ctoken\u003e              Notification token\n    -e, --engine \u003cengine\u003e            Storage engine (memory, redis ...)\n    --title \u003ctitle\u003e                  Notification title\n    --proxy \u003cproxy\u003e                  Proxy URL\n    --pid \u003cpid path\u003e                 Process identifier path\n    --redis-addr \u003credis addr\u003e        Redis addr (default: localhost:6379)\n    --ping                           healthy check command for container\niOS Options:\n    -i, --key \u003cfile\u003e                 certificate key file path\n    -P, --password \u003cpassword\u003e        certificate key password\n    --ios                            enabled iOS (default: false)\n    --production                     iOS production mode (default: false)\nAndroid Options:\n    --fcm-key \u003cfcm_key_path\u003e         FCM Key Path\n    --android                        enabled android (default: false)\nHuawei Options:\n    -hk, --hmskey \u003chms_key\u003e          HMS App Secret\n    -hid, --hmsid \u003chms_id\u003e           HMS App ID\n    --huawei                         enabled huawei (default: false)\nCommon Options:\n    --topic \u003ctopic\u003e                  iOS, Android or Huawei topic message\n    -h, --help                       Show this message\n    -V, --version                    Show version\n```\n\n### Send Android notification\n\nTo authenticate a service account and authorize it to access Firebase services, you must generate a private key file in JSON format.\n\n1. In the Firebase console, open **Settings** \u003e [Service Accounts](https://console.firebase.google.com/project/_/settings/serviceaccounts/adminsdk?_gl=1*1eqxjfp*_ga*MTQ0NjI5MTQ2MS4xNzA4NjA3MzU0*_ga_CW55HF8NVT*MTcxNzgxNDMyNi4xMS4xLjE3MTc4MTUyMzguNjAuMC4w).\n2. Click **Generate New Private Key**, then confirm by clicking **Generate Key**.\n3. Securely store the JSON file containing the key.\n\nWhen authorizing via a service account, you have two choices for providing the credentials to your application. You can either set the **GOOGLE_APPLICATION_CREDENTIALS** environment variable, or you can explicitly pass the path to the service account key in code. The first option is more secure and is strongly recommended.\n\nSend single notification with the following command.\n\n```bash\ngorush -android -m \"your message\" --fcm-key \"FCM Credentials Key Path\" -t \"device token\"\n\n# or set GOOGLE_APPLICATION_CREDENTIALS environment variable\nexport GOOGLE_APPLICATION_CREDENTIALS=\"FCM Credentials Key Path\"\ngorush -android -m \"your message\" -t \"device token\"\n```\n\nSend messages to topics.\n\n```bash\ngorush --android --topic \"foo-bar\" \\\n  -m \"This is a Firebase Cloud Messaging Topic Message\" \\\n  --fcm-key \"FCM Credentials Key Path\"\n```\n\n- `-m`: Notification message.\n- `--fcm-key`: [Firebase Cloud Messaging Provide credentials manually](https://firebase.google.com/docs/cloud-messaging/auth-server#provide-credentials-manually)\n- `-t`: Device token.\n- `--title`: Notification title.\n- `--topic`: Send messages to topics. note: don't add device token.\n- `--proxy`: Set `http`, `https` or `socks5` proxy url.\n\n### Send Huawei (HMS) notification\n\nSend single notification with the following command.\n\n```bash\ngorush -huawei -title \"Gorush with HMS\" -m \"your message\" -hk \"API Key\" -hid \"App ID\" -t \"Device token\"\n```\n\nSend messages to topics.\n\n```bash\ngorush --huawei --topic \"foo-bar\" \\\n  -title \"Gorush with HMS\" \\\n  -m \"This is a Huawei Mobile Services Topic Message\" \\\n  -hk \"API Key\" \\\n  -hid \"App ID\"\n```\n\n- `-m`: Notification message.\n- `-hk`: [Huawei Mobile Services](https://developer.huawei.com/consumer/en/doc/development/HMS-Guides/Preparations) api secret key\n- `-t`: Device token.\n- `--title`: Notification title.\n- `--topic`: Send messages to topics. note: don't add device token.\n- `--proxy`: Set `http`, `https` or `socks5` proxy url.\n\n### Send iOS notification\n\nSend single notification with the following command.\n\n```bash\n$ gorush -ios -m \"your message\" -i \"your certificate path\" \\\n  -t \"device token\" --topic \"apns topic\"\n```\n\n- `-m`: Notification message.\n- `-i`: Apple Push Notification Certificate path (`pem` or `p12` file).\n- `-t`: Device token.\n- `--title`: Notification title.\n- `--topic`: The topic of the remote notification.\n- `--password`: The certificate password.\n\nThe default endpoint is APNs development. Please add `-production` flag for APNs production push endpoint.\n\n```bash\n$ gorush -ios -m \"your message\" -i \"your certificate path\" \\\n  -t \"device token\" \\\n  -production\n```\n\n### Send Android or iOS notifications using Firebase Cloud Messaging\n\nSend single notification with the following command:\n\n```bash\ngorush -android -m \"your message\" \\\n  --fcm-key \"FCM Credentials Key Path\" \\\n  -t \"Device token\"\n```\n\n## Run gorush web server\n\nPlease make sure your [config.yml](config/testdata/config.yml) exist. Default port is `8088`.\n\n```bash\n# for default config\n$ gorush\n# for custom config file\n$ gorush -c config.yml\n```\n\nGet go status of api server using [httpie](https://github.com/httpie/cli) tool:\n\n```bash\n# install httpie\nbrew install httpie\n# get go status\nhttp -v --json GET http://localhost:8088/api/stat/go\n```\n\n## Web API\n\nGorush support the following API.\n\n- **GET** `/api/stat/go` Golang cpu, memory, gc, etc information. Thanks for [golang-stats-api-handler](https://github.com/fukata/golang-stats-api-handler).\n- **GET** `/api/stat/app` show notification success and failure counts.\n- **GET** `/api/config` show server yml config file.\n- **POST** `/api/push` push ios, android or huawei notifications.\n\n### GET /api/stat/go\n\nGolang cpu, memory, gc, etc information. Response with `200` http status code.\n\n```json\n{\n  \"time\": 1460686815848046600,\n  \"go_version\": \"go1.6.1\",\n  \"go_os\": \"darwin\",\n  \"go_arch\": \"amd64\",\n  \"cpu_num\": 4,\n  \"goroutine_num\": 15,\n  \"gomaxprocs\": 4,\n  \"cgo_call_num\": 1,\n  \"memory_alloc\": 7455192,\n  \"memory_total_alloc\": 8935464,\n  \"memory_sys\": 12560632,\n  \"memory_lookups\": 17,\n  \"memory_mallocs\": 31426,\n  \"memory_frees\": 11772,\n  \"memory_stack\": 524288,\n  \"heap_alloc\": 7455192,\n  \"heap_sys\": 8912896,\n  \"heap_idle\": 909312,\n  \"heap_inuse\": 8003584,\n  \"heap_released\": 0,\n  \"heap_objects\": 19654,\n  \"gc_next\": 9754725,\n  \"gc_last\": 1460686815762559700,\n  \"gc_num\": 2,\n  \"gc_per_second\": 0,\n  \"gc_pause_per_second\": 0,\n  \"gc_pause\": [0.326576, 0.227096]\n}\n```\n\n### GET /api/stat/app\n\nShow success or failure counts information of notification.\n\n```json\n{\n  \"version\": \"v1.6.2\",\n  \"busy_workers\": 0,\n  \"success_tasks\": 32,\n  \"failure_tasks\": 49,\n  \"submitted_tasks\": 81,\n  \"total_count\": 81,\n  \"ios\": {\n    \"push_success\": 19,\n    \"push_error\": 38\n  },\n  \"android\": {\n    \"push_success\": 10,\n    \"push_error\": 10\n  },\n  \"huawei\": {\n    \"push_success\": 3,\n    \"push_error\": 1\n  }\n}\n```\n\n### GET /sys/stats\n\nShow response time, status code count, etc.\n\n```json\n{\n  \"pid\": 80332,\n  \"uptime\": \"1m42.428010614s\",\n  \"uptime_sec\": 102.428010614,\n  \"time\": \"2016-06-26 12:27:11.675973571 +0800 CST\",\n  \"unixtime\": 1466915231,\n  \"status_code_count\": {},\n  \"total_status_code_count\": {\n    \"200\": 5\n  },\n  \"count\": 0,\n  \"total_count\": 5,\n  \"total_response_time\": \"10.422441ms\",\n  \"total_response_time_sec\": 0.010422441000000001,\n  \"average_response_time\": \"2.084488ms\",\n  \"average_response_time_sec\": 0.0020844880000000002\n}\n```\n\n### GET /metrics\n\nSupport expose [prometheus](https://prometheus.io/) metrics.\n\n![metrics screenshot](screenshot/metrics.png)\n\n### POST /api/push\n\nSimple send iOS notification example, the `platform` value is `1`:\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 1,\n      \"message\": \"Hello World iOS!\"\n    }\n  ]\n}\n```\n\nSimple send Android notification example, the `platform` value is `2`:\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 2,\n      \"message\": \"Hello World Android!\"\n    }\n  ]\n}\n```\n\nSimple send Huawei notification example, the `platform` value is `3`:\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 3,\n      \"title\": \"Gorush with HMS\",\n      \"message\": \"Hello World Huawei!\"\n    }\n  ]\n}\n```\n\nSimple send notification on Android and iOS devices using Firebase, the `platform` value is `2`:\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 2,\n      \"message\": \"This notification will go to iOS and Android platform via Firebase!\"\n    }\n  ]\n}\n```\n\nSend notification with custom sound on iOS devices, **volume must be in the interval [0, 1]**:\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"title\": \"Hello World iOS!\",\n      \"message\": \"Hello World iOS!\",\n      \"platform\": 2,\n      \"apns\": {\n        \"payload\": {\n          \"aps\": {\n            \"sound\": {\n              \"name\": \"default\",\n              \"critical\": 1,\n              \"volume\": 0.1\n            }\n          }\n        }\n      }\n    }\n  ]\n}\n```\n\nSend multiple notifications as below:\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 1,\n      \"message\": \"Hello World iOS!\"\n    },\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 2,\n      \"message\": \"Hello World Android!\"\n    },\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 3,\n      \"message\": \"Hello World Huawei!\",\n      \"title\": \"Gorush with HMS\"\n    },\n    .....\n  ]\n}\n```\n\nSee more example about [iOS](#ios-example), [Android](#android-example) or [Huawei](#huawei-example)\n\n### Request body\n\nThe Request body must have a notifications array. The following is a parameter table for each notification.\n\n| name                    | type         | description                                                                                       | required | note                                                          |\n| ----------------------- | ------------ | ------------------------------------------------------------------------------------------------- | -------- | ------------------------------------------------------------- |\n| notif_id                | string       | A unique string that identifies the notification for async feedback                               | -        |                                                               |\n| tokens                  | string array | device tokens                                                                                     | o        |                                                               |\n| platform                | int          | platform(iOS,Android)                                                                             | o        | 1=iOS, 2=Android (Firebase), 3=Huawei (HMS)                   |\n| message                 | string       | message for notification                                                                          | -        |                                                               |\n| title                   | string       | notification title                                                                                | -        |                                                               |\n| priority                | string       | Sets the priority of the message.                                                                 | -        | `normal` or `high`                                            |\n| content_available       | bool         | data messages wake the app by default.                                                            | -        |                                                               |\n| sound                   | interface{}  | sound type                                                                                        | -        |                                                               |\n| data                    | string array | extensible partition                                                                              | -        | only Android and IOS                                          |\n| huawei_data             | string       | JSON object as string to extensible partition partition                                           | -        | only Huawei. See the [detail](#huawei-notification)           |\n| retry                   | int          | retry send notification if fail response from server. Value must be small than `max_retry` field. | -        |                                                               |\n| topic                   | string       | send messages to topics                                                                           |          |                                                               |\n| image                   | string       | image url to show in notification                                                                 | -        | only Android and Huawei                                       |\n| to                      | string       | The value must be a registration token, notification key, or topic.                               | -        | only Android                                                  |\n| collapse_key            | string       | a key for collapsing notifications                                                                | -        | only Android                                                  |\n| huawei_collapse_key     | int          | a key integer for collapsing notifications                                                        | -        | only Huawei See the [detail](#huawei-notification)            |\n| delay_while_idle        | bool         | a flag for device idling                                                                          | -        | only Android                                                  |\n| time_to_live            | uint         | expiration of message kept on FCM storage                                                         | -        | only Android                                                  |\n| huawei_ttl              | string       | expiration of message kept on HMS storage                                                         | -        | only Huawei See the [detail](#huawei-notification)            |\n| restricted_package_name | string       | the package name of the application                                                               | -        | only Android                                                  |\n| dry_run                 | bool         | allows developers to test a request without actually sending a message                            | -        | only Android                                                  |\n| notification            | string array | payload of a FCM message                                                                          | -        | only Android. See the [detail](#android-notification-payload) |\n| huawei_notification     | string array | payload of a HMS message                                                                          | -        | only Huawei. See the [detail](#huawei-notification)           |\n| app_id                  | string       | hms app id                                                                                        | -        | only Huawei. See the [detail](#huawei-notification)           |\n| bi_tag                  | string       | Tag of a message in a batch delivery task                                                         | -        | only Huawei. See the [detail](#huawei-notification)           |\n| fast_app_target         | int          | State of a mini program when a quick app sends a data message.                                    | -        | only Huawei. See the [detail](#huawei-notification)           |\n| expiration              | int          | expiration for notification                                                                       | -        | only iOS                                                      |\n| apns_id                 | string       | A canonical UUID that identifies the notification                                                 | -        | only iOS                                                      |\n| collapse_id             | string       | An identifier you use to coalesce multiple notifications into a single notification for the user  | -        | only iOS                                                      |\n| push_type               | string       | The type of the notification. The value of this header is alert or background.                    | -        | only iOS                                                      |\n| badge                   | int          | badge count                                                                                       | -        | only iOS                                                      |\n| category                | string       | the UIMutableUserNotificationCategory object                                                      | -        | only iOS                                                      |\n| alert                   | string array | payload of a iOS message                                                                          | -        | only iOS. See the [detail](#ios-alert-payload)                |\n| mutable_content         | bool         | enable Notification Service app extension.                                                        | -        | only iOS(10.0+).                                              |\n| name                    | string       | sets the name value on the aps sound dictionary.                                                  | -        | only iOS                                                      |\n| volume                  | float32      | sets the volume value on the aps sound dictionary.                                                | -        | only iOS                                                      |\n| interruption_level      | string       | defines the interruption level for the push notification.                                         | -        | only iOS(15.0+)                                               |\n| content-state           | string array | dynamic and custom content for live-activity notification.                                        | -        | only iOS(16.1+)                                               |\n| timestamp               | int          | the UNIX time when sending the remote notification that updates or ends a Live Activity           | -        | only iOS(16.1+)                                               |\n| event                   | string       | describes whether you update or end an ongoing Live Activity                                      | -        | only iOS(16.1+)                                               |\n| stale-date              | int          | the date which a Live Activity becomes stale, or out of date                                      | -        | only iOS(16.1+)                                               |\n| dismissal-date          | int          | the UNIX time -timestamp- which a Live Activity will end and will be removed                      | -        | only iOS(16.1+)                                               |\n\n### iOS alert payload\n\n| name           | type             | description                                                                                      | required | note |\n| -------------- | ---------------- | ------------------------------------------------------------------------------------------------ | -------- | ---- |\n| title          | string           | Apple Watch \u0026 Safari display this string as part of the notification interface.                  | -        |      |\n| body           | string           | The text of the alert message.                                                                   | -        |      |\n| subtitle       | string           | Apple Watch \u0026 Safari display this string as part of the notification interface.                  | -        |      |\n| action         | string           | The label of the action button. This one is required for Safari Push Notifications.              | -        |      |\n| action-loc-key | string           | If a string is specified, the system displays an alert that includes the Close and View buttons. | -        |      |\n| launch-image   | string           | The filename of an image file in the app bundle, with or without the filename extension.         | -        |      |\n| loc-args       | array of strings | Variable string values to appear in place of the format specifiers in loc-key.                   | -        |      |\n| loc-key        | string           | A key to an alert-message string in a Localizable.strings file for the current localization.     | -        |      |\n| title-loc-args | array of strings | Variable string values to appear in place of the format specifiers in title-loc-key.             | -        |      |\n| title-loc-key  | string           | The key to a title string in the Localizable.strings file for the current localization.          | -        |      |\n\nSee more detail about [APNs Remote Notification Payload](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html).\n\n### iOS sound payload\n\n| name     | type    | description                                          | required | note |\n| -------- | ------- | ---------------------------------------------------- | -------- | ---- |\n| name     | string  | sets the name value on the aps sound dictionary.     | -        |      |\n| volume   | float32 | sets the volume value on the aps sound dictionary.   | -        |      |\n| critical | int     | sets the critical value on the aps sound dictionary. | -        |      |\n\nrequest format:\n\n```json\n{\n  \"sound\": {\n    \"critical\": 1,\n    \"name\": \"default\",\n    \"volume\": 2.0\n  }\n}\n```\n\n### Android notification payload\n\n| name           | type   | description                                                                                               | required | note |\n| -------------- | ------ | --------------------------------------------------------------------------------------------------------- | -------- | ---- |\n| icon           | string | Indicates notification icon.                                                                              | -        |      |\n| tag            | string | Indicates whether each notification message results in a new entry on the notification center on Android. | -        |      |\n| color          | string | Indicates color of the icon, expressed in #rrggbb format                                                  | -        |      |\n| click_action   | string | The action associated with a user click on the notification.                                              | -        |      |\n| body_loc_key   | string | Indicates the key to the body string for localization.                                                    | -        |      |\n| body_loc_args  | string | Indicates the string value to replace format specifiers in body string for localization.                  | -        |      |\n| title_loc_key  | string | Indicates the key to the title string for localization.                                                   | -        |      |\n| title_loc_args | string | Indicates the string value to replace format specifiers in title string for localization.                 | -        |      |\n\nSee more detail about [Firebase Cloud Messaging HTTP Protocol reference](https://firebase.google.com/docs/cloud-messaging/http-server-ref#send-downstream).\n\n### Huawei notification\n\n1. app_id: app id from huawei developer console\n2. bi_tag:\n3. fast_app_target:\n4. huawei_data: mapped to data\n5. huawei_notification: mapped to notification\n6. huawei_ttl: mapped to ttl\n7. huawei_collapse_key: mapped to collapse_key\n\nSee more detail about [Huawei Mobulse Services Push API reference](https://developer.huawei.com/consumer/en/doc/development/HMS-References/push-sendapi).\n\n### iOS Example\n\nSend normal notification.\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 1,\n      \"message\": \"Hello World iOS!\"\n    }\n  ]\n}\n```\n\nThe following payload asks the system to display an alert with a Close button and a single action button.The title and body keys provide the contents of the alert. The “PLAY” string is used to retrieve a localized string from the appropriate Localizable.strings file of the app. The resulting string is used by the alert as the title of an action button. This payload also asks the system to badge the app’s icon with the number 5.\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 1,\n      \"badge\": 5,\n      \"alert\": {\n        \"title\": \"Game Request\",\n        \"body\": \"Bob wants to play poker\",\n        \"action-loc-key\": \"PLAY\"\n      }\n    }\n  ]\n}\n```\n\nThe following payload specifies that the device should display an alert message, plays a sound, and badges the app’s icon.\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 1,\n      \"message\": \"You got your emails.\",\n      \"badge\": 9,\n      \"sound\": {\n        \"critical\": 1,\n        \"name\": \"default\",\n        \"volume\": 1.0\n      }\n    }\n  ]\n}\n```\n\nAdd other fields which user defined via `data` field.\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 1,\n      \"message\": \"Hello World iOS!\",\n      \"data\": {\n        \"key1\": \"welcome\",\n        \"key2\": 2\n      }\n    }\n  ]\n}\n```\n\nSupport send notification from different environment. See the detail of [issue](https://github.com/appleboy/gorush/issues/246).\n\n```diff\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 1,\n+     \"production\": true,\n      \"message\": \"Hello World iOS Production!\"\n    },\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 1,\n+     \"development\": true,\n      \"message\": \"Hello World iOS Sandbox!\"\n    }\n  ]\n}\n```\n\n### Android Example\n\nSend normal notification.\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 2,\n      \"message\": \"Hello World Android!\",\n      \"title\": \"You got message\"\n    }\n  ]\n}\n```\n\nLabel associated with the message's analytics data.\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 2,\n      \"message\": \"Hello World Android!\",\n      \"title\": \"You got message\",\n      \"fcm_options\": {\n        \"analytics_label\": \"example\"\n      }\n    }\n  ]\n}\n```\n\nAdd `notification` payload.\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 2,\n      \"message\": \"Hello World Android!\",\n      \"title\": \"You got message\",\n      \"notification\": {\n        \"icon\": \"myicon\",\n        \"color\": \"#112244\"\n      }\n    }\n  ]\n}\n```\n\nAdd other fields which user defined via `data` field.\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 2,\n      \"message\": \"Hello World Android!\",\n      \"title\": \"You got message\",\n      \"data\": {\n        \"Nick\": \"Mario\",\n        \"body\": \"great match!\",\n        \"Room\": \"PortugalVSDenmark\"\n      }\n    }\n  ]\n}\n```\n\nSend messages to topic\n\n```json\n{\n  \"notifications\": [\n    {\n      \"topic\": \"highScores\",\n      \"platform\": 2,\n      \"message\": \"This is a Firebase Cloud Messaging Topic Message\"\n    }\n  ]\n}\n```\n\n### Huawei Example\n\nSend normal notification.\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 3,\n      \"message\": \"Hello World Huawei!\",\n      \"title\": \"You got message\"\n    }\n  ]\n}\n```\n\nAdd `notification` payload.\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 3,\n      \"message\": \"Hello World Huawei!\",\n      \"title\": \"You got message\",\n      \"huawei_notification\": {\n        \"icon\": \"myicon\",\n        \"color\": \"#112244\"\n      }\n    }\n  ]\n}\n```\n\nAdd other fields which user defined via `huawei_data` field.\n\n```json\n{\n  \"notifications\": [\n    {\n      \"tokens\": [\"token_a\", \"token_b\"],\n      \"platform\": 3,\n      \"huawei_data\": \"{'title' : 'Mario','message' : 'great match!', 'Room' : 'PortugalVSDenmark'}\"\n    }\n  ]\n}\n```\n\nSend messages to topics\n\n```json\n{\n  \"notifications\": [\n    {\n      \"topic\": \"foo-bar\",\n      \"platform\": 3,\n      \"message\": \"This is a Huawei Mobile Services Topic Message\",\n      \"title\": \"You got message\"\n    }\n  ]\n}\n```\n\n### Response body\n\nError response message table:\n\n| status code | message                                    |\n| ----------- | ------------------------------------------ |\n| 400         | Missing `notifications` field.             |\n| 400         | Notifications field is empty.              |\n| 400         | Number of notifications(50) over limit(10) |\n\nSuccess response:\n\n```json\n{\n  \"counts\": 60,\n  \"logs\": [],\n  \"success\": \"ok\"\n}\n```\n\nIf you need error logs from sending fail notifications, please set a `feedback_hook_url` and `feedback_header` for custom header. The server with send the failing logs asynchronously to your API as `POST` requests.\n\n```diff\ncore:\n  port: \"8088\" # ignore this port number if auto_tls is enabled (listen 443).\n  worker_num: 0 # default worker number is runtime.NumCPU()\n  queue_num: 0 # default queue number is 8192\n  max_notification: 100\n  sync: false\n- feedback_hook_url: \"\"\n+ feedback_hook_url: \"https://exemple.com/api/hook\"\n+ feedback_header:\n+   - x-gorush-token:4e989115e09680f44a645519fed6a976\n```\n\nYou can also switch to **sync** mode by setting the `sync` value as `true` on yaml config. It only works when the queue engine is local.\n\n```diff\ncore:\n  port: \"8088\" # ignore this port number if auto_tls is enabled (listen 443).\n  worker_num: 0 # default worker number is runtime.NumCPU()\n  queue_num: 0 # default queue number is 8192\n  max_notification: 100\n- sync: false\n+ sync: true\n```\n\nSee the following error format.\n\n```json\n{\n  \"counts\": 60,\n  \"logs\": [\n    {\n      \"type\": \"failed-push\",\n      \"platform\": \"android\",\n      \"token\": \"*******\",\n      \"message\": \"Hello World Android!\",\n      \"error\": \"InvalidRegistration\"\n    },\n    {\n      \"type\": \"failed-push\",\n      \"platform\": \"ios\",\n      \"token\": \"*****\",\n      \"message\": \"Hello World iOS1111!\",\n      \"error\": \"Post https://api.push.apple.com/3/device/bbbbb: remote error: tls: revoked certificate\"\n    },\n    {\n      \"type\": \"failed-push\",\n      \"platform\": \"ios\",\n      \"token\": \"*******\",\n      \"message\": \"Hello World iOS222!\",\n      \"error\": \"Post https://api.push.apple.com/3/device/token_b: remote error: tls: revoked certificate\"\n    }\n  ],\n  \"success\": \"ok\"\n}\n```\n\n## Run gRPC service\n\nGorush support [gRPC](https://grpc.io/) service. You can enable the gRPC in `config.yml`, default as disabled. Enable the gRPC server:\n\n```sh\nGORUSH_GRPC_ENABLED=true GORUSH_GRPC_PORT=3000 gorush\n```\n\nThe following example code to send single notification in Go.\n\n```go\npackage main\n\nimport (\n  \"context\"\n  \"log\"\n\n  \"github.com/appleboy/gorush/rpc/proto\"\n\n  structpb \"github.com/golang/protobuf/ptypes/struct\"\n  \"google.golang.org/grpc\"\n)\n\nconst (\n  address = \"localhost:9000\"\n)\n\nfunc main() {\n  // Set up a connection to the server.\n  conn, err := grpc.NewClient(address, grpc.WithInsecure())\n  if err != nil {\n    log.Fatalf(\"did not connect: %v\", err)\n  }\n  defer conn.Close()\n  c := proto.NewGorushClient(conn)\n\n  r, err := c.Send(context.Background(), \u0026proto.NotificationRequest{\n    Platform: 2,\n    Tokens:   []string{\"1234567890\"},\n    Message:  \"test message\",\n    Badge:    1,\n    Category: \"test\",\n    Sound:    \"test\",\n    Priority: proto.NotificationRequest_HIGH,\n    Alert: \u0026proto.Alert{\n      Title:    \"Test Title\",\n      Body:     \"Test Alert Body\",\n      Subtitle: \"Test Alert Sub Title\",\n      LocKey:   \"Test loc key\",\n      LocArgs:  []string{\"test\", \"test\"},\n    },\n    Data: \u0026structpb.Struct{\n      Fields: map[string]*structpb.Value{\n        \"key1\": {\n          Kind: \u0026structpb.Value_StringValue{StringValue: \"welcome\"},\n        },\n        \"key2\": {\n          Kind: \u0026structpb.Value_NumberValue{NumberValue: 2},\n        },\n      },\n    },\n  })\n  if err != nil {\n    log.Println(\"could not greet: \", err)\n  }\n\n  if r != nil {\n    log.Printf(\"Success: %t\\n\", r.Success)\n    log.Printf(\"Count: %d\\n\", r.Counts)\n  }\n}\n```\n\nSee the Node.js example and see more detail from [README](rpc/example/node/README.md):\n\n```js\nvar messages = require(\"./gorush_pb\");\nvar services = require(\"./gorush_grpc_pb\");\n\nvar grpc = require(\"grpc\");\n\nfunction main() {\n  var client = new services.GorushClient(\n    \"localhost:9000\",\n    grpc.credentials.createInsecure()\n  );\n  var request = new messages.NotificationRequest();\n  var alert = new messages.Alert();\n  request.setPlatform(2);\n  request.setTokensList([\"1234567890\"]);\n  request.setMessage(\"Hello!!\");\n  request.setTitle(\"hello2\");\n  request.setBadge(2);\n  request.setCategory(\"mycategory\");\n  request.setSound(\"sound\");\n  alert.setTitle(\"title\");\n  request.setAlert(alert);\n  request.setThreadid(\"threadID\");\n  request.setContentavailable(false);\n  request.setMutablecontent(false);\n  client.send(request, function (err, response) {\n    if (err) {\n      console.log(err);\n    } else {\n      console.log(\"Success:\", response.getSuccess());\n      console.log(\"Counts:\", response.getCounts());\n    }\n  });\n}\n\nmain();\n```\n\nGRPC Health Checking example: See [document](https://github.com/grpc/grpc/blob/master/doc/health-checking.md).\n\n```go\npackage main\n\nimport (\n  \"context\"\n  \"log\"\n\n  \"github.com/appleboy/gorush/rpc/proto\"\n\n  structpb \"github.com/golang/protobuf/ptypes/struct\"\n  \"google.golang.org/grpc\"\n)\n\nconst (\n  address = \"localhost:9000\"\n)\n\nfunc main() {\n  // Set up a connection to the server.\n  conn, err := grpc.NewClient(address, grpc.WithInsecure())\n  if err != nil {\n    log.Fatalf(\"did not connect: %v\", err)\n  }\n  defer conn.Close()\n  c := proto.NewGorushClient(conn)\n\n  r, err := c.Send(context.Background(), \u0026proto.NotificationRequest{\n    Platform: 2,\n    Tokens:   []string{\"1234567890\"},\n    Message:  \"test message\",\n    Badge:    1,\n    Category: \"test\",\n    Sound:    \"test\",\n    Priority: proto.NotificationRequest_HIGH,\n    Alert: \u0026proto.Alert{\n      Title:    \"Test Title\",\n      Body:     \"Test Alert Body\",\n      Subtitle: \"Test Alert Sub Title\",\n      LocKey:   \"Test loc key\",\n      LocArgs:  []string{\"test\", \"test\"},\n    },\n    Data: \u0026structpb.Struct{\n      Fields: map[string]*structpb.Value{\n        \"key1\": {\n          Kind: \u0026structpb.Value_StringValue{StringValue: \"welcome\"},\n        },\n        \"key2\": {\n          Kind: \u0026structpb.Value_NumberValue{NumberValue: 2},\n        },\n      },\n    },\n  })\n  if err != nil {\n    log.Println(\"could not greet: \", err)\n  }\n\n  if r != nil {\n    log.Printf(\"Success: %t\\n\", r.Success)\n    log.Printf(\"Count: %d\\n\", r.Counts)\n  }\n}\n```\n\n## Run gorush in Docker\n\nSet up `gorush` in the cloud in under 5 minutes with zero knowledge of Golang or Linux shell using our [gorush Docker image](https://hub.docker.com/r/appleboy/gorush/).\n\n```bash\ndocker pull appleboy/gorush\ndocker run --name gorush -p 80:8088 appleboy/gorush\n```\n\nRun `gorush` with your own config file.\n\n```bash\ndocker pull appleboy/gorush\ndocker run --name gorush -v ${PWD}/config.yml:/home/gorush/config.yml -p 80:8088 appleboy/gorush\n```\n\nTesting your gorush server using [httpie](https://github.com/jkbrzt/httpie) command.\n\n```bash\nhttp -v --verify=no --json GET http://your.docker.host/api/stat/go\n```\n\n![statue screenshot](screenshot/status.png)\n\n## Run gorush in Kubernetes\n\n### Quick Start\n\nCreate namespace as `gorush` as `gorush` and then your configuration map:\n\n```sh\nkubectl create -f k8s/gorush-namespace.yaml\nkubectl create -f k8s/gorush-configmap.yaml\n```\n\nCreate redis service:\n\n```sh\nkubectl create -f k8s/gorush-redis-deployment.yaml\nkubectl create -f k8s/gorush-redis-service.yaml\n```\n\nCreate gorush deployment controller provides declarative updates for Pods and ReplicaSets:\n\n```sh\nkubectl create -f k8s/gorush-deployment.yaml\n```\n\n### Create the Service Controller for AWS ELB\n\n```sh\nkubectl create -f k8s/gorush-service.yaml\n```\n\n### Ingress Controller for AWS ALB\n\nUpdate the following in `k8s/gorush-service.yaml`\n\n```diff\n-  type: LoadBalancer\n-  # type: NodePort\n+  # type: LoadBalancer\n+  type: NodePort\n```\n\nThen start the AWS ALB by the follwong command.\n\n```sh\nkubectl create -f k8s/gorush-service.yaml\nkubectl create -f k8s/gorush-aws-alb-ingress.yaml\n```\n\n### Clean up the gorush\n\n```sh\nkubectl delete -f k8s\n```\n\n## Run gorush in AWS Lambda\n\n![lambda](./screenshot/lambda.png)\n\nAWS excited to [announce Go as a supported language for AWS Lambda](https://aws.amazon.com/blogs/compute/announcing-go-support-for-aws-lambda/). You’re going to create an application that uses an [API Gateway](https://aws.amazon.com/apigateway) event source to create a simple Hello World RESTful API.\n\n### Build gorush binary\n\nDownload source code first.\n\n```sh\ngit clone https://github.com/appleboy/gorush.git\ncd gorush \u0026\u0026 make build_linux_lambda\n```\n\nyou can see the binary file in `release/linux/lambda/` folder\n\n### Deploy gorush application\n\nwe need to build a binary that will run on Linux, and ZIP it up into a deployment package.\n\n```sh\nzip deployment.zip release/linux/lambda/gorush\n```\n\nUpload the `deployment.zip` via web UI or you can try the [drone-lambda](https://github.com/appleboy/drone-lambda) as the following command. it will zip your binary file and upload to AWS Lambda automatically.\n\n```sh\n$ AWS_ACCESS_KEY_ID=YOUR_AWS_ACCESS_KEY_ID \\\n  AWS_SECRET_ACCESS_KEY=YOUR_AWS_SECRET_ACCESS_KEY \\\n  drone-lambda --region ap-southeast-1 \\\n  --function-name gorush \\\n  --source release/linux/lambda/gorush\n```\n\n### Without an AWS account\n\nOr you can deploy gorush to alternative solution like [netlify functions](https://docs.netlify.com/functions/overview/). [Netlify](https://www.netlify.com/) lets you deploy serverless Lambda functions without an AWS account, and with function management handled directly within Netlify. Please see the netlify.toml file:\n\n```toml\n[build]\ncommand = \"make build_linux_lambda\"\nfunctions = \"release/linux/lambda\"\n\n[build.environment]\nGO111MODULE = \"on\"\nGO_IMPORT_PATH = \"github.com/appleboy/gorush\"\nGO_VERSION = \"1.21.11\"\n\n[[redirects]]\nfrom = \"/*\"\nstatus = 200\nto = \"/.netlify/functions/gorush/:splat\"\n```\n\n## Stargazers over time\n\n[![Stargazers over time](https://starchart.cc/appleboy/gorush.svg)](https://starchart.cc/appleboy/gorush)\n\n## License\n\nCopyright 2019 Bo-Yi Wu [@appleboy](https://twitter.com/appleboy).\n\nLicensed under the MIT License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fappleboy%2FGorush","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fappleboy%2FGorush","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fappleboy%2FGorush/lists"}