Add endpoint for retrieving devices.
Add an endpoint for retrieving devices, either as a list or by ID.
Stub endpoints for updating and deleting devices., along with TODOs marking them
as things to still be completed. (Right now, accessing those endpoints is an
insta-panic.)
Simplify our handleCreateDevices by returning StatusUnauthorized if AuthUser
fails, so we can reserve StatusForbidden for when auth succeeds but access is
still denied. Also, delay the instantiation and allocation of a Response
variable until we're actually going to use it.
Create a handleGetDevices handler that authenticates the user, and if no ID is
set, returns a list of all their Devices. If one or more IDs are set, only those
Devices are returned. If ScopeViewPushToken is one of the scopes associated with
the request, the push tokens for each Device will be included in the response.
Otherwise, they will be omitted.
1 // Copyright 2014 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Package context defines the Context type, which carries deadlines,
6 // cancelation signals, and other request-scoped values across API boundaries
7 // and between processes.
9 // Incoming requests to a server should create a Context, and outgoing calls to
10 // servers should accept a Context. The chain of function calls between must
11 // propagate the Context, optionally replacing it with a modified copy created
12 // using WithDeadline, WithTimeout, WithCancel, or WithValue.
14 // Programs that use Contexts should follow these rules to keep interfaces
15 // consistent across packages and enable static analysis tools to check context
18 // Do not store Contexts inside a struct type; instead, pass a Context
19 // explicitly to each function that needs it. The Context should be the first
20 // parameter, typically named ctx:
22 // func DoSomething(ctx context.Context, arg Arg) error {
26 // Do not pass a nil Context, even if a function permits it. Pass context.TODO
27 // if you are unsure about which Context to use.
29 // Use context Values only for request-scoped data that transits processes and
30 // APIs, not for passing optional parameters to functions.
32 // The same Context may be passed to functions running in different goroutines;
33 // Contexts are safe for simultaneous use by multiple goroutines.
35 // See http://blog.golang.org/context for example code for a server that uses
46 // A Context carries a deadline, a cancelation signal, and other values across
49 // Context's methods may be called by multiple goroutines simultaneously.
50 type Context interface {
51 // Deadline returns the time when work done on behalf of this context
52 // should be canceled. Deadline returns ok==false when no deadline is
53 // set. Successive calls to Deadline return the same results.
54 Deadline() (deadline time.Time, ok bool)
56 // Done returns a channel that's closed when work done on behalf of this
57 // context should be canceled. Done may return nil if this context can
58 // never be canceled. Successive calls to Done return the same value.
60 // WithCancel arranges for Done to be closed when cancel is called;
61 // WithDeadline arranges for Done to be closed when the deadline
62 // expires; WithTimeout arranges for Done to be closed when the timeout
65 // Done is provided for use in select statements:
67 // // Stream generates values with DoSomething and sends them to out
68 // // until DoSomething returns an error or ctx.Done is closed.
69 // func Stream(ctx context.Context, out <-chan Value) error {
71 // v, err := DoSomething(ctx)
83 // See http://blog.golang.org/pipelines for more examples of how to use
84 // a Done channel for cancelation.
85 Done() <-chan struct{}
87 // Err returns a non-nil error value after Done is closed. Err returns
88 // Canceled if the context was canceled or DeadlineExceeded if the
89 // context's deadline passed. No other values for Err are defined.
90 // After Done is closed, successive calls to Err return the same value.
93 // Value returns the value associated with this context for key, or nil
94 // if no value is associated with key. Successive calls to Value with
95 // the same key returns the same result.
97 // Use context values only for request-scoped data that transits
98 // processes and API boundaries, not for passing optional parameters to
101 // A key identifies a specific value in a Context. Functions that wish
102 // to store values in Context typically allocate a key in a global
103 // variable then use that key as the argument to context.WithValue and
104 // Context.Value. A key can be any type that supports equality;
105 // packages should define keys as an unexported type to avoid
108 // Packages that define a Context key should provide type-safe accessors
109 // for the values stores using that key:
111 // // Package user defines a User type that's stored in Contexts.
114 // import "golang.org/x/net/context"
116 // // User is the type of value stored in the Contexts.
117 // type User struct {...}
119 // // key is an unexported type for keys defined in this package.
120 // // This prevents collisions with keys defined in other packages.
123 // // userKey is the key for user.User values in Contexts. It is
124 // // unexported; clients use user.NewContext and user.FromContext
125 // // instead of using this key directly.
126 // var userKey key = 0
128 // // NewContext returns a new Context that carries value u.
129 // func NewContext(ctx context.Context, u *User) context.Context {
130 // return context.WithValue(ctx, userKey, u)
133 // // FromContext returns the User value stored in ctx, if any.
134 // func FromContext(ctx context.Context) (*User, bool) {
135 // u, ok := ctx.Value(userKey).(*User)
138 Value(key interface{}) interface{}
141 // Canceled is the error returned by Context.Err when the context is canceled.
142 var Canceled = errors.New("context canceled")
144 // DeadlineExceeded is the error returned by Context.Err when the context's
146 var DeadlineExceeded = errors.New("context deadline exceeded")
148 // An emptyCtx is never canceled, has no values, and has no deadline. It is not
149 // struct{}, since vars of this type must have distinct addresses.
152 func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
156 func (*emptyCtx) Done() <-chan struct{} {
160 func (*emptyCtx) Err() error {
164 func (*emptyCtx) Value(key interface{}) interface{} {
168 func (e *emptyCtx) String() string {
171 return "context.Background"
173 return "context.TODO"
175 return "unknown empty Context"
179 background = new(emptyCtx)
183 // Background returns a non-nil, empty Context. It is never canceled, has no
184 // values, and has no deadline. It is typically used by the main function,
185 // initialization, and tests, and as the top-level Context for incoming
187 func Background() Context {
191 // TODO returns a non-nil, empty Context. Code should use context.TODO when
192 // it's unclear which Context to use or it's is not yet available (because the
193 // surrounding function has not yet been extended to accept a Context
194 // parameter). TODO is recognized by static analysis tools that determine
195 // whether Contexts are propagated correctly in a program.
196 func TODO() Context {
200 // A CancelFunc tells an operation to abandon its work.
201 // A CancelFunc does not wait for the work to stop.
202 // After the first call, subsequent calls to a CancelFunc do nothing.
203 type CancelFunc func()
205 // WithCancel returns a copy of parent with a new Done channel. The returned
206 // context's Done channel is closed when the returned cancel function is called
207 // or when the parent context's Done channel is closed, whichever happens first.
209 // Canceling this context releases resources associated with it, so code should
210 // call cancel as soon as the operations running in this Context complete.
211 func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
212 c := newCancelCtx(parent)
213 propagateCancel(parent, &c)
214 return &c, func() { c.cancel(true, Canceled) }
217 // newCancelCtx returns an initialized cancelCtx.
218 func newCancelCtx(parent Context) cancelCtx {
221 done: make(chan struct{}),
225 // propagateCancel arranges for child to be canceled when parent is.
226 func propagateCancel(parent Context, child canceler) {
227 if parent.Done() == nil {
228 return // parent is never canceled
230 if p, ok := parentCancelCtx(parent); ok {
233 // parent has already been canceled
234 child.cancel(false, p.err)
236 if p.children == nil {
237 p.children = make(map[canceler]bool)
239 p.children[child] = true
245 case <-parent.Done():
246 child.cancel(false, parent.Err())
253 // parentCancelCtx follows a chain of parent references until it finds a
254 // *cancelCtx. This function understands how each of the concrete types in this
255 // package represents its parent.
256 func parentCancelCtx(parent Context) (*cancelCtx, bool) {
258 switch c := parent.(type) {
262 return &c.cancelCtx, true
271 // removeChild removes a context from its parent.
272 func removeChild(parent Context, child canceler) {
273 p, ok := parentCancelCtx(parent)
278 if p.children != nil {
279 delete(p.children, child)
284 // A canceler is a context type that can be canceled directly. The
285 // implementations are *cancelCtx and *timerCtx.
286 type canceler interface {
287 cancel(removeFromParent bool, err error)
288 Done() <-chan struct{}
291 // A cancelCtx can be canceled. When canceled, it also cancels any children
292 // that implement canceler.
293 type cancelCtx struct {
296 done chan struct{} // closed by the first cancel call.
299 children map[canceler]bool // set to nil by the first cancel call
300 err error // set to non-nil by the first cancel call
303 func (c *cancelCtx) Done() <-chan struct{} {
307 func (c *cancelCtx) Err() error {
313 func (c *cancelCtx) String() string {
314 return fmt.Sprintf("%v.WithCancel", c.Context)
317 // cancel closes c.done, cancels each of c's children, and, if
318 // removeFromParent is true, removes c from its parent's children.
319 func (c *cancelCtx) cancel(removeFromParent bool, err error) {
321 panic("context: internal error: missing cancel error")
326 return // already canceled
330 for child := range c.children {
331 // NOTE: acquiring the child's lock while holding parent's lock.
332 child.cancel(false, err)
337 if removeFromParent {
338 removeChild(c.Context, c)
342 // WithDeadline returns a copy of the parent context with the deadline adjusted
343 // to be no later than d. If the parent's deadline is already earlier than d,
344 // WithDeadline(parent, d) is semantically equivalent to parent. The returned
345 // context's Done channel is closed when the deadline expires, when the returned
346 // cancel function is called, or when the parent context's Done channel is
347 // closed, whichever happens first.
349 // Canceling this context releases resources associated with it, so code should
350 // call cancel as soon as the operations running in this Context complete.
351 func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
352 if cur, ok := parent.Deadline(); ok && cur.Before(deadline) {
353 // The current deadline is already sooner than the new one.
354 return WithCancel(parent)
357 cancelCtx: newCancelCtx(parent),
360 propagateCancel(parent, c)
361 d := deadline.Sub(time.Now())
363 c.cancel(true, DeadlineExceeded) // deadline has already passed
364 return c, func() { c.cancel(true, Canceled) }
369 c.timer = time.AfterFunc(d, func() {
370 c.cancel(true, DeadlineExceeded)
373 return c, func() { c.cancel(true, Canceled) }
376 // A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
377 // implement Done and Err. It implements cancel by stopping its timer then
378 // delegating to cancelCtx.cancel.
379 type timerCtx struct {
381 timer *time.Timer // Under cancelCtx.mu.
386 func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
387 return c.deadline, true
390 func (c *timerCtx) String() string {
391 return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now()))
394 func (c *timerCtx) cancel(removeFromParent bool, err error) {
395 c.cancelCtx.cancel(false, err)
396 if removeFromParent {
397 // Remove this timerCtx from its parent cancelCtx's children.
398 removeChild(c.cancelCtx.Context, c)
408 // WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
410 // Canceling this context releases resources associated with it, so code should
411 // call cancel as soon as the operations running in this Context complete:
413 // func slowOperationWithTimeout(ctx context.Context) (Result, error) {
414 // ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
415 // defer cancel() // releases resources if slowOperation completes before timeout elapses
416 // return slowOperation(ctx)
418 func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
419 return WithDeadline(parent, time.Now().Add(timeout))
422 // WithValue returns a copy of parent in which the value associated with key is
425 // Use context Values only for request-scoped data that transits processes and
426 // APIs, not for passing optional parameters to functions.
427 func WithValue(parent Context, key interface{}, val interface{}) Context {
428 return &valueCtx{parent, key, val}
431 // A valueCtx carries a key-value pair. It implements Value for that key and
432 // delegates all other calls to the embedded Context.
433 type valueCtx struct {
438 func (c *valueCtx) String() string {
439 return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val)
442 func (c *valueCtx) Value(key interface{}) interface{} {
446 return c.Context.Value(key)