英文:
How can I create cloud context.Context from appengine.Context
问题
我无法弄清楚如何在只有appengine.Context
而没有context.Context
的情况下调用cloud.WithContext
和google.DefaultClient
。
有两个包,一个是旧的"appengine",另一个是新的"google.golang.org/appengine"。第一个包提供了自定义的appengine.Context
,而第二个包则使用来自"golang.org/x/net/context"的context.Context
。
整个google.golang.org/cloud
只接受context.Context
。
我很乐意开始使用新的"google.golang.org/appengine",但我卡在了尚未移植的runtime.RunInBackground
上。来自https://github.com/golang/appengine:
appengine/aetest
、appengine/cloudsql
和appengine/runtime
尚未移植。
如果appengine/runtime
已经移植完成,我可以这样写:
import (
"golang.org/x/net/context"
"google.golang.org/appengine"
"google.golang.org/appengine/runtime"
"google.golang.org/cloud"
"google.golang.org/cloud/storage"
)
func handler(w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
runtime.RunInBackground(c, func(ctx context.Context) {
hc, _ := google.DefaultClient(ctx, storage.ScopeFullControl)
cc := cloud.WithContext(ctx, appengine.AppID(ctx), hc)
…
})
}
但是目前还没有"google.golang.org/appengine/runtime"
。所以我有:
runtime.RunInBackground(c, func(ctx appengine.Context) {
英文:
I can't figure out how to call cloud.WithContext
and google.DefaultClient
if I have appengine.Context
and not context.Context
.
There are (old) "appengine" and (new) "google.golang.org/appengine" packages. The first one brings custom appengine.Context
when second one comes with context.Context
from "golang.org/x/net/context"
The whole google.golang.org/cloud
expects context.Context
only.
I would be happy to move to using new "google.golang.org/appengine"
, but I've stuck with runtime.RunInBackground
that have not been ported yet. From https://github.com/golang/appengine:
> appengine/aetest
, appengine/cloudsql
and appengine/runtime
have not been ported yet.
What I could write if appengine/runtime
have been ported already:
import (
"golang.org/x/net/context"
"google.golang.org/appengine"
"google.golang.org/appengine/runtime"
"google.golang.org/cloud"
"google.golang.org/cloud/storage"
)
func handler(w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
runtime.RunInBackground(c, func(ctx context.Context) {
hc, _ := google.DefaultClient(ctx, storage.ScopeFullControl)
cc := cloud.WithContext(ctx, appengine.AppID(ctx), hc)
…
})
}
but there is no "google.golang.org/appengine/runtime"
yet. So I have
runtime.RunInBackground(c, func(ctx appengine.Context) {
答案1
得分: 3
目前无法从(旧的)appengine.Context
中获取云context.Context
的方法。
托管 VM 的解决方案
一个月前,google.golang.org/appengine
中添加了BackgroundContext()
方法(仅适用于托管 VM)。这允许启动 goroutine 并获取云context.Context
而无需传递它。
经典 Appengine 的解决方案
目前没有解决方案。
英文:
At the moment there is no way to get cloud context.Context
from (old) appengine.Context
.
Solution for Managed VM
A month ago BackgroundContext()
method was added to google.golang.org/appengine
(available for Managed VM only). This allows start goroutine and get cloud context.Context
without passing it into.
Solution for classic Appengine
There is no solution at the moment.
答案2
得分: 2
做这个:
func getCloudContext(appengineContext context.Context) context.Context {
hc := &http.Client{
Transport: &oauth2.Transport{
Source: google.AppEngineTokenSource(appengineContext, storage.ScopeFullControl),
Base: &urlfetch.Transport{Context: appengineContext},
},
}
return cloud.NewContext(appengine.AppID(appengineContext), hc)
}
或者,如果通过开发服务器传递凭据不起作用,您还可以使用显式凭据:
func getCloudContext(aeCtx context.Context) (context.Context, error) {
data, err := ioutil.ReadFile("/path/to/credentials.json")
if err != nil {
return nil, err
}
conf, err := google.JWTConfigFromJSON(
data,
storage.ScopeFullControl,
)
if err != nil {
return nil, err
}
tokenSource := conf.TokenSource(aeCtx)
hc := &http.Client{
Transport: &oauth2.Transport{
Source: tokenSource,
Base: &urlfetch.Transport{Context: aeCtx},
},
}
return cloud.NewContext(appengine.AppID(aeCtx), hc), nil
}
英文:
Do this:
func getCloudContext(appengineContext context.Context) context.Context {
hc := &http.Client{
Transport: &oauth2.Transport{
Source: google.AppEngineTokenSource(appengineContext, storage.ScopeFullControl),
Base: &urlfetch.Transport{Context: appengineContext},
},
}
return cloud.NewContext(appengine.AppID(appengineContext), hc)
}
Or if passing the credentials through the dev server isn't working, you can also use explicit credentials:
func getCloudContext(aeCtx context.Context) (context.Context, error) {
data, err := ioutil.ReadFile("/path/to/credentials.json")
if err != nil {
return nil, err
}
conf, err := google.JWTConfigFromJSON(
data,
storage.ScopeFullControl,
)
if err != nil {
return nil, err
}
tokenSource := conf.TokenSource(aeCtx)
hc := &http.Client{
Transport: &oauth2.Transport{
Source: tokenSource,
Base: &urlfetch.Transport{Context: aeCtx},
},
}
return cloud.NewContext(appengine.AppID(aeCtx), hc), nil
}
答案3
得分: 1
以下是你想要的代码的翻译:
这是你可以实现你想要的方式:
import (
"code.google.com/p/goauth2/appengine/serviceaccount"
"golang.org/x/net/context"
"appengine"
)
// oauth2 模块需要一个 context.Context,所以现在先使用 goauth2
func CloudContext(c appengine.Context, scopes ...string) context.Context {
client, _ := serviceaccount.NewClient(c, scopes...)
return cloud.WithContext(context.Background(), appengine.AppID(c), client)
}
你可以从 https://code.google.com/p/goauth2/source/browse/ 获取 goauth2 库。
英文:
Here is how you can do what you want:
import (
"code.google.com/p/goauth2/appengine/serviceaccount"
"golang.org/x/net/context"
"appengine"
)
// oauth2 module requires a context.Context so use goauth2 for now
func CloudContext(c appengine.Context, scopes ...string) context.Context {
client, _ := serviceaccount.NewClient(c, scopes...)
return cloud.WithContext(context.Background(), appengine.AppID(c), client)
}
You can get the goauth2 library from https://code.google.com/p/goauth2/source/browse/
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论