Skip to content

Confusing error when using other Google APIs #63

Description

Symptom: I tried to use stock Google libraries to access other Google APIs, like Google Storage, but got bit by an obscure error "not an App Engine context". Here's a repro, and a commented out fix I eventually found after talking to @danjacques :

package lucigaeissue

import (
    "net/http"

    "golang.org/x/oauth2/google"
    storage "google.golang.org/api/storage/v1"

    // "github.com/luci/gae/impl/prod"
    "github.com/luci/luci-go/appengine/gaemiddleware"
    "github.com/luci/luci-go/common/logging"
    "github.com/luci/luci-go/server/router"
)

func init() {
    r := router.New()
    mw := gaemiddleware.BaseProd()
    gaemiddleware.InstallHandlers(r, mw)
    r.GET("/", mw, handler)

    http.DefaultServeMux.Handle("/", r)
}

func handler(c *router.Context) {
    scope := storage.DevstorageFullControlScope
    ctx := c.Context // What I'd expect to use
    // ctx := prod.AEContext(c.Context) // What I should really use
    client, _ := google.DefaultClient(ctx, scope)
    service, _ := storage.New(client)
    if _, err := service.Buckets.List("project-id").Do(); err != nil {
        logging.Errorf(c.Context, "Buckets.List failed: %s", err)
    } else {
        logging.Infof(c.Context, "Buckets.List succeeded")
    }
}

What happens: router.Handle() starts the handler with an empty context;
gaemiddleware.BaseProd() installs ProdServices which calls prod.Use which hides the true AppEngine context under a key.

As a result, it appears that c.Context is an App Engine context, because Datastore and other GAE services work just fine, yet calling a native Cloud API fails with "not an App Engine context".

This error is very non-intuitive, and cost me hours of debugging. Turns out, I simply needed to use prod.AEContext(c.Context) in DefaultClient(). I did not find any mention of it in the documentation, not even for AEContext itself.

The problem stems from the fact that c.Context appears to be the only way to get a context.Context value, and nothing indicates that it's not an App Engine context.

So, it's a UX / useability issue which could probably be fixed by better documentation, or simply allowing c.Context to be a derivative of the actual App Engine context. The latter might be a luci-go issue.

Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions