aboutsummaryrefslogtreecommitdiff
path: root/docs/sym_upload_v2_protocol.md
blob: d56a4c836deedf8903e4b0dcf63cef42b74d5601 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# Introduction

The `sym_upload` tool is able to operate in `sym-upload-v2` protocol mode, in
addition to the legacy protocol (which will be referred to as `sym-upload-v1`
for the rest of this document). For now `sym-upload-v2` is HTTP/REST-based but
it could be extended to operate over gRPC instead, in the future.

# Table of Contents
* [Why](#why)
* [How](#how)
   * [Uploading](#uploading)
     * [Uploading with `sym_upload`](#uploading-with-sym_upload)
     * [Uploading with curl](#uploading-with-curl)
     * [Serving the `sym-upload-v2` protocol](#serving-the-sym-upload-v2-protocol)
       * [Authenticate using `key`](#authenticate-using-key)
       * [Symbol `checkStatus`](#symbol-checkstatus)
       * [Upload `create`](#upload-create)
       * [Uploading the symbol file](#uploading-the-symbol-file)
       * [Upload complete](#upload-complete)


# Why

Using `sym_upload` in `sym-upload-v2` protocol mode has the following features
beyond `sym-upload-v1`:
  * Authentication via `key` (arbitrary secret).
  * Symbol identifier (product of `debug_file` and `debug_id`, as recorded in
output from `dump_syms`) can be checked against existing symbol information on
server. If it's present, then the upload is skipped entirely.

# How

## Uploading

### Uploading with `sym_upload`

Uploading in `sym-upload-v2` protocol mode is easy. Invoke `sym_upload` like
```
$ ./sym_upload -p sym-upload-v2 [-k <API-key>] <symbol-file> <API-URL>
```

Where `symbol-file` is a symbol file created by `dump_syms`, `API-URL` is the
URL of your `sym-upload-v2` API service (see next section for details), and
`API-key` is a secret known to your uploader and server.

For more options see `sym_upload --help`.

### Uploading with curl

As an example, if:
  * Your API's URL was "https://sym-upload-api".
  * Your service has assigned you `key` "myfancysecret123".
  * You wanted to upload the symbol file at "path/to/file_name", with
`debug_file` being "file_name" and `debug_id` being
"123123123123123123123123123". Normally you would read these values from
"path/to/file_name", which in turn was generated by `dump_syms`.

Then you might run:
```
$ curl https://sym-upload-api/symbols/file_name/123123123123123123123123123:checkStatus?key=myfancysecret123
```

And, upon seeing that this `debug_file`/`debug_id` combo is missing from symbol
storage then you could run:
```
$ curl --request POST https://sym-upload-api/uploads:create?key=myfancysecret123
```

Which returns `upload_url` "https://upload-server/42?creds=shhhhh" and
`upload_key` "42". Next you upload the file directly like:
```
$ curl -T path/to/file_name "https://upload-server/42?creds=shhhhh"
```

Once the HTTP PUT is complete, run:
```
$ curl --header "Content-Type: application/json" \
    --request POST \
    --data '{symbol_id:{"debugFile":"file_name",'\
        '"debugId":"123123123123123123123123123"}}' \
    https://sym-upload-api/uploads/42:complete?key=myfancysecret123
```

### Serving the `sym-upload-v2` Protocol

The protocol is currently defined only in HTTP/REST. There are three necessary
REST operations to implement in your service:
* `/symbols/<debug_file>/<debug_id>:checkStatus?key=<key>`
* `/uploads:create?key=<key>`
* `/uploads/<upload_key>:complete?key=<key>`

#### Authenticate Using `key`

The query string arg `key` contains some secret that both the uploader and
server understand. It is up to the service implementer to decide on what
constitutes a valid `key`, how the uploader acquires one, and how to handle
requests made with invalid ones.

#### Symbol `checkStatus`

```
/symbols/<debug_file>/<debug_id>:checkStatus?key=<key>
```

This operation expects an empty (or no) JSON payload in the request.

This operation should return the status of the symbol file uniquely identified
by the given `debug_file` and `debug_id`. JSON schema:
```
{
    "type": object",
    "properties": {
        "status": {
            "type": "string",
            "enum": ["STATUS_UNSPECIFIED", "MISING", "FOUND"],
            "required": true
        }
    }
}
```

Where `MISSING` denotes that the symbol file does not exist on the server and
`FOUND` denotes that the symbol file exists on the server.

#### Upload `create`

```
/uploads:create?key=<key>
```

This operation expects an empty (or no) JSON payload in the request.

This operation should return a URL that uploader can HTTP PUT their symbol file
to, along with an "upload key" that can be used to notify the service once the
file upload is completed. JSON schema:
```
{
    "type": "object",
    "properties": {
        "upload_url": {
            "type: "string",
            "required": true
        },
        "upload_key": {
            "type": "string",
            "required": true
        }
    }
}
```

Since this REST API operation can be authenticated via the `key` query string
arg, the service can return a URL that encodes permission delegation to the
upload endpoint resource and thereby constrain the ability to upload to those
with valid `key`s.

#### Uploading the Symbol File

Note that the actual symbol upload step is _not_ part of the REST API. The
upload URL obtained in the above operation is meant to be used as the endpoint
for a normal HTTP PUT request for the contents of the symbol file. Once that
HTTP PUT request is completed use the upload `complete` operation.

#### Upload `complete`

```
/uploads/<upload_key>:complete?key=<key>
```

This operation expects a JSON payload in the HTTP request body with the
following schema:
```
{
    "type": "object",
    "properties": {
        "symbol_id": {
            "type": "object",
            "properties": {
                "debug_file": {
                    "type": "string",
                    "required": true
                },
                "debug_id": {
                    "type": "string",
                    "required": true
                }
            }
        }
    }
}
```

This operation should cause the symbol storage back-end (however implemented)
to consume the symbol file identified by `upload_key`. It is up to the service
implementation to decide how uploads are assigned `upload_key`s and how to
retrieve a completed upload by its `upload_key`. If the symbol file cannot be
found, is malformed, or the operation cannot be completed for any other reason
then an HTTP error will be returned. JSON schema of non-error responses:
```
{
    "type": "object",
    "properties": {
        "result": {
            "type": string,
            "enum": ["RESULT_UNSPECIFIED", "OK", "DUPLICATE_DATA"],
            "required": true
        }
    }
}
```

Where `OK` denotes that the symbol storage was updated with the new symbol file
and `DUPLICATE_DATA` denotes that the symbol file data was identical to data
already in symbol storage and therefore nothing changed.