{"id":18457404,"url":"https://github.com/kayac/gunfish","last_synced_at":"2025-04-08T05:33:26.766Z","repository":{"id":56604422,"uuid":"58601037","full_name":"kayac/Gunfish","owner":"kayac","description":null,"archived":false,"fork":false,"pushed_at":"2024-04-09T06:25:19.000Z","size":7586,"stargazers_count":38,"open_issues_count":7,"forks_count":6,"subscribers_count":132,"default_branch":"main","last_synced_at":"2025-04-06T00:25:00.570Z","etag":null,"topics":["apns","apple","go","golang","push-notifications"],"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/kayac.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":"2016-05-12T02:39:12.000Z","updated_at":"2025-02-26T07:37:15.000Z","dependencies_parsed_at":"2024-04-08T02:49:14.429Z","dependency_job_id":"6da3d36d-3dbd-45d1-8c90-112ee275fc30","html_url":"https://github.com/kayac/Gunfish","commit_stats":null,"previous_names":[],"tags_count":31,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kayac%2FGunfish","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kayac%2FGunfish/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kayac%2FGunfish/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kayac%2FGunfish/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kayac","download_url":"https://codeload.github.com/kayac/Gunfish/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247785878,"owners_count":20995641,"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":["apns","apple","go","golang","push-notifications"],"created_at":"2024-11-06T08:14:16.001Z","updated_at":"2025-04-08T05:33:25.622Z","avatar_url":"https://github.com/kayac.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/kayac/Gunfish.svg?branch=master)](https://travis-ci.org/kayac/Gunfish)\n\n# Gunfish\n\nAPNs and FCM provider server on HTTP/2.\n\n* Gunfish provides the interface as the APNs / FCM provider server.\n\n## Overview\n\n![overviews 1](https://cloud.githubusercontent.com/assets/13774847/14844813/17035232-0c95-11e6-8307-1d8340978bb7.png)\n\n[Gunfish slides](http://slides.com/takuyayoshimura-tkyshm/deck-1/fullscreen)\n\n[Gunfish slides (jp)](http://slides.com/takuyayoshimura-tkyshm/deck/fullscreen)\n\n## Install\n\n### Binary\n\nDownload the latest binary from [releases](https://github.com/kayac/Gunfish/releases)\n\n### Docker images\n\n[DockerHub](https://hub.docker.com/r/kayac/gunfish/)\n\n[GitHub Packages](https://github.com/kayac/Gunfish/pkgs/container/gunfish)\n\n### Homebrew\n\n```console\n$ brew tap kayac/tap\n$ brew install gunfish\n```\n\n## Quick Started\n\n```bash\n$ gunfish -c ./config/gunfish.toml -E production\n```\n\n### Commandline Options\n\noption              | required | description\n------------------- |----------|------------------------------------------------------------------------------------------------------------------\n-port               | Optional | Port number of Gunfish provider server. Default is `8003`.\n-environment, -E    | Optional | Default value is `production`.\n-conf, -c           | Optional | Please specify this option if you want to change `toml` config file path. (default: `/etc/gunfish/config.toml`.)\n-log-level          | Optional | Set the log level as 'warn', 'info', or 'debug'.\n-log-format         | Optional | Supports `json` or `ltsv` log formats.\n-enable-pprof       | Optional | You can set the flag of pprof debug port open.\n-output-hook-stdout | Optional | Merge stdout of hook command to gunfish's stdout.\n-output-hook-stderr | Optional | Merge stderr of hook command to gunfish's stderr.\n\n## API\n\n### POST /push/apns\n\nTo delivery remote notifications via APNS to user's devices.\n\nparam | description\n--- | ---\nArray | Array of JSON dictionary includes 'token' and 'payload' properties\n\npayload param | description\n--- | ---\ntoken | Published token from APNS to user's remote device\npayload | APNS notification payload\n\nPost JSON example:\n```json\n[\n  {\n    \"payload\": {\n      \"aps\": {\n        \"alert\": \"test notification\",\n        \"sound\": \"default\"\n      },\n      \"option1\": \"foo\",\n      \"option2\": \"bar\"\n    },\n    \"token\": \"apns device token\",\n    \"header\": {\n      \"apns-id\": \"your apns id\",\n      \"apns-topic\": \"your app bundle id\",\n      \"apns-push-type\": \"alert\"\n    }\n  }\n]\n```\n\nResponse example:\n```json\n{\"result\": \"ok\"}\n```\n\n### POST /push/fcm **Deprecated**\n\nThis API has been deleted at v0.6.0. Use `/push/fcm/v1` instead.\n\nSee also https://firebase.google.com/docs/cloud-messaging/migrate-v1 .\n\n### POST /push/fcm/v1\n\nTo delivery remote notifications via FCM v1 API to user's devices.\n\nPost body format is equal to it for FCM v1 origin server.\n\nexample:\n```json\n{\n  \"message\": {\n    \"notification\": {\n      \"title\": \"message_title\",\n      \"body\": \"message_body\",\n      \"image\": \"https://example.com/notification.png\"\n    },\n    \"data\": {\n      \"sample_key\": \"sample key\",\n      \"message\": \"sample message\"\n    },\n    \"token\": \"InstanceIDTokenForDevice\"\n  }\n}\n```\n\nResponse example:\n```json\n{\"result\": \"ok\"}\n```\n\nFCM v1 endpoint allows multiple payloads in a single request body. You can build request body simply concat multiple JSON payloads. Gunfish sends for each that payloads to FCM server. Limitation: Max count of payloads in a request body is 500.\n\n### GET /stats/app\n\n```json\n{\n  \"pid\": 57843,\n  \"debug_port\": 0,\n  \"uptime\": 384,\n  \"start_at\": 1492476864,\n  \"su_at\": 0,\n  \"period\": 309,\n  \"retry_after\": 10,\n  \"workers\": 8,\n  \"queue_size\": 0,\n  \"retry_queue_size\": 0,\n  \"workers_queue_size\": 0,\n  \"cmdq_queue_size\": 0,\n  \"retry_count\": 0,\n  \"req_count\": 0,\n  \"sent_count\": 0,\n  \"err_count\": 0,\n  \"certificate_not_after\": \"2027-04-16T00:53:53Z\",\n  \"certificate_expire_until\": 315359584\n}\n```\n\nTo get the status of APNS proveder server.\n\nstats type | description\n--- | ---\npid | PID\ndebug\\_port | pprof port number\nuptime | uptime\nworkers | number of workers\nstart\\_at | The time of started\nqueue\\_size | queue size of requests\nretry\\_queue\\_size | queue size for resending notification\nworkers\\_queue\\_size | summary of worker's queue size\ncommand\\_queue\\_size | error hook command queue size\nretry\\_count | summary of retry count\nrequest\\_count | request count to gunfish\nerr\\_count | count of recieving error response\nsent\\_count | count of sending notification\ncertificate\\_not\\_after | certificates minimum expiration date for APNs\ncertificate\\_expire\\_until | certificates minimum expiration untile (sec)\n\n### GET /stats/profile\n\nTo get the status of go application.\n\nSee detail properties that url: (https://github.com/fukata/golang-stats-api-handler).\n\n## Configuration\nThe Gunfish configuration file is a TOML file that Gunfish server uses to configure itself.\nThat configuration file should be located at `/etc/gunfish.toml`, and is required to start.\nHere is an example configuration:\n\n```toml\n[provider]\nport = 8003\nworker_num = 8\nqueue_size = 2000\nmax_request_size = 1000\nmax_connections = 2000\nerror_hook = \"echo -e 'Hello Gunfish at error hook!'\"\n\n[apns]\nkey_file = \"/path/to/server.key\"\ncert_file = \"/path/to/server.crt\"\nkid = \"kid\"\nteam_id = \"team_id\"\n\n[fcm_v1]\ngoogle_application_credentials = \"/path/to/credentials.json\"\n```\n\n### [provider] section\n\nThis section is for Gunfish server configuration.\n\nParameter        | Requirement | Description\n---------------- | ------ | --------------------------------------------------------------------------------------\nport             |optional| Listen port number.\nworker_num       |optional| Number of Gunfish owns http clients.\nqueue_size       |optional| Limit number of posted JSON from the developer application.\nmax_request_size |optional| Limit size of Posted JSON array.\nmax_connections  |optional| Max connections\nerror_hook       |optional| Error hook command. This command runs when Gunfish catches an error response.\n\n### [apns] section\n\nThis section is for APNs provider configuration.\nIf you don't need to APNs provider, you can skip this section.\n\nParameter        | Requirement | Description\n---------------- | ------ | --------------------------------------------------------------------------------------\nkey_file         |required| The key file path.\ncert_file        |optional| The cert file path.\nkid              |optional| kid for APNs provider authentication token.\nteam_id          |optional| team id for APNs provider authentication token.\n\n### [fcm_v1] section\n\nThis section is for FCM v1 provider configuration.\nIf you don't need to FCM v1 provider, you can skip this section.\n\nParameter        | Requirement | Description\n---------------- | ------ | --------------------------------------------------------------------------------------\ngoogle_application_credentials |required| The path to the Google Cloud Platform service account key file.\n\n## Error Hook\n\nError hook command can get an each error response with JSON format by STDIN.\n\nfor example JSON structure: (\u003e= v0.2.x)\n```json5\n// APNs\n{\n  \"provider\": \"apns\",\n  \"apns-id\": \"123e4567-e89b-12d3-a456-42665544000\",\n  \"status\": 400,\n  \"token\": \"9fe817acbcef8173fb134d8a80123cba243c8376af83db8caf310daab1f23003\",\n  \"reason\": \"MissingTopic\"\n}\n```\n\n```json5\n// FCM v1\n{\n  \"provider\": \"fcmv1\",\n  \"status\": 400,\n  \"token\": \"testToken\",\n  \"error\": {\n    \"status\": \"INVALID_ARGUMENT\",\n    \"message\": \"The registration token is not a valid FCM registration token\"\n  }\n}\n```\n\n## Graceful Restart\nGunfish supports graceful restarting based on `Start Server`. So, you should start on `start_server` command if you want graceful to restart.\n\n```bash\n### install start_server\n$ go get github.com/lestrrat/go-server-starter/cmd/start_server\n\n### Starts Gunfish with start_server\n$ start_server --port 38003 --pid-file gunfish.pid -- ./gunfish -c conf/gunfish.toml\n```\n\n### Test\n\n```\n$ make test\n```\n\nThe following tools are useful to send requests to gunfish for test the following.\n- gunfish-cli (send push notification to Gunfish for test)\n- apnsmock (APNs mock server)\n\n```\n$ make tools/gunfish-cli\n$ make tools/apnsmock\n```\n\n- send a request example with gunfish-cli\n```\n$ ./gunfish-cli -type apns -count 1 -json-file some.json -verbose\n$ ./gunfish-cli -type apns -count 1 -token \u003cdevice token\u003e -apns-topic \u003cyour topic\u003e -options key1=val1,key2=val2 -verbose\n```\n\n- start apnsmock server\n```\n$ ./apnsmock -cert-file ./test/server.crt -key-file ./test/server.key -verbose\n```\n\n### Benchmark\n\nGunfish repository includes Lua script for the benchmark. You can use wrk command with `err_and_success.lua` script.\n\n```\n$ make tools/apnsmock\n$ ./apnsmock -cert-file ./test/server.crt -key-file ./test/server.key -verbosea \u0026\n$ ./gunfish -c test/gunfish_test.toml -E test\n$ wrk2 -t2 -c20 -s bench/scripts/err_and_success.lua -L -R100 http://localhost:38103\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkayac%2Fgunfish","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkayac%2Fgunfish","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkayac%2Fgunfish/lists"}