apns

package module
v0.0.0-...-02b9718 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 10, 2015 License: MIT Imports: 13 Imported by: 0

README

apns

GoDoc Build Status

A Go package to interface with the Apple Push Notification Service

Features

This library implements a few features that we couldn't find in any one library elsewhere:

  • Long Lived Clients - Apple's documentation say that you should hold a persistent connection open and not create new connections for every payload
  • Use of New Protocol - Apple came out with v2 of their API with support for variable length payloads. This library uses that protocol.
  • Robust Send Guarantees - APNS has asynchronous feedback on whether a push sent. That means that if you send pushes after a bad send, those pushes will be lost forever. Our library records the last N pushes, detects errors, and is able to resend the pushes that could have been lost. More reading

API Compatibility

The apns package may undergo breaking changes. A tool like godep is recommended to vendor the current release.

Install

go get github.com/timehop/apns

Checkout the develop branch for the current work in progress.

Usage

Sending a push notification (basic)
c, _ := apns.NewClient(apns.ProductionGateway, apnsCert, apnsKey)

p := apns.NewPayload()
p.APS.Alert.Body = "I am a push notification!"
p.APS.Badge.Set(5)
p.APS.Sound = "turn_down_for_what.aiff"

m := apns.NewNotification()
m.Payload = p
m.DeviceToken = "A_DEVICE_TOKEN"
m.Priority = apns.PriorityImmediate

