{"id":13813035,"url":"https://github.com/RobotsAndPencils/buford","last_synced_at":"2025-05-14T22:31:38.495Z","repository":{"id":48499248,"uuid":"47787689","full_name":"RobotsAndPencils/buford","owner":"RobotsAndPencils","description":"A push notification delivery engine for the new HTTP/2 APNS service.","archived":true,"fork":false,"pushed_at":"2023-02-25T00:56:00.000Z","size":169,"stargazers_count":475,"open_issues_count":15,"forks_count":52,"subscribers_count":40,"default_branch":"master","last_synced_at":"2024-11-17T12:46:52.689Z","etag":null,"topics":[],"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/RobotsAndPencils.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}},"created_at":"2015-12-10T21:11:36.000Z","updated_at":"2024-09-09T07:27:17.000Z","dependencies_parsed_at":"2024-01-18T02:38:29.421Z","dependency_job_id":"c02cb950-c8c2-4014-8f10-24c64e04d5d1","html_url":"https://github.com/RobotsAndPencils/buford","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobotsAndPencils%2Fbuford","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobotsAndPencils%2Fbuford/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobotsAndPencils%2Fbuford/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobotsAndPencils%2Fbuford/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RobotsAndPencils","download_url":"https://codeload.github.com/RobotsAndPencils/buford/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254239650,"owners_count":22037745,"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":[],"created_at":"2024-08-04T04:01:00.560Z","updated_at":"2025-05-14T22:31:33.458Z","avatar_url":"https://github.com/RobotsAndPencils.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# Buford\n\nApple Push Notification (APN) Provider library for Go 1.6 and HTTP/2. Send remote notifications to iOS, macOS, tvOS and watchOS. Buford can also sign push packages for Safari notifications and Wallet passes.\n\nPlease see [releases](https://github.com/RobotsAndPencils/buford/releases) for updates.\n\n[![GoDoc](https://godoc.org/github.com/RobotsAndPencils/buford?status.svg)](https://godoc.org/github.com/RobotsAndPencils/buford) [![Build Status](https://travis-ci.org/RobotsAndPencils/buford.svg?branch=ci)](https://travis-ci.org/RobotsAndPencils/buford) ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) [![codecov](https://codecov.io/gh/RobotsAndPencils/buford/branch/master/graph/badge.svg)](https://codecov.io/gh/RobotsAndPencils/buford)\n\n### Documentation\n\nBuford uses Apple's new HTTP/2 Notification API that was announced at WWDC 2015 and [released on December 17, 2015](https://developer.apple.com/news/?id=12172015b).\n\n[API documentation](https://godoc.org/github.com/RobotsAndPencils/buford/) is available from GoDoc.\n\nAlso see Apple's [Local and Remote Notification Programming Guide][notification], especially the sections on the JSON [payload][] and the [Notification API][notification-api].\n\n[notification]: https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/Introduction.html\n[payload]: https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/TheNotificationPayload.html#//apple_ref/doc/uid/TP40008194-CH107-SW1\n[notification-api]: https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/APNsProviderAPI.html#//apple_ref/doc/uid/TP40008194-CH101-SW1\n\n#### Terminology\n\n**APN** Apple Push Notification\n\n**Provider** The Buford library is used to create a _provider_ of push notifications.\n\n**Service** Apple's push notification service that Buford communicates with.\n\n**Client** An `http.Client` provides an HTTP/2 client to communicate with the APN Service.\n\n**Notification** A payload, device token, and headers.\n\n**Device Token** An identifier for an application on a given device.\n\n**Payload** The JSON sent to a device.\n\n**Headers** HTTP/2 headers are used to set priority and expiration.\n\n### Installation\n\nThis library requires [Go 1.6.3](https://golang.org/dl/) or better.\n\n```\ngo get -u -d github.com/RobotsAndPencils/buford\n```\n\nBuford depends on several packages outside of the standard library, including the http2 package. Its certificate package depends on the pkcs12 and pushpackage depends on pkcs7. They can be retrieved or updated with:\n\n```\ngo get -u golang.org/x/net/http2\ngo get -u golang.org/x/crypto/pkcs12\ngo get -u github.com/aai/gocrypto/pkcs7\n```\n\nI am still looking for feedback on the API so it may change. Please copy Buford and its dependencies into a `vendor/` folder at the root of your project.\n\n### Examples\n\n```go\npackage main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\n\t\"github.com/RobotsAndPencils/buford/certificate\"\n\t\"github.com/RobotsAndPencils/buford/payload\"\n\t\"github.com/RobotsAndPencils/buford/payload/badge\"\n\t\"github.com/RobotsAndPencils/buford/push\"\n)\n\n// set these variables appropriately\nconst (\n\tfilename = \"/path/to/certificate.p12\"\n\tpassword = \"\"\n\thost = push.Development\n\tdeviceToken = \"c2732227a1d8021cfaf781d71fb2f908c61f5861079a00954a5453f1d0281433\"\n)\n\nfunc main() {\n\t// load a certificate and use it to connect to the APN service:\n\tcert, err := certificate.Load(filename, password)\n\texitOnError(err)\n\n\tclient, err := push.NewClient(cert)\n\texitOnError(err)\n\n\tservice := push.NewService(client, host)\n\n\t// construct a payload to send to the device:\n\tp := payload.APS{\n\t\tAlert: payload.Alert{Body: \"Hello HTTP/2\"},\n\t\tBadge: badge.New(42),\n\t}\n\tb, err := json.Marshal(p)\n\texitOnError(err)\n\n\t// push the notification:\n\tid, err := service.Push(deviceToken, nil, b)\n\texitOnError(err)\n\n\tfmt.Println(\"apns-id:\", id)\n}\n```\n\nSee `example/push` for the complete listing.\n\n#### Concurrent use\n\nHTTP/2 can send multiple requests over a single connection, but `service.Push` waits for a response before returning. Instead, you can wrap a `Service` in a queue to handle responses independently, allowing you to send multiple notifications at once.\n\n```go\nvar wg sync.WaitGroup\nqueue := push.NewQueue(service, numWorkers)\n\n// process responses (responses may be received in any order)\ngo func() {\n\tfor resp := range queue.Responses {\n\t\tlog.Println(resp)\n\t\t// done receiving and processing one response\n\t\twg.Done()\n\t}\n}()\n\n// send the notifications\nfor i := 0; i \u003c 100; i++ {\n\t// increment count of notifications sent and queue it\n\twg.Add(1)\n\tqueue.Push(deviceToken, nil, b)\n}\n\n// wait for all responses to be processed\nwg.Wait()\n// shutdown the channels and workers for the queue\nqueue.Close()\n```\n\nIt's important to set up a goroutine to handle responses before sending any notifications, otherwise Push will block waiting for room to return a Response.\n\nYou can configure the number of workers used to send notifications concurrently, but be aware that a larger number isn't necessarily better, as Apple limits the number of concurrent streams. From the Apple Push Notification documentation:\n\n\u003e \"The APNs server allows multiple concurrent streams for each connection. The exact number of streams is based on server load, so do not assume a specific number of streams.\"\n\nSee `example/concurrent/` for a complete listing.\n\n#### Headers\n\nYou can specify an ID, expiration, priority, and other parameters via the Headers struct.\n\n```go\nheaders := \u0026push.Headers{\n\tID:          \"922D9F1F-B82E-B337-EDC9-DB4FC8527676\",\n\tExpiration:  time.Now().Add(time.Hour),\n\tLowPriority: true,\n\tType:        push.Alert,\n}\n\nid, err := service.Push(deviceToken, headers, b)\n```\n\nIf no ID is specified APNS will generate and return a unique ID. When an expiration is specified, APNS will store and retry sending the notification until that time, otherwise APNS will not store or retry the notification. LowPriority should always be set when sending a ContentAvailable payload.\n\n#### Custom values\n\nTo add custom values to an APS payload, use the Map method as follows:\n\n```go\np := payload.APS{\n\tAlert: payload.Alert{Body: \"Message received from Bob\"},\n}\npm := p.Map()\npm[\"acme2\"] = []string{\"bang\", \"whiz\"}\n\nb, err := json.Marshal(pm)\nif err != nil {\n\tlog.Fatal(b)\n}\n\nid, err := service.Push(deviceToken, nil, b)\n```\n\n#### Error responses\n\nErrors from `service.Push` or `queue.Response` could be HTTP errors or an error response from Apple. To access the Reason and HTTP Status code, you must convert the `error` to a `push.Error` as follows:\n\n```go\nif e, ok := err.(*push.Error); ok {\n\tswitch e.Reason {\n\tcase push.ErrBadDeviceToken:\n\t\t// handle error\n\t}\n}\n```\n\n### Website Push\n\nBefore you can send push notifications through Safari and the Notification Center, you must provide a push package, which is a signed zip file containing some JSON and icons.\n\nUse `pushpackage` to write a zip to a `http.ResponseWriter` or to a file. It will create the `manifest.json` and `signature` files for you.\n\n```go\npkg := pushpackage.New(w)\npkg.EncodeJSON(\"website.json\", website)\npkg.File(\"icon.iconset/icon_128x128@2x.png\", \"static/icon_128x128@2x.png\")\n// other icons... (required)\nif err := pkg.Sign(cert, nil); err != nil {\n\tlog.Fatal(err)\n}\n```\n\nNOTE: The filenames added to the zip may contain forward slashes but not back slashes or drive letters.\n\nSee `example/website/` and the [Safari Push Notifications][safari] documentation.\n\n[safari]: https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/NotificationProgrammingGuideForWebsites/PushNotifications/PushNotifications.html#//apple_ref/doc/uid/TP40013225-CH3-SW12\n\n### Wallet (Passbook) Pass\n\nA pass is a signed zip file with a .pkpass extension and a `application/vnd.apple.pkpass` MIME type. You can use `pushpackage` to write a .pkpass that contains a `pass.json` file.\n\nSee `example/wallet/` and the [Wallet Developer Guide][wallet].\n\n[wallet]: https://developer.apple.com/library/prerelease/ios/documentation/UserExperience/Conceptual/PassKit_PG/index.html\n\n### Related Projects\n\n* [apns2](https://github.com/sideshow/apns2) Alternative HTTP/2 APN provider library (Go)\n* [go-apns-server](https://github.com/CleverTap/go-apns-server) Mock APN server (Go)\n* [gorush](https://github.com/appleboy/gorush) A push notification server (Go)\n* [Push Encryption](https://github.com/GoogleChrome/push-encryption-go) Web Push for Chrome and Firefox (Go)\n* [apns](https://github.com/timehop/apns) A Go package to interface with the Apple Push Notification Service (Timehop)\n* [apns](https://github.com/Coccodrillo/apns) Utilities for Apple Push Notification and Feedback Services\n* [micromdm](https://micromdm.io/) Mobile Device Management server (Go)\n* [Lowdown](https://github.com/alloy/lowdown) (Ruby)\n* [Apnotic](https://github.com/ostinelli/apnotic) (Ruby)\n* [Pigeon](https://github.com/codedge-llc/pigeon) (Elixir, iOS and Android)\n* [APNSwift](https://github.com/kaunteya/APNSwift) (Swift)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRobotsAndPencils%2Fbuford","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FRobotsAndPencils%2Fbuford","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRobotsAndPencils%2Fbuford/lists"}