Add's the Push documentation with updates to match the current state of
Push and its ecosystem. Minor updates for docusaurus formatting.

Closes #584
This commit is contained in:
Ben Bangert 2019-01-31 10:43:59 -08:00
Родитель e410f3df20
Коммит f4a5973d6b
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 340D6D716D25CCA6
12 изменённых файлов: 1273 добавлений и 3 удалений

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 103 KiB

568
docs/push/design.md Normal file
Просмотреть файл

@ -0,0 +1,568 @@
---
id: design
title: Design, API's, Error Codes
---
From [the WebPush
specification](https://tools.ietf.org/html/draft-ietf-webpush-protocol-01#section-2):
> A general model for push services includes three basic actors: a user agent, a
> push service, and an application (server).
+-------+ +--------------+ +-------------+
| UA | | Push Service | | Application |
+-------+ +--------------+ +-------------+
| | |
| Subscribe | |
|--------------------->| |
| Monitor | |
|<====================>| |
| | |
| Distribute Push Resource |
|-------------------------------------------->|
| | |
: : :
| | Push Message |
| Push Message |<---------------------|
|<---------------------| |
| | |
In WebPush, the Push Message is used to wake UA code.
Currently the Mozilla Push Service supports a proprietary protocol
using a websocket between the UA and the Push Service.
## Bridge API
Push allows for remote devices to perform some functions using an HTTP
interface. This allows remote devices on Android, iOS, and Amazon to receive
WebPush compatible messages using WebPush endpoints.
See [Push Bridge API Documentation][bridge-api].
## WebPush Proprietary Protocol
This documents the current Push Service Protocol used between the UA and
the Push Service.
The protocol uses a websocket that carries JSON messages in a mostly
request/response style format. The only exception is that after the **Hello**
response the Push Server will send any stored notifications as well as new
notifications when they arrive.
All websocket connections are secured with TLS (wss://). The Push Server
maintains a list of all previously seen UAID's and notifications for UA's that
came in while the UA was disconnected. There is no authentication for a given
UAID when reconnecting.
It is **required** that ChannelID's and UAID's be UUID's.
### Messages
All messages are encoded as JSON. All messages MUST have the following fields:
messageType string
: Defines the message type
### Handshake
After the WebSocket is established, the UserAgent begins communication by
sending a hello message. The hello message contains the UAID if the UserAgent
has one, either generated by the UserAgent for the first handshake or returned
by the server from an earlier handshake. The UserAgent also transmits the
channelIDs it knows so the server may synchronize its state and optionally the
Megaphone broadcastIDs it's subscribed to (if any).
The server MAY respect this UAID, but it is at liberty to ask the UserAgent to
change its UAID in the response.
If the UserAgent receives a new UAID, it MUST delete all existing channelIDs and
their associated versions. It MAY then wake up all registered applications
immediately or at a later date by sending them a push-register message.
A repeated hello message on an established channel may result in the server
disconnecting the client for bad behavior.
The handshake is considered complete, once the UserAgent has received a reply.
An UserAgent MUST transmit a hello message only once on its WebSocket. If the
handshake is not completed in the first try, it MUST disconnect the WebSocket
and begin a new connection.
**NOTE**: Applications may request registrations or unregistrations from the
UserAgent, before or when the handshake is in progress. The UserAgent MAY buffer
these or report errors to the application. But it MUST NOT send these requests
to the PushServer until the handshake is completed.
#### UserAgent -> PushServer
<dl>
<dt>messageType = "hello"</dt>
<dd></dd>
<dt>uaid string REQUIRED</dt>
<dd>If the UserAgent has a previously assigned UAID, it should send it. Otherwise
send an empty string.</dd>
<dt>channelIDs list of strings REQUIRED</dt>
<dd>If the UserAgent has a list of channelIDs it wants to be notified of, it must
pass these, otherwise an empty list.</dd>
<dt>use_webpush bool OPTIONAL</dt>
<dd>If the UserAgent wants the WebPush data support for notifications it
may include this field with a value of *true*. This field may appear for legacy reasons.</dd>
<dt>broadcasts object OPTIONAL</dt>
<dd>If the UserAgent wants to subscribe to specific megaphone broadcasts, it may
include this field: an object consisting of broadcastIDs mapped to the
UserAgent's current broadcast versions.</dt>
</dl>
Extra fields: The UserAgent MAY pass any extra JSON data to the PushServer. This
data may include information required to wake up the UserAgent out-of-band. The
PushServer MAY ignore this data.
**Example**
```json
{
"messageType": "hello",
"uaid": "fd52438f-1c49-41e0-a2e4-98e49833cc9c",
"broadcasts": {
"test/broadcast1": "v3",
"test/broadcast2": "v0"
}
}
```
#### PushServer -> UserAgent
<dl>
<dt>messageType = "hello"</dt>
<dd></dd>
<dt>uaid string REQUIRED</dt>
<dd>The UserAgent's provided UAID OR a new UAID.</dd>
<dt>status number REQUIRED</dt>
<dd>Used to indicate success/failure. MUST be one of:
* 200 - OK. Successful handshake.
* 503 - Service Unavailable. Database out of space or offline. Disk space
full or whatever other reason due to which the PushServer could not grant
this registration. UserAgent SHOULD avoid retrying immediately.</dd>
<dt>use_webpush bool OPTIONAL</dt>
<dd>Must match sent value</dd>
<dt>broadcasts object OPTIONAL</dt>
<dd>*Only* broadcasts the UserAgent has requested subscriptions to whose version
values differ from the UserAgent's provided values. It may be empty if the
UserAgent is up to date.</dd>
</dl>
**Example**
```json
{
"messageType": "hello",
"status": 200,
"uaid": "fd52438f-1c49-41e0-a2e4-98e49833cc9c",
"broadcasts": {
"test/broadcast2": "v1"
}
}
```
### Register
The Register message is used by the UserAgent to request that the PushServer
notify it when a channel changes. Since channelIDs are associated with only one
UAID, this effectively creates the channel, while unregister destroys the
channel.
The channelID is chosen by the UserAgent because it also acts like a nonce for
the Register message itself. Because of this PushServers MAY respond out of
order to multiple register messages or messages may be lost without compromising
correctness of the protocol.
The request is considered successful only after a response is received with a
status code of 200. On success the UserAgent MUST:
* Update its persistent storage based on the response
* Notify the application of a successful registration.
* On error, the UserAgent MUST notify the application as soon as possible.
**NOTE**: The register call is made by the UserAgent on behalf of an
application. The UserAgent SHOULD have reasonable timeouts in place so that
the application is not kept waiting for too long if the server does not
respond or the UserAgent has to retry the connection.
#### UserAgent -> PushServer
<dl>
<dt>messageType = "register"</dt>
<dd></dd>
<dt>channelID string REQUIRED</dt>
<dd>A unique identifier generated by the UserAgent, distinct from any existing
channelIDs it has registered. It is RECOMMENDED that this is a UUIDv4 token.</dd>
</dl>
**Example**
```json
{
"messageType": "register",
"channelID": "d9b74644-4f97-46aa-b8fa-9393985cd6cd"
}
```
#### PushServer -> UserAgent
<dl>
<dt>messageType = "register"</dt>
<dd></dd>
<dt>channelID string REQUIRED</dt>
<dd>This MUST be the same as the channelID sent by the UserAgent in the register
request that this message is a response to.</dd>
<dt>status number REQUIRED</dt>
<dd>Used to indicate success/failure. MUST be one of:
* 200 - OK. Success. Idempotent: If the PushServer receives a register for the
same channelID from a UserAgent which already has a registration for the
channelID, it should still respond with success.
* 409 - Conflict. The chosen ChannelID is already in use and NOT associated
with this UserAgent. UserAgent SHOULD retry with a new ChannelID as soon as
possible.
* 500 - Internal server error. Database out of space or offline. Disk space
full or whatever other reason due to which the PushServer could not grant
this registration. UserAgent SHOULD avoid retrying immediately.</dd>
<dt>pushEndpoint string REQUIRED</dt>
<dd>Should be the URL sent to the application by the UserAgent. AppServers will
contact the PushServer at this URL to update the version of the channel
identified by channelID.</dd>
</dl>
**Example**
```json
{
"messageType": "register",
"channelID": "d9b74644-4f97-46aa-b8fa-9393985cd6cd",
"status": 200,
"pushEndpoint": "http://pushserver.example.org/d9b74644"
}
```
### Unregister
Unregistration is **required** for the WebPush.
PushServers MUST support it. UserAgents SHOULD support it.
The unregister is required only between the App and the UserAgent, so that the
UserAgent stops notifying the App when the App is no longer interested in a
pushEndpoint.
The unregister is also useful to the AppServer, because it should stop sending
notifications to an endpoint the App is no longer monitoring. Even then, it is
really an optimization so that the AppServer need not have some sort of garbage
collection mechanism to clean up endpoints at intervals of time.
The PushServer MUST implement unregister, but need not rely on it. Well behaved
AppServers will stop notifying it of unregistered endpoints automatically. Well
behaved UserAgents won't notify their apps of unregistered updates either. So
the PushServer can continue to process notifications and pass them on to
UserAgents, when it has not been told about the unregistration.
When an App calls unregister(endpoint) it is RECOMMENDED that the UserAgent
follow these steps:
1. Remove its local registration first, for example from the database.
This will allow it to immediately start ignoring updates.
2. Notify the App that unregistration succeeded.
3. Fire off an unregister message to the PushServer
#### UserAgent -> PushServer
<dl>
<dt>messageType = "unregister"</dt>
<dd></dd>
<dt>channelID string REQUIRED</dt>
<dd>ChannelID that should be unregistered.</dd>
</dl>
**Example**
```json
{
"messageType": "unregister",
"channelID": "d9b74644-4f97-46aa-b8fa-9393985cd6cd"
}
```
#### PushServer -> UserAgent
<dl>
<dt>messageType = "unregister"</dt>
<dd></dd>
<dt>channelID string REQUIRED</dt>
<dd>This MUST be the same as the channelID sent by the UserAgent in the
unregister request that this message is a response to.</dd>
<dt>status number REQUIRED</dt>
<dd>Used to indicate success/failure. MUST be one of:
* 200 - OK. Success. Idempotent: If the PushServer receives a unregister for a
non-existent channelID it should respond with success. If the channelID is
associated with a DIFFERENT UAID, it MUST NOT delete the channelID, but
still MUST respond with success to this UserAgent.
* 500 - Internal server error. Database offline or whatever other reason due
to which the PushServer could not grant this unregistration. UserAgent
SHOULD avoid retrying immediately.</dd>
</dl>
**Example**
```json
{
"messageType": "unregister",
"channelID": "d9b74644-4f97-46aa-b8fa-9393985cd6cd",
"status": 200
}
```
### Ping
The connection to the Push Server may be lost due to network issues. When the
UserAgent detects loss of network, it should reconnect. There are situations in
which the TCP connection dies without either end discovering it immediately. The
UserAgent MAY send a ping approximately every 30 minutes and expect a reply
from the server in a reasonable time (The Mozilla UserAgent uses 10 seconds). If
no data is received, the connection should be presumed closed and a new
connection started.
A UserAgent MUST NOT send a Ping more frequently than once a minute or its
connection MAY be dropped.
The UserAgent should consider normal communications as an indication that the
socket is working properly. It SHOULD send the ping packet only if no activity
has occurred in the past 30 minutes.
**Note**: This section is included for relevant historical purposes as the
current implementation sends WebSocket Ping frames every 5 minutes which is
sufficient to keep the connection alive. As such, client-sent Ping's are no
longer needed.
#### UserAgent -> PushServer
The 2-character string {} is sent. This is a valid JSON object that requires no
alternative processing on the server, while keeping transmission size small.
#### PushServer -> UserAgent
The PushServer may reply with any data. The UserAgent is only concerned about
the state of the connection. The PushServer may deliver pending notifications or
other information. If there is no pending information to be sent, it is
RECOMMENDED that the PushServer also reply with the string {}.
### Notification
#### AppServer -> PushServer
The AppServer MUST make a HTTP PUT request to the Endpoint received from the
App, or a HTTP POST if using the WebPush extension.
If no request body is present, the server MAY presume the version to be the
current server UTC.
If the request body is present, the request MUST contain the string "version=N"
and the Content-Type MUST be application/x-www-form-urlencoded.
#### PushServer -> AppServer
The HTTP response status code indicates if the request was successful.
* 200 - OK. The PushServer will attempt to deliver a notification to the
associated UserAgent.
* 500 - Something went wrong with the server. Rare, but the AppServer should try
again.
The HTTP response body SHOULD be empty.
#### PushServer -> UserAgent
Notifications are acknowledged by the UserAgent. PushServers should retry unacknowledged notifications every 60 seconds. If the version of an unacknowledged notification is updated, the PushServer MAY queue up a new notification for this channelID and the new version, and remove the old notification from the pending queue.
<dl>
<dt>messageType = "notification"</dt>
<dd></dd>
</dl>
The following attributes are present
in each notification. A
notification message is sent for every stored notification individually, as well
as new notifications.
<dl>
<dt>channelID string REQUIRED</dt>
<dd>ChannelID of the notification</dd>
<dt>version string REQUIRED</dt>
<dd>Version of the notification sent</dd>
<dt>headers map OPTIONAL</dt>
<dd>Encryption headers sent along with the data. Present only if data was sent.</dd>
<dt>data string OPTIONAL</dt>
<dd>Data payload, if included. This string is Base64 URL-encoded.</dd>
</dl>
**Example**
```json
{
"messageType": "notification",
"channelID": "431b4391-c78f-429a-a134-f890b5adc0bb",
"version": "a7695fa0-9623-4890-9c08-cce0231e4b36:d9b74644-4f97-46aa-b8fa-9393985cd6cd"
}
```
#### UserAgent -> PushServer
It is RECOMMENDED that the UserAgent try to batch all pending acknowledgements
into fewer messages if bandwidth is a concern. The ack MUST be sent as soon as
the message has been processed, otherwise the
Push Server MAY cease sending notifications to avoid holding excessive client
state.
<dl>
<dt>messageType = "ack"</dt>
<dd></dd>
<dt>updates list</dt>
<dd>The list contains one or more {"channelID": channelID, "version": N} pairs.</dd>
</dl>
**Example**
```json
{
"messageType": "ack",
"updates": [{ "channelID": "431b4391-c78f-429a-a134-f890b5adc0bb", "version": 23 }, { "channelID": "a7695fa0-9623-4890-9c08-cce0231e4b36", "version": 42 } ]
}
```
### Broadcast
When a UserAgent's subscribed broadcasts are updated, PushServers send
broadcast messages with no expected reply.
#### PushServer -> UserAgent
<dl>
<dt>messageType = "broadcast"</dt>
<dd></dd>
<dt>broadcasts object OPTIONAL</dt>
<dd>*Only* broadcasts the UserAgent has requested subscriptions to whose new
version values differ from the UserAgent's provided values.</dd>
</dl>
**Example**
```json
{
"messageType": "broadcast",
"broadcasts": {
"test/broadcast1": "v4"
}
}
```
### Broadcast Subscribe
UserAgents subscribe to broadcasts during the hello handshake but may also
subscribe to additional broadcasts afterwards. There is no expected reply to
this message.
#### UserAgent -> PushServer
<dl>
<dt>messageType = "broadcast_subscribe"</dt>
<dd></dd>
<dt>broadcasts object REQUIRED</dt>
<dd>New broadcasts the UserAgent is requesting subscriptions to and their current
broadcast versions.</dd>
</dl>
**Example**
```json
{
"messageType": "broadcast_subscribe",
"broadcasts": {
"test/new-broadcast22": "v8"
}
}
```
## Error Codes
The Mozilla Push Service may return a variety of error codes depending on what
went wrong in the request.
Autopush uses error codes based on [HTTP response codes](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html).
An error response will contain a JSON body including an additional error information.
Unless otherwise specified, all calls return one the following error statuses:
- 20x - **Success** - The message was accepted for transmission to the client. Please note that the message may still be rejected by the User Agent if there is an error with the message's encryption.
- 301 - **Moved + `Location:`** if `{client_token}` is invalid (Bridge API Only) - Bridged services (ones that run over third party services like GCM and APNS), may require a new URL be used. Please stop using the old URL immediately and instead use the new URL provided.
- 400 - **Bad Parameters** -- One or more of the parameters specified is invalid. See the following sub-errors indicated by `errno`
- errno 101 - Missing necessary crypto keys - One or more required crypto key elements are missing from this transaction. Refer to the [appropriate specification](https://datatracker.ietf.org/doc/draft-ietf-httpbis-encryption-encoding/) for the requested content-type.
- errno 108 - Router type is invalid - The URL contains an invalid router type, which may be from URL corruption or an unsupported bridge. Refer to [bridge API][bridge-api].
- errno 110 - Invalid crypto keys specified - One or more of the crytpo key elements are invalid. Refer to the [appropriate specification](https://datatracker.ietf.org/doc/draft-ietf-httpbis-encryption-encoding/) for the requested content-type.
- errno 111 - Missing Required Header - A required crypto element header is missing. Refer to the [appropriate specification](https://datatracker.ietf.org/doc/draft-ietf-httpbis-encryption-encoding/) for the requested content-type.
- Missing TTL Header - Include the Time To Live header ([IETF WebPush protocol §6.2](https://tools.ietf.org/html/draft-ietf-webpush-protocol#section-6.2))
- Missing Crypto Headers - Include the appropriate encryption headers ([WebPush Encryption §3.2](https://webpush-wg.github.io/webpush-encryption/#rfc.section.3.2) and [WebPush VAPID §4](https://tools.ietf.org/html/draft-ietf-webpush-vapid-02#section-4))
- errno 112 - Invalid TTL header value - The Time To Live "TTL" header contains an invalid or unreadable value. Please change to a number of seconds that this message should live, between 0 (message should be dropped immediately if user is unavailable) and 2592000 (hold for delivery within the next approximately 30 days).
- errno 113 - Invalid Topic header value - The Topic header contains an invalid or unreadable value. Please use only ASCII alphanumeric values [A-Za-z0-9] and a maximum length of 32 bytes..
- 401 - **Bad Authorization** - `Authorization` header is invalid or missing. See the [VAPID specification](https://datatracker.ietf.org/doc/draft-ietf-webpush-vapid/).
- errno 109 - Invalid authentication
- 404 - **Endpoint Not Found** - The URL specified is invalid and should not be used again.
- errno 102 - Invalid URL endpoint
- 410 - **Endpoint Not Valid** - The URL specified is no longer valid and should no longer be used. A User has become permanently unavailable at this URL.
- errno 103 - Expired URL endpoint
- errno 105 - Endpoint became unavailable during request
- errno 106 - Invalid subscription
- 413 - **Payload too large** - The body of the message to send is too large. The max data that can be sent is 4028 characters. Please reduce the size of the message.
- errno 104 - Data payload too large
- 500 - **Unknown server error** - An internal error occurred within the Push Server.
- errno 999 - Unknown error
- 502 - **Bad Gateway** - The Push Service received an invalid response from an upstream Bridge service.
- errno 900 - Internal Bridge misconfiguration
- errno 901 - Invalid authentication
- errno 902 - An error occurred while establishing a connection
- errno 903 - The request timed out
- 503 - **Server temporarily unavailable.** - The Push Service is currently unavailable. See the error number "errno" value to see if retries are available.
- errno 201 - Use exponential back-off for retries
- errno 202 - Immediate retry ok
[pushapi]: https://developer.mozilla.org/en-US/docs/Web/API/Simple_Push_API
[bridge-api]: ../../api/push_bridge.html

162
docs/push/development.md Normal file
Просмотреть файл

@ -0,0 +1,162 @@
---
id: development
title: Development Process
---
We develop and deploy on a 2 week schedule. A new release is
tagged and cut a week before deploy, QA files a deployment ticket filed then verifies the release. On occasion a release
will get a full suite of load-tests as well.
Some of the ancillary Push projects have no set release schedule and are
released as needed.
## Code Development
### Architecture Discussion & Documentation
Architecture changes and proposals are discussed on the
[Push-Service mail list][PSML] using the "Design: " subject prefix. When
a topic has been idle at least a week with no further replies it is
considered at the next standup. If the team approves the change, the
appropriate Github issues are created, and an email sent on the topic
to the list pointing to the outcome and issue created. Otherwise an
email is sent on the topic indicating it will not be implemented.
### Milestones & Waffleboard
Issues are created in their appropriate repositories. Ownership and triage of
issues is done via a single Waffleboard that aggregates issue tracking across
all Push-related repositories.
* [Push Waffleboard](https://waffle.io/mozilla-services/push-service)
### Labels
Issues are assigned a priority based on the release the issue is targeted at.
* P1 - Next release
* P2 - Release after next
* P3 - No immediate release targeted
P2 issues are promoted to P1 after a release, while P3's are triaged to
determine if they should become P2's at the first standup after a release.
The priority tags are applied as Github labels. Other labels will also be
applied to categorize the issue appropriately.
Issues being worked on are moved to the **In Progress** column and assigned to
the person working on the issue.
### Versions
Push repositories use a {major}.{minor}.{patch} version scheme, with
patch tags released to address emergency issues in a deployed release.
Major versions are generally large re-writes and assumed to possibly
break backwards compatibility.
Releases are tagged under `release/{major}.{minor}` branches.
### Github Workflow
(Based heavily on [Servo's Workflow](https://github.com/servo/servo/wiki/Github-workflow))
You will need to [fork](https://help.github.com/articles/fork-a-repo/) the
appropriate repository in order to be able to publish your changes. Push Team
members may create a branch in the repo which should reference the issue being
worked on. In these instructions `<mozilla-services>` is the name of the remote
pointing to the remote at the appropriate repo and `<fork>` is the remote
pointing at your fork of the repository.
All commits should be [signed](https://help.github.com/articles/signing-commits-using-gpg/).
1. Fetch the latest code and create a local branch:
`$ git fetch <mozilla-services>`
`$ git checkout -b <local_branch> <mozilla-services>/master`
Name the branch appropriately for the fix/feat/docs commit you're working on.
Ideally a Pull Request will have a single commit to address the issue.
<br /><br />
2. Code/hack/do stuff then commit:
`$ git commit -S -a `
Make sure to phrase your commit message appropriately per the Contributing
documentation for the repository. Most Push-related repositories use an
[Angular-based commit style][contrib].
Before committing and pushing code, remember to run the appropriate tests
locally to avoid having our CI systems reject it. PR's that don't pass the
automated tests won't be reviewed until they pass.
<br /><br />
3. Push local branch to your cloned repository:
`$ git push --set-upstream <fork> <local_branch> `
(`git push -u <fork> <local_branch>[:remote_name]` should work if you want to
publish your changes to a branch with a different name than `[local_branch]`.)
<br /><br />
4. Create a [PR in GitHub](https://help.github.com/articles/using-pull-requests/).
If you know who should code review this PR, you can write `r? @username`
in the text of the PR and they will automatically be assigned to it.
If not, don't worry: a reviewer will be randomly selected and notified.
<br /><br />
5. Wait for reviewers' feedback - if something needs to be fixed, either amend
the existing commits if the changes are minor, or fix it in a new commit on
the same branch, optionally using `--fixup`:
`$ git commit -S --fixup=<sha1_of_relevant_commit_on_branch>`
Alternatively, add the following to your `.gitconfig` and simply use `git fixup`:
```
[alias]
fixup = !sh -c 'git commit -m \"fixup! $(git log -1 --format='\\''%s'\\'' $@ | sed \"s/fixup\\! //\")\"' -
ri = rebase --interactive --autosquash
```
<br /><br />
6. Use `git push` to update the Pull Request. Repeat steps 5-6 until the review
is accepted. If existing commits were amended, a force push will be necessary
(see step 8).
<br /><br />
7. When you know there is a substantive change on master that affects your
patch, update `<mozilla>` and rebase your local branch to make sure your
patch still applies correctly:
`$ git fetch <mozilla-services>`
`$ git rebase <mozilla-services>/master`
You may have to fix merge conflicts on the way.
<br /><br />
8. Force-push your changes:
`$ git push -f <fork> <local_branch>`
<br /><br />
9. Once your patch is accepted and based on a recent master, squash the commits
together for a cleaner history (if requested):
`$ git rebase -i --autosquash <mozilla-services>/master`
<br /><br />
10. Force push the squashed commits to github (see step 8).
<br /><br />
11. When the reviewer thinks the code is ready, they will leave a comment
saying "r+", meaning "review granted." Then our bot will
automatically test and merge your PR. Congratulations!
[MPSM]: https://github.com/mozilla-services/push-service/milestones
[contrib]: https://github.com/mozilla-services/autopush/blob/master/CONTRIBUTING.md
[PSML]: https://groups.google.com/a/mozilla.com/forum/#!forum/push-service

33
docs/push/history.md Normal file
Просмотреть файл

@ -0,0 +1,33 @@
---
id: history
title: History
---
The Push Service was originally developed in Go, utilizing a websocket
connection from [Firefox OS][fxos] to the Push service. It was
deployed in 2013
with the legacy [SimplePush DOM
API](https://developer.mozilla.org/en-US/docs/Web/API/Simple_Push_API) that runs
under [Firefox OS][fxos]. This API only supported incrementing version numbers,
to wake a device so that it could check with an Application Server to determine
what to display.
In 2015 the Push Service was rewritten in Python, and added preliminary
[WebPush][wp] support for carrying data in push messages. The underlying
protocol used between [Firefox][ffx] and the Push Service is an extended
[SimplePush Protocol](design.md#simplepush-protocol) utilizing a websocket protocol that will eventually be
deprecated in favor of a specification compliant [WebPush][wp] HTTP 2.0
protocol.
With the release of [RFC 8030](https://tools.ietf.org/html/rfc8030), Simplepush support was deprecated.
In 2017, a prototype of the Push connection node was written in Rust with bindings
to a Python extraction of the logic. By early 2018 the connection node logic was
ported entirely to Rust and a [Rust connection node][autopush-rs] was put into production
service. The Rust port drastically lowered CPU usage, and reduced the per-client
memory consumption to slightly less than 10Kb.
[autopush-rs]: https://github.com/mozilla-services/autopush-rs
[wp]: https://webpush-wg.github.io/webpush-protocol/
[fxos]: https://www.mozilla.org/en-US/firefox/os/
[ffx]: https://www.mozilla.org/en-US/firefox/

140
docs/push/welcome.md Normal file
Просмотреть файл

@ -0,0 +1,140 @@
---
title: Push
sidebar_label: Welcome
---
Mozilla Push Service is the server-side project supporting Push Notifications in
[Firefox][ffx]. The current server is
[autopush](https://github.com/mozilla-services/autopush). You can
learn how to use the web based API to push messages to web
applications running Push by reading the [autopush HTTP API
document](https://autopush.readthedocs.io/en/latest/http.html).
## Service Architecture
![Push Architecture Diagram](assets/push_architecture.svg)
## Code
The current production deployment of Push is a Python-based websocket server
named **autopush**, developed on Github. The Push Service team has several
repositories for development of the Push Server, and supporting tooling.
- [autopush](https://github.com/mozilla-services/autopush) - Push connection
and endpoint server (Python, only autoendpoint in use)
- [autopush-rs](https://github.com/mozilla-services/autopush-rs) - Push connection
server (Rust, connection-node only, production deployed)
- [megaphone](https://github.com/mozilla-services/megaphone) - Global broadcast
server
- [ap-loadtester](https://github.com/mozilla-services/ap-loadtester/) - Load and
end-to-end Push testing application
See the [architecture](#architecture) image for reference on what components
each of these code pieces correspond to.
## People and Places
* [Ben Bangert](https://github.com/bbangert) - Engineering (San Francisco, UTC-8)
* [JR Conlin](https://github.com/jrconlin) - Engineering (Mountain View, UTC-8)
* [Philip Jenvey](https://github.com/pjenvey) - Engineering (San Francisco, UTC-8)
* [Chris Hartjes](https://github.com/chartjes) - QA (Ontario, UTC-5)
* [Jeremy Orem](https://github.com/oremj) - Operations (Portland, UTC-8)
* [Janet Dragojevic](https://github.com/jdragojevic) - Application Services Manager (New York, UTC-5)
### Product
* Alex Davis (:ADavis) - Product Manager (Vancouver, UTC-8)
* Julie McCracken (:Julie) - Engineering Program Manager (San Diego, UTC-8)
### Mail Lists and IRC
Additional ways to get in contact with the team:
* The [Push-Service mail list (public)](https://groups.google.com/a/mozilla.com/forum/#!forum/push-service)
* The [Push mailing list (Mozilla internal)](http://groups.google.com/a/mozilla.com/group/push/)
* The `#push` channel on [Mozilla IRC](https://wiki.mozilla.org/IRC)
## Sending Push Messages
If you are interested in using WebPush for your application, there are
a number of resources that should help.
If you are adding Push to your browser or progressive enhancement
application, see [Using the Push
API](https://developer.mozilla.org/en-US/docs/Web/API/Push_API/Using_the_Push_API)
on MDN.
If you are creating a service that sends Push messages to remote
browser applications, see [HTTP Endpoints for
Notifications](https://autopush.readthedocs.io/en/latest/http.html).
## Terminology
The Push Service uses a range of terminology that can be difficult at first to
keep straight. This is a list of commonly used terms and phrases with their
meaning in the context of Push.
For an overview of how these terms fit together to deliver a push message to a
user-agent, [see the Firefox Push Notification high-level
diagram](https://wiki.mozilla.org/Firefox/Push_Notifications#Technologies). This
page also includes descriptions of related technologies that help to deliver a
cohesive Push Notification experience.
Where applicable, these match the [Webpush Spec Terminology][wpst].
<dl>
<dt>Application</dt>
<dd>Both the sender and ultimate consumer of push messages. Many applications
have components that are run on a user agent and other components that run on
servers.</dd>
<dt>Application Server</dt>
<dd>The component of an application that runs on a server and requests the
delivery of a push message.</dd>
<dt>Channel ID</dt>
<dd>Legacy terminology for a Push Message Subscription utilized by WebPush and
the websocket client protocol.</dd>
<dt>Endpoint</dt>
<dd>A REST-ful HTTP URL uniquely associated with a Push Message Subscription. This
is referred to as a "push resource" in the [WebPush specification][wp].</dd>
<dt>Push Message Subscription</dt>
<dd>A message delivery context that is established between the user agent and the
push service and shared with the application server. All push messages are
associated with a push message subscription.</dd>
<dt>Push Message</dt>
<dd>A message sent from an application server to a user agent via a push service.</dd>
<dt>Push Message Receipt</dt>
<dd>A message delivery confirmation sent from the push service to the application
server.</dd>
<dt>Push Service</dt>
<dd>A service that delivers push messages to user agents.</dd>
<dt>SimplePush</dt>
<dd>Deprecated Firefox OS specific Push system that carries no data, only an incrementing
version number. The Mozilla Push Service no longer continues to support this legacy API.</dd>
<dt>UAID</dt>
<dd>A globally unique UserAgent ID. Used by the Push Service to associate clients
utilizing the websocket protocol with their associated channel ID's. This
string is always a UUID.</dd>
<dt>User Agent</dt>
<dd>A device and software that is the recipient of push messages.</dd>
<dt>WebPush</dt>
<dd>IETF specification regarding Push Messages, the protocol for their delivery
(HTTP 2.0) to User Agents, and how the Application Server interacts with the
Push Service. [See the complete Webpush Specification][wp].</dd>
</dl>
## Alternate Implementation
Other groups have implemented Push Services implementing WebPush.
- [Aerogear Unified Push Server](
https://github.com/aerogear/aerogear-unifiedpush-server)
## Community Contributions
[Matthias Wessendorf](https://gist.github.com/matzew) has provided [a quick
hack](https://gist.github.com/matzew/cbda360d72eaaef75971) showing how to call
the server by hand.
[wpst]: https://tools.ietf.org/html/draft-ietf-webpush-protocol-01#section-1.1
[wp]: https://webpush-wg.github.io/webpush-protocol/
[ffx]: https://www.mozilla.org/en-US/firefox/

Просмотреть файл

@ -65,6 +65,22 @@
"title": "Docs",
"sidebar_label": "Docs"
},
"push/design": {
"title": "Design, API's, Error Codes"
},
"push/development": {
"title": "Development Process"
},
"push/history": {
"title": "History"
},
"push/welcome": {
"title": "Push",
"sidebar_label": "Welcome"
},
"release-process": {
"title": "release-process"
},
"sync/canned-bug-responses": {
"title": "Canned Bug Responses"
},
@ -100,6 +116,7 @@
"Accounts": "Accounts",
"Sync": "Sync",
"Applications": "Applications",
"Push": "Push",
"Firefox Accounts": "Firefox Accounts",
"Mobile SDKs": "Mobile SDKs",
"Other Features": "Other Features",

Просмотреть файл

@ -0,0 +1,2 @@
<redoc spec-url='push_bridge.yml'></redoc>
<script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"> </script>

Просмотреть файл

@ -114,7 +114,7 @@ const Features = props => (
{
imageAlign: 'top',
title: 'Push',
imageLink: `https://mozilla-push-service.readthedocs.io/en/latest/`,
imageLink: `${siteConfig.baseUrl}docs/push/welcome.html`,
image: imgUrl('notification-16.svg'),
},
]}

Просмотреть файл

@ -2,7 +2,8 @@
"docs": {
"Accounts": ["accounts/welcome"],
"Sync": ["sync/welcome"],
"Applications": ["applications/welcome"]
"Applications": ["applications/welcome"],
"Push": ["push/welcome"]
},
"accounts": {
"Firefox Accounts": [
@ -48,5 +49,13 @@
"sync/canned-bug-responses",
"sync/redash"
]
},
"push": {
"Push": [
"push/welcome",
"push/development",
"push/design",
"push/history"
]
}
}

Просмотреть файл

@ -53,7 +53,8 @@ const siteConfig = {
// You may provide arbitrary config keys to be used as needed by your template.
repoUrl: 'https://github.com/mozilla/application-services',
/* On page navigation for the current documentation page */
// onPageNav: 'separate',
onPageNav: 'separate',
wrapPagesHTML: true,
};
module.exports = siteConfig;

Просмотреть файл

@ -0,0 +1,324 @@
swagger: "2.0"
info:
title: Push Third-Party Bridge API
description: |
Push allows for remote devices to perform some functions using an HTTP
interface. This is mostly used by devices that are bridging via an
external protocol like
[GCM](https://developers.google.com/cloud-messaging/), [FCM](https://firebase.google.com/docs/cloud-messaging/>) or
[APNs](https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Introduction.html#//apple_ref/doc/uid/TP40008196-CH1-SW1). All message bodies must be UTF-8 encoded.
\
\
API methods requiring Authorization must provide the Authorization
header containing the registration secret. The registration secret is
returned as "secret" in the registration response.
\
\
Error codes and `errno` results can be [found in the Error Codes section](../docs/push/design.html#error-codes).
\
\
**NOTE**: This is not intended to be used by app developers. Please see the
[Web Push API on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Push_API)
for how to use WebPush.
version: "1.0"
host: updates.push.services.mozilla.com
basePath: /v1/
schemes:
- https
securityDefinitions:
AuthApiKey:
type: apiKey
in: header
name: Authorization
description: |
Registration "secret" returned in the registration response.
An example of the Authorization header would be:
```Authorization: Bearer 00secret00```
parameters:
typeParam:
in: path
name: type
description: |
Allowed bridges are `gcm` (Google Cloud Messaging), `fcm` (Firebase Cloud
Messaging), `adm` (Amazon Device Messaging) and `apns` (Apple Push Notification system).
type: string
required: true
enum:
- gcm
- fcm
- adm
- apns
appIdParam:
in: path
name: app_id
type: string
description: |
Each bridge may require a unique token that addresses the remote application.
For GCM/FCM, this is the `SenderID` (or 'project number') and is pre-negotiated
outside of the push service. You can find this number using the
[Google developer console](https://console.developers.google.com/iam-admin/settings/project>).
For APNS, this value is the "platform" or "channel" of development (e.g.
"firefox", "beta", "gecko", etc.).
For our examples, we will use a client token of "33clienttoken33".
required: true
uaidParam:
in: path
name: uaid
type: string
required: true
description: |
The Push User Agent Registration ID
Push assigns each remote recipient a unique identifier. {UAID}s are UUIDs in
lower case, undashed format. (e.g. '01234567abcdabcdabcd01234567abcd') This
value is assigned during **Registration**.
chidParam:
in: path
name: chid
type: string
required: true
description: |
The Channel Subscription ID
Push assigns a unique identifier for each subscription for a given UAID.
Like UAIDs, CHIDs are UUIDs, but in lower case, dashed format( e.g.
'01234567-abcd-abcd-abcd-0123456789ab'). The User Agent usually creates this
value and passes it as part of the **Channel Subscription**. If no value is
supplied, the server will create and return one.
paths:
/{type}/{app_id}/registration:
post:
summary: Register for WebPush delivery.
tags:
- Registration
description: |
Request a new UAID registration, Channel ID, and set a bridge
type and 3rd party bridge instance ID token for this client.
\
\
**NOTE**: This call is designed for devices to register endpoints to be
used by bridge protocols. Please see [Web Push API](https://developer.mozilla.org/en-US/docs/Web/API/Push_API) for how to use
Web Push in your application.
consumes:
- application/json
produces:
- application/json
parameters:
- $ref: '#/parameters/typeParam'
- $ref: '#/parameters/appIdParam'
- in: body
name: root
schema:
$ref: '#/definitions/Token'
responses:
200:
description: OK
schema:
type: object
properties:
uaid:
$ref: "#/definitions/UAID"
channelID:
$ref: "#/definitions/CHID"
secret:
type: string
description:
Secret to use for authenticating for other API calls.
example: 00secret00
endpoint:
$ref: '#/definitions/WebPushEndpoint'
/{type}/{app_id}/registration/{uaid}:
put:
summary: Update bridge token
tags:
- Registration
description: |
Update the current bridge token value. Note, this is a **PUT** call, since
we are updating existing information.
consumes:
- application/json
produces:
- application/json
security:
- AuthApiKey: []
parameters:
- $ref: '#/parameters/typeParam'
- $ref: '#/parameters/appIdParam'
- $ref: '#/parameters/uaidParam'
- in: body
name: root
schema:
$ref: '#/definitions/Token'
responses:
200:
description: OK
schema:
type: object
delete:
summary: Delete the UAID and all subscriptions
tags:
- Registration
description: |
Indicate that the UAID, and by extension all associated subscriptions,
is no longer valid.
consumes:
- application/json
produces:
- application/json
security:
- AuthApiKey: []
parameters:
- $ref: '#/parameters/typeParam'
- $ref: '#/parameters/appIdParam'
- $ref: '#/parameters/uaidParam'
- in: body
name: root
schema:
type: object
responses:
200:
description: OK
schema:
type: object
/{type}/{app_id}/registration/{uaid}/:
get:
summary: Get all subscriptions
tags:
- Subscriptions
description: |
Fetch the known ChannelIDs for a given bridged endpoint. This is useful to check link status.
If no channelIDs are present for a given UAID, an empty set of channelIDs will be returned.
consumes:
- application/json
produces:
- application/json
security:
- AuthApiKey: []
parameters:
- $ref: '#/parameters/typeParam'
- $ref: '#/parameters/appIdParam'
- $ref: '#/parameters/uaidParam'
- in: body
name: root
schema:
type: object
responses:
200:
description: OK
schema:
type: object
properties:
uaid:
$ref: '#/definitions/UAID'
channelIDS:
type: array
items:
type: string
description: Channel Subscription ID's
example:
- 01234567-0000-1111-2222-0123456789ab
- 76543210-0000-1111-2222-0123456789ab
/{type}/{app_id}/registration/{uaid}/subscription:
post:
summary: Acquire a new ChannelID for a given UAID.
tags:
- Subscriptions
consumes:
- application/json
produces:
- application/json
security:
- AuthApiKey: []
parameters:
- $ref: '#/parameters/typeParam'
- $ref: '#/parameters/appIdParam'
- $ref: '#/parameters/uaidParam'
- in: body
name: root
schema:
type: object
responses:
200:
description: OK
schema:
type: object
properties:
channelID:
$ref: '#/definitions/CHID'
endpoint:
$ref: '#/definitions/WebPushEndpoint'
/{type}/{app_id}/registration/{uaid}/subscription/{chid}:
delete:
summary: Subscription delete.
description: Remove a given ChannelID subscription from a UAID.
tags:
- Subscriptions
consumes:
- application/json
produces:
- application/json
security:
- AuthApiKey: []
parameters:
- $ref: '#/parameters/typeParam'
- $ref: '#/parameters/appIdParam'
- $ref: '#/parameters/uaidParam'
- $ref: '#/parameters/chidParam'
responses:
200:
description: OK
schema:
type: object
definitions:
UAID:
type: string
description: |
The Push User Agent Registration ID
Push assigns each remote recipient a unique identifier. {UAID}s are UUIDs in
lower case, undashed format. (e.g. '01234567abcdabcdabcd01234567abcd') This
value is assigned during **Registration**.
example: 01234567-0000-1111-2222-0123456789ab
CHID:
type: string
description: |
The Channel Subscription ID
Push assigns a unique identifier for each subscription for a given UAID.
Like UAIDs, CHIDs are UUIDs, but in lower case, dashed format( e.g.
'01234567-abcd-abcd-abcd-0123456789ab'). The User Agent usually creates this
value and passes it as part of the **Channel Subscription**. If no value is
supplied, the server will create and return one.
example: 00000000-0000-1111-2222-0123456789ab
Token:
type: object
required:
- token
properties:
token:
type: string
description: |
Each bridge requires a unique token that addresses the
application on a given user's device. This is the
"[Registration Token](https://firebase.google.com/docs/cloud-messaging/android/client#sample-register)" for
GCM/FCM or "[Device Token](https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/IPhoneOSClientImp.html#//apple_ref/doc/uid/TP40008194-CH103-SW2)"
for APNS.
This is usually the product of the application registering the {token} with the native bridge via the user
agent.
example:
token: 11-token-11
WebPushEndpoint:
type: string
description: WebPush compatible endpoint.
example: https://updates-push.services.mozaws.net/push/...

Просмотреть файл

@ -129,3 +129,15 @@ footer.nav-footer a {
footer .copyright {
padding: 40px 0 10px 0;
}
dl dt {
display: inline-block;
margin: 6px 0;
background: rgba(66, 76, 85, 0.1);
border-top: solid 3px rgb(66, 76, 85);
padding: 6px;
}
dl dd {
margin: 0 0 12px 24px;
}