c.Send(m)
Sending a push notification with error handling
c, err := apns.NewClient(apns.ProductionGateway, apnsCert, apnsKey)
if err != nil {
	log.Fatal("could not create new client", err.Error()
}

go func() {
	for f := range c.FailedNotifs {
		fmt.Println("Notif", f.Notif.ID, "failed with", f.Err.Error())
	}
}()

p := apns.NewPayload()
p.APS.Alert.Body = "I am a push notification!"
p.APS.Badge.Set(5)
p.APS.Sound = "turn_down_for_what.aiff"
p.APS.ContentAvailable = 1

p.SetCustomValue("link", "zombo://dot/com")
p.SetCustomValue("game", map[string]int{"score": 234})

m := apns.NewNotification()
m.Payload = p
m.DeviceToken = "A_DEVICE_TOKEN"
m.Priority = apns.PriorityImmediate
m.Identifier = 12312, // Integer for APNS
m.ID = "user_id:timestamp", // ID not sent to Apple – to identify error notifications

c.Send(m)
Retrieving feedback
f, err := apns.NewFeedback(s.Address(), DummyCert, DummyKey)
if err != nil {
	log.Fatal("Could not create feedback", err.Error())
}

for ft := range f.Receive() {
	fmt.Println("Feedback for token:", ft.DeviceToken)
}

Note that the channel returned from Receive will close after the feedback service has no more data to send.

Running the tests

We use Ginkgo for our testing framework and Gomega for our matchers. To run the tests:

go get github.com/onsi/ginkgo/ginkgo
go get github.com/onsi/gomega
ginkgo -randomizeAllSpecs

Contributing

License

MIT License

Documentation

Overview

A Go package to interface with the Apple Push Notification Service

Features

This library implements a few features that we couldn't find in any one library elsewhere:

Long Lived Clients     - Apple's documentation say that you should hold a
                         persistent connection open and not create new
                         connections for every payload
                         See: https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/CommunicatingWIthAPS.html#//apple_ref/doc/uid/TP40008194-CH101-SW6)

Use of New Protocol    - Apple came out with v2 of their API with support for
                         variable length payloads. This library uses that
                         protocol.

Robust Send Guarantees - APNS has asynchronous feedback on whether a push
                         sent. That means that if you send pushes after a
                         bad send, those pushes will be lost forever. Our
                         library records the last N pushes, detects errors,
                         and is able to resend the pushes that could have
                         been lost.
                         See: http://redth.codes/the-problem-with-apples-push-notification-ser/

Index

Constants

View Source
const (
	ProductionGateway = "gateway.push.apple.com:2195"
	SandboxGateway    = "gateway.sandbox.push.apple.com:2195"

	ProductionFeedbackGateway = "feedback.push.apple.com:2196"
	SandboxFeedbackGateway    = "feedback.sandbox.push.apple.com:2196"
)
View Source
const (
	// Error strings based on the codes specified here:
	// https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/CommunicatingWIthAPS.html#//apple_ref/doc/uid/TP40008194-CH101-SW12
	ErrProcessing         = "Processing error"
	ErrMissingDeviceToken = "Missing device token"
	ErrMissingTopic       = "Missing topic"
	ErrMissingPayload     = "Missing payload"
	ErrInvalidTokenSize   = "Invalid token size"
	ErrInvalidTopicSize   = "Invalid topic size"
	ErrInvalidPayloadSize = "Invalid payload size"
	ErrInvalidToken       = "Invalid token"
	ErrShutdown           = "Shutdown"
	ErrUnknown            = "None (unknown)"
)
View Source
const (
	PriorityImmediate     = 10
	PriorityPowerConserve = 5
)

Variables

This section is empty.

Functions

This section is empty.

Types

type APS

type APS struct {
	Alert            Alert
	Badge            BadgeNumber
	Sound            string
	ContentAvailable int
	URLArgs          []string
	Category         string // requires iOS 8+
	AccountId        string // for email push notifications
}

func (APS) MarshalJSON

func (aps APS) MarshalJSON() ([]byte, error)

type Alert

type Alert struct {
	// Do not add fields without updating the implementation of isZero.
	Body         string   `json:"body,omitempty"`
	Title        string   `json:"title,omitempty"`
	Action       string   `json:"action,omitempty"`
	LocKey       string   `json:"loc-key,omitempty"`
	LocArgs      []string `json:"loc-args,omitempty"`
	ActionLocKey string   `json:"action-loc-key,omitempty"`
	LaunchImage  string   `json:"launch-image,omitempty"`
}

type BadgeNumber

type BadgeNumber struct {
	Number uint
	IsSet  bool
}

BadgeNumber is much a NullInt64 in database/sql except instead of using the nullable value for driver.Value encoding and decoding, this is specifically meant for JSON encoding and decoding

func (BadgeNumber) MarshalJSON

func (b BadgeNumber) MarshalJSON() ([]byte, error)

MarshalJSON will marshall the numerical value of BadgeNumber

func (*BadgeNumber) Set

func (b *BadgeNumber) Set(number uint)

Set will set the BadgeNumber value to the number passed in, assuming it's >= 0. If so, the BadgeNumber will also be marked valid

func (*BadgeNumber) UnmarshalJSON

func (b *BadgeNumber) UnmarshalJSON(data []byte) error

UnmarshalJSON will take any non-nil value and set BadgeNumber's numeric value to it. It assumes that if the unmarshaller gets here, there is a number to unmarshal and it's valid

func (*BadgeNumber) Unset

func (b *BadgeNumber) Unset()

Unset will reset the BadgeNumber to both 0 and invalid

type Client

type Client struct {
	Conn         *Conn
	FailedNotifs chan NotificationResult
	// contains filtered or unexported fields
}

func NewClient

func NewClient(gw string, cert string, key string) (Client, error)

func NewClientWithCert

func NewClientWithCert(gw string, cert tls.Certificate) Client

func NewClientWithFiles

func NewClientWithFiles(gw string, certFile string, keyFile string) (Client, error)

func (*Client) Send

func (c *Client) Send(n Notification) error

type Conn

type Conn struct {
	NetConn net.Conn
	Conf    *tls.Config
	// contains filtered or unexported fields
}

Conn is a wrapper for the actual TLS connections made to Apple

func NewConn

func NewConn(gw string, crt string, key string) (Conn, error)

NewConnWithFiles creates a new Conn from certificate and key in the specified files

func NewConnWithCert

func NewConnWithCert(gw string, cert tls.Certificate) Conn

func NewConnWithFiles

func NewConnWithFiles(gw string, certFile string, keyFile string) (Conn, error)

NewConnWithFiles creates a new Conn from certificate and key in the specified files

func (*Conn) Close

func (c *Conn) Close() error

func (*Conn) Connect

func (c *Conn) Connect() error

Connect actually creates the TLS connection

func (*Conn) Read

func (c *Conn) Read(p []byte) (int, error)

Read reads data from the connection

func (*Conn) Write

func (c *Conn) Write(p []byte) (int, error)

Write writes data from the connection

type Error

type Error struct {
	Command    uint8
	Status     uint8
	Identifier uint32
	ErrStr     string
}

func NewError

func NewError(p []byte) Error

func (*Error) Error

func (e *Error) Error() string

type Feedback

type Feedback struct {
	Conn *Conn
}

func NewFeedback

func NewFeedback(gw string, cert string, key string) (Feedback, error)

func NewFeedbackWithCert

func NewFeedbackWithCert(gw string, cert tls.Certificate) Feedback

func NewFeedbackWithFiles

func NewFeedbackWithFiles(gw string, certFile string, keyFile string) (Feedback, error)

func (Feedback) Receive

func (f Feedback) Receive() <-chan FeedbackTuple

Receive returns a read only channel for APNs feedback. The returned channel will close when there is no more data to be read.

type FeedbackTuple

type FeedbackTuple struct {
	Timestamp   time.Time
	TokenLength uint16
	DeviceToken string
}

type Notification

type Notification struct {
	ID          string
	DeviceToken string
	Identifier  uint32
	Expiration  *time.Time
	Priority    int
	Payload     *Payload
}

func NewNotification

func NewNotification() Notification

func (Notification) ToBinary

func (n Notification) ToBinary() ([]byte, error)

type NotificationResult

type NotificationResult struct {
	Notif Notification
	Err   Error
}

type Payload

type Payload struct {
	APS APS
	// MDM for mobile device management
	MDM string
	// contains filtered or unexported fields
}

func NewPayload

func NewPayload() *Payload

func (*Payload) MarshalJSON

func (p *Payload) MarshalJSON() ([]byte, error)

func (*Payload) SetCustomValue

func (p *Payload) SetCustomValue(key string, value interface{}) error

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL