1
0
Fork 0
forked from forgejo/forgejo

Use Go1.11 module (#5743)

* Migrate to go modules

* make vendor

* Update mvdan.cc/xurls

* make vendor

* Update code.gitea.io/git

* make fmt-check

* Update github.com/go-sql-driver/mysql

* make vendor
This commit is contained in:
Mura Li 2019-03-27 19:15:23 +08:00 committed by Lunny Xiao
parent d578b71d61
commit d77176912b
575 changed files with 63239 additions and 13963 deletions

202
vendor/google.golang.org/appengine/LICENSE generated vendored Normal file
View file

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -0,0 +1,62 @@
// Copyright 2013 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.
/*
Package cloudsql exposes access to Google Cloud SQL databases.
This package does not work in App Engine "flexible environment".
This package is intended for MySQL drivers to make App Engine-specific
connections. Applications should use this package through database/sql:
Select a pure Go MySQL driver that supports this package, and use sql.Open
with protocol "cloudsql" and an address of the Cloud SQL instance.
A Go MySQL driver that has been tested to work well with Cloud SQL
is the go-sql-driver:
import "database/sql"
import _ "github.com/go-sql-driver/mysql"
db, err := sql.Open("mysql", "user@cloudsql(project-id:instance-name)/dbname")
Another driver that works well with Cloud SQL is the mymysql driver:
import "database/sql"
import _ "github.com/ziutek/mymysql/godrv"
db, err := sql.Open("mymysql", "cloudsql:instance-name*dbname/user/password")
Using either of these drivers, you can perform a standard SQL query.
This example assumes there is a table named 'users' with
columns 'first_name' and 'last_name':
rows, err := db.Query("SELECT first_name, last_name FROM users")
if err != nil {
log.Errorf(ctx, "db.Query: %v", err)
}
defer rows.Close()
for rows.Next() {
var firstName string
var lastName string
if err := rows.Scan(&firstName, &lastName); err != nil {
log.Errorf(ctx, "rows.Scan: %v", err)
continue
}
log.Infof(ctx, "First: %v - Last: %v", firstName, lastName)
}
if err := rows.Err(); err != nil {
log.Errorf(ctx, "Row error: %v", err)
}
*/
package cloudsql
import (
"net"
)
// Dial connects to the named Cloud SQL instance.
func Dial(instance string) (net.Conn, error) {
return connect(instance)
}

View file

@ -0,0 +1,17 @@
// Copyright 2013 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.
// +build appengine
package cloudsql
import (
"net"
"appengine/cloudsql"
)
func connect(instance string) (net.Conn, error) {
return cloudsql.Dial(instance)
}

View file

@ -0,0 +1,16 @@
// Copyright 2013 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.
// +build !appengine
package cloudsql
import (
"errors"
"net"
)
func connect(instance string) (net.Conn, error) {
return nil, errors.New(`cloudsql: not supported in App Engine "flexible environment"`)
}

660
vendor/google.golang.org/appengine/internal/api.go generated vendored Normal file
View file

@ -0,0 +1,660 @@
// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.
// +build !appengine
// +build go1.7
package internal
import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"log"
"net"
"net/http"
"net/url"
"os"
"runtime"
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
"github.com/golang/protobuf/proto"
netcontext "golang.org/x/net/context"
basepb "google.golang.org/appengine/internal/base"
logpb "google.golang.org/appengine/internal/log"
remotepb "google.golang.org/appengine/internal/remote_api"
)
const (
apiPath = "/rpc_http"
defaultTicketSuffix = "/default.20150612t184001.0"
)
var (
// Incoming headers.
ticketHeader = http.CanonicalHeaderKey("X-AppEngine-API-Ticket")
dapperHeader = http.CanonicalHeaderKey("X-Google-DapperTraceInfo")
traceHeader = http.CanonicalHeaderKey("X-Cloud-Trace-Context")
curNamespaceHeader = http.CanonicalHeaderKey("X-AppEngine-Current-Namespace")
userIPHeader = http.CanonicalHeaderKey("X-AppEngine-User-IP")
remoteAddrHeader = http.CanonicalHeaderKey("X-AppEngine-Remote-Addr")
// Outgoing headers.
apiEndpointHeader = http.CanonicalHeaderKey("X-Google-RPC-Service-Endpoint")
apiEndpointHeaderValue = []string{"app-engine-apis"}
apiMethodHeader = http.CanonicalHeaderKey("X-Google-RPC-Service-Method")
apiMethodHeaderValue = []string{"/VMRemoteAPI.CallRemoteAPI"}
apiDeadlineHeader = http.CanonicalHeaderKey("X-Google-RPC-Service-Deadline")
apiContentType = http.CanonicalHeaderKey("Content-Type")
apiContentTypeValue = []string{"application/octet-stream"}
logFlushHeader = http.CanonicalHeaderKey("X-AppEngine-Log-Flush-Count")
apiHTTPClient = &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
Dial: limitDial,
},
}
defaultTicketOnce sync.Once
defaultTicket string
backgroundContextOnce sync.Once
backgroundContext netcontext.Context
)
func apiURL() *url.URL {
host, port := "appengine.googleapis.internal", "10001"
if h := os.Getenv("API_HOST"); h != "" {
host = h
}
if p := os.Getenv("API_PORT"); p != "" {
port = p
}
return &url.URL{
Scheme: "http",
Host: host + ":" + port,
Path: apiPath,
}
}
func handleHTTP(w http.ResponseWriter, r *http.Request) {
c := &context{
req: r,
outHeader: w.Header(),
apiURL: apiURL(),
}
r = r.WithContext(withContext(r.Context(), c))
c.req = r
stopFlushing := make(chan int)
// Patch up RemoteAddr so it looks reasonable.
if addr := r.Header.Get(userIPHeader); addr != "" {
r.RemoteAddr = addr
} else if addr = r.Header.Get(remoteAddrHeader); addr != "" {
r.RemoteAddr = addr
} else {
// Should not normally reach here, but pick a sensible default anyway.
r.RemoteAddr = "127.0.0.1"
}
// The address in the headers will most likely be of these forms:
// 123.123.123.123
// 2001:db8::1
// net/http.Request.RemoteAddr is specified to be in "IP:port" form.
if _, _, err := net.SplitHostPort(r.RemoteAddr); err != nil {
// Assume the remote address is only a host; add a default port.
r.RemoteAddr = net.JoinHostPort(r.RemoteAddr, "80")
}
// Start goroutine responsible for flushing app logs.
// This is done after adding c to ctx.m (and stopped before removing it)
// because flushing logs requires making an API call.
go c.logFlusher(stopFlushing)
executeRequestSafely(c, r)
c.outHeader = nil // make sure header changes aren't respected any more
stopFlushing <- 1 // any logging beyond this point will be dropped
// Flush any pending logs asynchronously.
c.pendingLogs.Lock()
flushes := c.pendingLogs.flushes
if len(c.pendingLogs.lines) > 0 {
flushes++
}
c.pendingLogs.Unlock()
go c.flushLog(false)
w.Header().Set(logFlushHeader, strconv.Itoa(flushes))
// Avoid nil Write call if c.Write is never called.
if c.outCode != 0 {
w.WriteHeader(c.outCode)
}
if c.outBody != nil {
w.Write(c.outBody)
}
}
func executeRequestSafely(c *context, r *http.Request) {
defer func() {
if x := recover(); x != nil {
logf(c, 4, "%s", renderPanic(x)) // 4 == critical
c.outCode = 500
}
}()
http.DefaultServeMux.ServeHTTP(c, r)
}
func renderPanic(x interface{}) string {
buf := make([]byte, 16<<10) // 16 KB should be plenty
buf = buf[:runtime.Stack(buf, false)]
// Remove the first few stack frames:
// this func
// the recover closure in the caller
// That will root the stack trace at the site of the panic.
const (
skipStart = "internal.renderPanic"
skipFrames = 2
)
start := bytes.Index(buf, []byte(skipStart))
p := start
for i := 0; i < skipFrames*2 && p+1 < len(buf); i++ {
p = bytes.IndexByte(buf[p+1:], '\n') + p + 1
if p < 0 {
break
}
}
if p >= 0 {
// buf[start:p+1] is the block to remove.
// Copy buf[p+1:] over buf[start:] and shrink buf.
copy(buf[start:], buf[p+1:])
buf = buf[:len(buf)-(p+1-start)]
}
// Add panic heading.
head := fmt.Sprintf("panic: %v\n\n", x)
if len(head) > len(buf) {
// Extremely unlikely to happen.
return head
}
copy(buf[len(head):], buf)
copy(buf, head)
return string(buf)
}
// context represents the context of an in-flight HTTP request.
// It implements the appengine.Context and http.ResponseWriter interfaces.
type context struct {
req *http.Request
outCode int
outHeader http.Header
outBody []byte
pendingLogs struct {
sync.Mutex
lines []*logpb.UserAppLogLine
flushes int
}
apiURL *url.URL
}
var contextKey = "holds a *context"
// jointContext joins two contexts in a superficial way.
// It takes values and timeouts from a base context, and only values from another context.
type jointContext struct {
base netcontext.Context
valuesOnly netcontext.Context
}
func (c jointContext) Deadline() (time.Time, bool) {
return c.base.Deadline()
}
func (c jointContext) Done() <-chan struct{} {
return c.base.Done()
}
func (c jointContext) Err() error {
return c.base.Err()
}
func (c jointContext) Value(key interface{}) interface{} {
if val := c.base.Value(key); val != nil {
return val
}
return c.valuesOnly.Value(key)
}
// fromContext returns the App Engine context or nil if ctx is not
// derived from an App Engine context.
func fromContext(ctx netcontext.Context) *context {
c, _ := ctx.Value(&contextKey).(*context)
return c
}
func withContext(parent netcontext.Context, c *context) netcontext.Context {
ctx := netcontext.WithValue(parent, &contextKey, c)
if ns := c.req.Header.Get(curNamespaceHeader); ns != "" {
ctx = withNamespace(ctx, ns)
}
return ctx
}
func toContext(c *context) netcontext.Context {
return withContext(netcontext.Background(), c)
}
func IncomingHeaders(ctx netcontext.Context) http.Header {
if c := fromContext(ctx); c != nil {
return c.req.Header
}
return nil
}
func ReqContext(req *http.Request) netcontext.Context {
return req.Context()
}
func WithContext(parent netcontext.Context, req *http.Request) netcontext.Context {
return jointContext{
base: parent,
valuesOnly: req.Context(),
}
}
// DefaultTicket returns a ticket used for background context or dev_appserver.
func DefaultTicket() string {
defaultTicketOnce.Do(func() {
if IsDevAppServer() {
defaultTicket = "testapp" + defaultTicketSuffix
return
}
appID := partitionlessAppID()
escAppID := strings.Replace(strings.Replace(appID, ":", "_", -1), ".", "_", -1)
majVersion := VersionID(nil)
if i := strings.Index(majVersion, "."); i > 0 {
majVersion = majVersion[:i]
}
defaultTicket = fmt.Sprintf("%s/%s.%s.%s", escAppID, ModuleName(nil), majVersion, InstanceID())
})
return defaultTicket
}
func BackgroundContext() netcontext.Context {
backgroundContextOnce.Do(func() {
// Compute background security ticket.
ticket := DefaultTicket()
c := &context{
req: &http.Request{
Header: http.Header{
ticketHeader: []string{ticket},
},
},
apiURL: apiURL(),
}
backgroundContext = toContext(c)
// TODO(dsymonds): Wire up the shutdown handler to do a final flush.
go c.logFlusher(make(chan int))
})
return backgroundContext
}
// RegisterTestRequest registers the HTTP request req for testing, such that
// any API calls are sent to the provided URL. It returns a closure to delete
// the registration.
// It should only be used by aetest package.
func RegisterTestRequest(req *http.Request, apiURL *url.URL, decorate func(netcontext.Context) netcontext.Context) (*http.Request, func()) {
c := &context{
req: req,
apiURL: apiURL,
}
ctx := withContext(decorate(req.Context()), c)
req = req.WithContext(ctx)
c.req = req
return req, func() {}
}
var errTimeout = &CallError{
Detail: "Deadline exceeded",
Code: int32(remotepb.RpcError_CANCELLED),
Timeout: true,
}
func (c *context) Header() http.Header { return c.outHeader }
// Copied from $GOROOT/src/pkg/net/http/transfer.go. Some response status
// codes do not permit a response body (nor response entity headers such as
// Content-Length, Content-Type, etc).
func bodyAllowedForStatus(status int) bool {
switch {
case status >= 100 && status <= 199:
return false
case status == 204:
return false
case status == 304:
return false
}
return true
}
func (c *context) Write(b []byte) (int, error) {
if c.outCode == 0 {
c.WriteHeader(http.StatusOK)
}
if len(b) > 0 && !bodyAllowedForStatus(c.outCode) {
return 0, http.ErrBodyNotAllowed
}
c.outBody = append(c.outBody, b...)
return len(b), nil
}
func (c *context) WriteHeader(code int) {
if c.outCode != 0 {
logf(c, 3, "WriteHeader called multiple times on request.") // error level
return
}
c.outCode = code
}
func (c *context) post(body []byte, timeout time.Duration) (b []byte, err error) {
hreq := &http.Request{
Method: "POST",
URL: c.apiURL,
Header: http.Header{
apiEndpointHeader: apiEndpointHeaderValue,
apiMethodHeader: apiMethodHeaderValue,
apiContentType: apiContentTypeValue,
apiDeadlineHeader: []string{strconv.FormatFloat(timeout.Seconds(), 'f', -1, 64)},
},
Body: ioutil.NopCloser(bytes.NewReader(body)),
ContentLength: int64(len(body)),
Host: c.apiURL.Host,
}
if info := c.req.Header.Get(dapperHeader); info != "" {
hreq.Header.Set(dapperHeader, info)
}
if info := c.req.Header.Get(traceHeader); info != "" {
hreq.Header.Set(traceHeader, info)
}
tr := apiHTTPClient.Transport.(*http.Transport)
var timedOut int32 // atomic; set to 1 if timed out
t := time.AfterFunc(timeout, func() {
atomic.StoreInt32(&timedOut, 1)
tr.CancelRequest(hreq)
})
defer t.Stop()
defer func() {
// Check if timeout was exceeded.
if atomic.LoadInt32(&timedOut) != 0 {
err = errTimeout
}
}()
hresp, err := apiHTTPClient.Do(hreq)
if err != nil {
return nil, &CallError{
Detail: fmt.Sprintf("service bridge HTTP failed: %v", err),
Code: int32(remotepb.RpcError_UNKNOWN),
}
}
defer hresp.Body.Close()
hrespBody, err := ioutil.ReadAll(hresp.Body)
if hresp.StatusCode != 200 {
return nil, &CallError{
Detail: fmt.Sprintf("service bridge returned HTTP %d (%q)", hresp.StatusCode, hrespBody),
Code: int32(remotepb.RpcError_UNKNOWN),
}
}
if err != nil {
return nil, &CallError{
Detail: fmt.Sprintf("service bridge response bad: %v", err),
Code: int32(remotepb.RpcError_UNKNOWN),
}
}
return hrespBody, nil
}
func Call(ctx netcontext.Context, service, method string, in, out proto.Message) error {
if ns := NamespaceFromContext(ctx); ns != "" {
if fn, ok := NamespaceMods[service]; ok {
fn(in, ns)
}
}
if f, ctx, ok := callOverrideFromContext(ctx); ok {
return f(ctx, service, method, in, out)
}
// Handle already-done contexts quickly.
select {
case <-ctx.Done():
return ctx.Err()
default:
}
c := fromContext(ctx)
if c == nil {
// Give a good error message rather than a panic lower down.
return errNotAppEngineContext
}
// Apply transaction modifications if we're in a transaction.
if t := transactionFromContext(ctx); t != nil {
if t.finished {
return errors.New("transaction context has expired")
}
applyTransaction(in, &t.transaction)
}
// Default RPC timeout is 60s.
timeout := 60 * time.Second
if deadline, ok := ctx.Deadline(); ok {
timeout = deadline.Sub(time.Now())
}
data, err := proto.Marshal(in)
if err != nil {
return err
}
ticket := c.req.Header.Get(ticketHeader)
// Use a test ticket under test environment.
if ticket == "" {
if appid := ctx.Value(&appIDOverrideKey); appid != nil {
ticket = appid.(string) + defaultTicketSuffix
}
}
// Fall back to use background ticket when the request ticket is not available in Flex or dev_appserver.
if ticket == "" {
ticket = DefaultTicket()
}
req := &remotepb.Request{
ServiceName: &service,
Method: &method,
Request: data,
RequestId: &ticket,
}
hreqBody, err := proto.Marshal(req)
if err != nil {
return err
}
hrespBody, err := c.post(hreqBody, timeout)
if err != nil {
return err
}
res := &remotepb.Response{}
if err := proto.Unmarshal(hrespBody, res); err != nil {
return err
}
if res.RpcError != nil {
ce := &CallError{
Detail: res.RpcError.GetDetail(),
Code: *res.RpcError.Code,
}
switch remotepb.RpcError_ErrorCode(ce.Code) {
case remotepb.RpcError_CANCELLED, remotepb.RpcError_DEADLINE_EXCEEDED:
ce.Timeout = true
}
return ce
}
if res.ApplicationError != nil {
return &APIError{
Service: *req.ServiceName,
Detail: res.ApplicationError.GetDetail(),
Code: *res.ApplicationError.Code,
}
}
if res.Exception != nil || res.JavaException != nil {
// This shouldn't happen, but let's be defensive.
return &CallError{
Detail: "service bridge returned exception",
Code: int32(remotepb.RpcError_UNKNOWN),
}
}
return proto.Unmarshal(res.Response, out)
}
func (c *context) Request() *http.Request {
return c.req
}
func (c *context) addLogLine(ll *logpb.UserAppLogLine) {
// Truncate long log lines.
// TODO(dsymonds): Check if this is still necessary.
const lim = 8 << 10
if len(*ll.Message) > lim {
suffix := fmt.Sprintf("...(length %d)", len(*ll.Message))
ll.Message = proto.String((*ll.Message)[:lim-len(suffix)] + suffix)
}
c.pendingLogs.Lock()
c.pendingLogs.lines = append(c.pendingLogs.lines, ll)
c.pendingLogs.Unlock()
}
var logLevelName = map[int64]string{
0: "DEBUG",
1: "INFO",
2: "WARNING",
3: "ERROR",
4: "CRITICAL",
}
func logf(c *context, level int64, format string, args ...interface{}) {
if c == nil {
panic("not an App Engine context")
}
s := fmt.Sprintf(format, args...)
s = strings.TrimRight(s, "\n") // Remove any trailing newline characters.
c.addLogLine(&logpb.UserAppLogLine{
TimestampUsec: proto.Int64(time.Now().UnixNano() / 1e3),
Level: &level,
Message: &s,
})
log.Print(logLevelName[level] + ": " + s)
}
// flushLog attempts to flush any pending logs to the appserver.
// It should not be called concurrently.
func (c *context) flushLog(force bool) (flushed bool) {
c.pendingLogs.Lock()
// Grab up to 30 MB. We can get away with up to 32 MB, but let's be cautious.
n, rem := 0, 30<<20
for ; n < len(c.pendingLogs.lines); n++ {
ll := c.pendingLogs.lines[n]
// Each log line will require about 3 bytes of overhead.
nb := proto.Size(ll) + 3
if nb > rem {
break
}
rem -= nb
}
lines := c.pendingLogs.lines[:n]
c.pendingLogs.lines = c.pendingLogs.lines[n:]
c.pendingLogs.Unlock()
if len(lines) == 0 && !force {
// Nothing to flush.
return false
}
rescueLogs := false
defer func() {
if rescueLogs {
c.pendingLogs.Lock()
c.pendingLogs.lines = append(lines, c.pendingLogs.lines...)
c.pendingLogs.Unlock()
}
}()
buf, err := proto.Marshal(&logpb.UserAppLogGroup{
LogLine: lines,
})
if err != nil {
log.Printf("internal.flushLog: marshaling UserAppLogGroup: %v", err)
rescueLogs = true
return false
}
req := &logpb.FlushRequest{
Logs: buf,
}
res := &basepb.VoidProto{}
c.pendingLogs.Lock()
c.pendingLogs.flushes++
c.pendingLogs.Unlock()
if err := Call(toContext(c), "logservice", "Flush", req, res); err != nil {
log.Printf("internal.flushLog: Flush RPC: %v", err)
rescueLogs = true
return false
}
return true
}
const (
// Log flushing parameters.
flushInterval = 1 * time.Second
forceFlushInterval = 60 * time.Second
)
func (c *context) logFlusher(stop <-chan int) {
lastFlush := time.Now()
tick := time.NewTicker(flushInterval)
for {
select {
case <-stop:
// Request finished.
tick.Stop()
return
case <-tick.C:
force := time.Now().Sub(lastFlush) > forceFlushInterval
if c.flushLog(force) {
lastFlush = time.Now()
}
}
}
}
func ContextForTesting(req *http.Request) netcontext.Context {
return toContext(&context{req: req})
}

View file

@ -0,0 +1,169 @@
// Copyright 2015 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.
// +build appengine
package internal
import (
"errors"
"fmt"
"net/http"
"time"
"appengine"
"appengine_internal"
basepb "appengine_internal/base"
"github.com/golang/protobuf/proto"
netcontext "golang.org/x/net/context"
)
var contextKey = "holds an appengine.Context"
// fromContext returns the App Engine context or nil if ctx is not
// derived from an App Engine context.
func fromContext(ctx netcontext.Context) appengine.Context {
c, _ := ctx.Value(&contextKey).(appengine.Context)
return c
}
// This is only for classic App Engine adapters.
func ClassicContextFromContext(ctx netcontext.Context) (appengine.Context, error) {
c := fromContext(ctx)
if c == nil {
return nil, errNotAppEngineContext
}
return c, nil
}
func withContext(parent netcontext.Context, c appengine.Context) netcontext.Context {
ctx := netcontext.WithValue(parent, &contextKey, c)
s := &basepb.StringProto{}
c.Call("__go__", "GetNamespace", &basepb.VoidProto{}, s, nil)
if ns := s.GetValue(); ns != "" {
ctx = NamespacedContext(ctx, ns)
}
return ctx
}
func IncomingHeaders(ctx netcontext.Context) http.Header {
if c := fromContext(ctx); c != nil {
if req, ok := c.Request().(*http.Request); ok {
return req.Header
}
}
return nil
}
func ReqContext(req *http.Request) netcontext.Context {
return WithContext(netcontext.Background(), req)
}
func WithContext(parent netcontext.Context, req *http.Request) netcontext.Context {
c := appengine.NewContext(req)
return withContext(parent, c)
}
type testingContext struct {
appengine.Context
req *http.Request
}
func (t *testingContext) FullyQualifiedAppID() string { return "dev~testcontext" }
func (t *testingContext) Call(service, method string, _, _ appengine_internal.ProtoMessage, _ *appengine_internal.CallOptions) error {
if service == "__go__" && method == "GetNamespace" {
return nil
}
return fmt.Errorf("testingContext: unsupported Call")
}
func (t *testingContext) Request() interface{} { return t.req }
func ContextForTesting(req *http.Request) netcontext.Context {
return withContext(netcontext.Background(), &testingContext{req: req})
}
func Call(ctx netcontext.Context, service, method string, in, out proto.Message) error {
if ns := NamespaceFromContext(ctx); ns != "" {
if fn, ok := NamespaceMods[service]; ok {
fn(in, ns)
}
}
if f, ctx, ok := callOverrideFromContext(ctx); ok {
return f(ctx, service, method, in, out)
}
// Handle already-done contexts quickly.
select {
case <-ctx.Done():
return ctx.Err()
default:
}
c := fromContext(ctx)
if c == nil {
// Give a good error message rather than a panic lower down.
return errNotAppEngineContext
}
// Apply transaction modifications if we're in a transaction.
if t := transactionFromContext(ctx); t != nil {
if t.finished {
return errors.New("transaction context has expired")
}
applyTransaction(in, &t.transaction)
}
var opts *appengine_internal.CallOptions
if d, ok := ctx.Deadline(); ok {
opts = &appengine_internal.CallOptions{
Timeout: d.Sub(time.Now()),
}
}
err := c.Call(service, method, in, out, opts)
switch v := err.(type) {
case *appengine_internal.APIError:
return &APIError{
Service: v.Service,
Detail: v.Detail,
Code: v.Code,
}
case *appengine_internal.CallError:
return &CallError{
Detail: v.Detail,
Code: v.Code,
Timeout: v.Timeout,
}
}
return err
}
func handleHTTP(w http.ResponseWriter, r *http.Request) {
panic("handleHTTP called; this should be impossible")
}
func logf(c appengine.Context, level int64, format string, args ...interface{}) {
var fn func(format string, args ...interface{})
switch level {
case 0:
fn = c.Debugf
case 1:
fn = c.Infof
case 2:
fn = c.Warningf
case 3:
fn = c.Errorf
case 4:
fn = c.Criticalf
default:
// This shouldn't happen.
fn = c.Criticalf
}
fn(format, args...)
}

View file

@ -0,0 +1,123 @@
// Copyright 2015 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.
package internal
import (
"errors"
"os"
"github.com/golang/protobuf/proto"
netcontext "golang.org/x/net/context"
)
var errNotAppEngineContext = errors.New("not an App Engine context")
type CallOverrideFunc func(ctx netcontext.Context, service, method string, in, out proto.Message) error
var callOverrideKey = "holds []CallOverrideFunc"
func WithCallOverride(ctx netcontext.Context, f CallOverrideFunc) netcontext.Context {
// We avoid appending to any existing call override
// so we don't risk overwriting a popped stack below.
var cofs []CallOverrideFunc
if uf, ok := ctx.Value(&callOverrideKey).([]CallOverrideFunc); ok {
cofs = append(cofs, uf...)
}
cofs = append(cofs, f)
return netcontext.WithValue(ctx, &callOverrideKey, cofs)
}
func callOverrideFromContext(ctx netcontext.Context) (CallOverrideFunc, netcontext.Context, bool) {
cofs, _ := ctx.Value(&callOverrideKey).([]CallOverrideFunc)
if len(cofs) == 0 {
return nil, nil, false
}
// We found a list of overrides; grab the last, and reconstitute a
// context that will hide it.
f := cofs[len(cofs)-1]
ctx = netcontext.WithValue(ctx, &callOverrideKey, cofs[:len(cofs)-1])
return f, ctx, true
}
type logOverrideFunc func(level int64, format string, args ...interface{})
var logOverrideKey = "holds a logOverrideFunc"
func WithLogOverride(ctx netcontext.Context, f logOverrideFunc) netcontext.Context {
return netcontext.WithValue(ctx, &logOverrideKey, f)
}
var appIDOverrideKey = "holds a string, being the full app ID"
func WithAppIDOverride(ctx netcontext.Context, appID string) netcontext.Context {
return netcontext.WithValue(ctx, &appIDOverrideKey, appID)
}
var namespaceKey = "holds the namespace string"
func withNamespace(ctx netcontext.Context, ns string) netcontext.Context {
return netcontext.WithValue(ctx, &namespaceKey, ns)
}
func NamespaceFromContext(ctx netcontext.Context) string {
// If there's no namespace, return the empty string.
ns, _ := ctx.Value(&namespaceKey).(string)
return ns
}
// FullyQualifiedAppID returns the fully-qualified application ID.
// This may contain a partition prefix (e.g. "s~" for High Replication apps),
// or a domain prefix (e.g. "example.com:").
func FullyQualifiedAppID(ctx netcontext.Context) string {
if id, ok := ctx.Value(&appIDOverrideKey).(string); ok {
return id
}
return fullyQualifiedAppID(ctx)
}
func Logf(ctx netcontext.Context, level int64, format string, args ...interface{}) {
if f, ok := ctx.Value(&logOverrideKey).(logOverrideFunc); ok {
f(level, format, args...)
return
}
c := fromContext(ctx)
if c == nil {
panic(errNotAppEngineContext)
}
logf(c, level, format, args...)
}
// NamespacedContext wraps a Context to support namespaces.
func NamespacedContext(ctx netcontext.Context, namespace string) netcontext.Context {
return withNamespace(ctx, namespace)
}
// SetTestEnv sets the env variables for testing background ticket in Flex.
func SetTestEnv() func() {
var environ = []struct {
key, value string
}{
{"GAE_LONG_APP_ID", "my-app-id"},
{"GAE_MINOR_VERSION", "067924799508853122"},
{"GAE_MODULE_INSTANCE", "0"},
{"GAE_MODULE_NAME", "default"},
{"GAE_MODULE_VERSION", "20150612t184001"},
}
for _, v := range environ {
old := os.Getenv(v.key)
os.Setenv(v.key, v.value)
v.value = old
}
return func() { // Restore old environment after the test completes.
for _, v := range environ {
if v.value == "" {
os.Unsetenv(v.key)
continue
}
os.Setenv(v.key, v.value)
}
}
}

View file

@ -0,0 +1,682 @@
// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.
// +build !appengine
// +build !go1.7
package internal
import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"log"
"net"
"net/http"
"net/url"
"os"
"runtime"
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
"github.com/golang/protobuf/proto"
netcontext "golang.org/x/net/context"
basepb "google.golang.org/appengine/internal/base"
logpb "google.golang.org/appengine/internal/log"
remotepb "google.golang.org/appengine/internal/remote_api"
)
const (
apiPath = "/rpc_http"
defaultTicketSuffix = "/default.20150612t184001.0"
)
var (
// Incoming headers.
ticketHeader = http.CanonicalHeaderKey("X-AppEngine-API-Ticket")
dapperHeader = http.CanonicalHeaderKey("X-Google-DapperTraceInfo")
traceHeader = http.CanonicalHeaderKey("X-Cloud-Trace-Context")
curNamespaceHeader = http.CanonicalHeaderKey("X-AppEngine-Current-Namespace")
userIPHeader = http.CanonicalHeaderKey("X-AppEngine-User-IP")
remoteAddrHeader = http.CanonicalHeaderKey("X-AppEngine-Remote-Addr")
// Outgoing headers.
apiEndpointHeader = http.CanonicalHeaderKey("X-Google-RPC-Service-Endpoint")
apiEndpointHeaderValue = []string{"app-engine-apis"}
apiMethodHeader = http.CanonicalHeaderKey("X-Google-RPC-Service-Method")
apiMethodHeaderValue = []string{"/VMRemoteAPI.CallRemoteAPI"}
apiDeadlineHeader = http.CanonicalHeaderKey("X-Google-RPC-Service-Deadline")
apiContentType = http.CanonicalHeaderKey("Content-Type")
apiContentTypeValue = []string{"application/octet-stream"}
logFlushHeader = http.CanonicalHeaderKey("X-AppEngine-Log-Flush-Count")
apiHTTPClient = &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
Dial: limitDial,
},
}
defaultTicketOnce sync.Once
defaultTicket string
)
func apiURL() *url.URL {
host, port := "appengine.googleapis.internal", "10001"
if h := os.Getenv("API_HOST"); h != "" {
host = h
}
if p := os.Getenv("API_PORT"); p != "" {
port = p
}
return &url.URL{
Scheme: "http",
Host: host + ":" + port,
Path: apiPath,
}
}
func handleHTTP(w http.ResponseWriter, r *http.Request) {
c := &context{
req: r,
outHeader: w.Header(),
apiURL: apiURL(),
}
stopFlushing := make(chan int)
ctxs.Lock()
ctxs.m[r] = c
ctxs.Unlock()
defer func() {
ctxs.Lock()
delete(ctxs.m, r)
ctxs.Unlock()
}()
// Patch up RemoteAddr so it looks reasonable.
if addr := r.Header.Get(userIPHeader); addr != "" {
r.RemoteAddr = addr
} else if addr = r.Header.Get(remoteAddrHeader); addr != "" {
r.RemoteAddr = addr
} else {
// Should not normally reach here, but pick a sensible default anyway.
r.RemoteAddr = "127.0.0.1"
}
// The address in the headers will most likely be of these forms:
// 123.123.123.123
// 2001:db8::1
// net/http.Request.RemoteAddr is specified to be in "IP:port" form.
if _, _, err := net.SplitHostPort(r.RemoteAddr); err != nil {
// Assume the remote address is only a host; add a default port.
r.RemoteAddr = net.JoinHostPort(r.RemoteAddr, "80")
}
// Start goroutine responsible for flushing app logs.
// This is done after adding c to ctx.m (and stopped before removing it)
// because flushing logs requires making an API call.
go c.logFlusher(stopFlushing)
executeRequestSafely(c, r)
c.outHeader = nil // make sure header changes aren't respected any more
stopFlushing <- 1 // any logging beyond this point will be dropped
// Flush any pending logs asynchronously.
c.pendingLogs.Lock()
flushes := c.pendingLogs.flushes
if len(c.pendingLogs.lines) > 0 {
flushes++
}
c.pendingLogs.Unlock()
go c.flushLog(false)
w.Header().Set(logFlushHeader, strconv.Itoa(flushes))
// Avoid nil Write call if c.Write is never called.
if c.outCode != 0 {
w.WriteHeader(c.outCode)
}
if c.outBody != nil {
w.Write(c.outBody)
}
}
func executeRequestSafely(c *context, r *http.Request) {
defer func() {
if x := recover(); x != nil {
logf(c, 4, "%s", renderPanic(x)) // 4 == critical
c.outCode = 500
}
}()
http.DefaultServeMux.ServeHTTP(c, r)
}
func renderPanic(x interface{}) string {
buf := make([]byte, 16<<10) // 16 KB should be plenty
buf = buf[:runtime.Stack(buf, false)]
// Remove the first few stack frames:
// this func
// the recover closure in the caller
// That will root the stack trace at the site of the panic.
const (
skipStart = "internal.renderPanic"
skipFrames = 2
)
start := bytes.Index(buf, []byte(skipStart))
p := start
for i := 0; i < skipFrames*2 && p+1 < len(buf); i++ {
p = bytes.IndexByte(buf[p+1:], '\n') + p + 1
if p < 0 {
break
}
}
if p >= 0 {
// buf[start:p+1] is the block to remove.
// Copy buf[p+1:] over buf[start:] and shrink buf.
copy(buf[start:], buf[p+1:])
buf = buf[:len(buf)-(p+1-start)]
}
// Add panic heading.
head := fmt.Sprintf("panic: %v\n\n", x)
if len(head) > len(buf) {
// Extremely unlikely to happen.
return head
}
copy(buf[len(head):], buf)
copy(buf, head)
return string(buf)
}
var ctxs = struct {
sync.Mutex
m map[*http.Request]*context
bg *context // background context, lazily initialized
// dec is used by tests to decorate the netcontext.Context returned
// for a given request. This allows tests to add overrides (such as
// WithAppIDOverride) to the context. The map is nil outside tests.
dec map[*http.Request]func(netcontext.Context) netcontext.Context
}{
m: make(map[*http.Request]*context),
}
// context represents the context of an in-flight HTTP request.
// It implements the appengine.Context and http.ResponseWriter interfaces.
type context struct {
req *http.Request
outCode int
outHeader http.Header
outBody []byte
pendingLogs struct {
sync.Mutex
lines []*logpb.UserAppLogLine
flushes int
}
apiURL *url.URL
}
var contextKey = "holds a *context"
// fromContext returns the App Engine context or nil if ctx is not
// derived from an App Engine context.
func fromContext(ctx netcontext.Context) *context {
c, _ := ctx.Value(&contextKey).(*context)
return c
}
func withContext(parent netcontext.Context, c *context) netcontext.Context {
ctx := netcontext.WithValue(parent, &contextKey, c)
if ns := c.req.Header.Get(curNamespaceHeader); ns != "" {
ctx = withNamespace(ctx, ns)
}
return ctx
}
func toContext(c *context) netcontext.Context {
return withContext(netcontext.Background(), c)
}
func IncomingHeaders(ctx netcontext.Context) http.Header {
if c := fromContext(ctx); c != nil {
return c.req.Header
}
return nil
}
func ReqContext(req *http.Request) netcontext.Context {
return WithContext(netcontext.Background(), req)
}
func WithContext(parent netcontext.Context, req *http.Request) netcontext.Context {
ctxs.Lock()
c := ctxs.m[req]
d := ctxs.dec[req]
ctxs.Unlock()
if d != nil {
parent = d(parent)
}
if c == nil {
// Someone passed in an http.Request that is not in-flight.
// We panic here rather than panicking at a later point
// so that stack traces will be more sensible.
log.Panic("appengine: NewContext passed an unknown http.Request")
}
return withContext(parent, c)
}
// DefaultTicket returns a ticket used for background context or dev_appserver.
func DefaultTicket() string {
defaultTicketOnce.Do(func() {
if IsDevAppServer() {
defaultTicket = "testapp" + defaultTicketSuffix
return
}
appID := partitionlessAppID()
escAppID := strings.Replace(strings.Replace(appID, ":", "_", -1), ".", "_", -1)
majVersion := VersionID(nil)
if i := strings.Index(majVersion, "."); i > 0 {
majVersion = majVersion[:i]
}
defaultTicket = fmt.Sprintf("%s/%s.%s.%s", escAppID, ModuleName(nil), majVersion, InstanceID())
})
return defaultTicket
}
func BackgroundContext() netcontext.Context {
ctxs.Lock()
defer ctxs.Unlock()
if ctxs.bg != nil {
return toContext(ctxs.bg)
}
// Compute background security ticket.
ticket := DefaultTicket()
ctxs.bg = &context{
req: &http.Request{
Header: http.Header{
ticketHeader: []string{ticket},
},
},
apiURL: apiURL(),
}
// TODO(dsymonds): Wire up the shutdown handler to do a final flush.
go ctxs.bg.logFlusher(make(chan int))
return toContext(ctxs.bg)
}
// RegisterTestRequest registers the HTTP request req for testing, such that
// any API calls are sent to the provided URL. It returns a closure to delete
// the registration.
// It should only be used by aetest package.
func RegisterTestRequest(req *http.Request, apiURL *url.URL, decorate func(netcontext.Context) netcontext.Context) (*http.Request, func()) {
c := &context{
req: req,
apiURL: apiURL,
}
ctxs.Lock()
defer ctxs.Unlock()
if _, ok := ctxs.m[req]; ok {
log.Panic("req already associated with context")
}
if _, ok := ctxs.dec[req]; ok {
log.Panic("req already associated with context")
}
if ctxs.dec == nil {
ctxs.dec = make(map[*http.Request]func(netcontext.Context) netcontext.Context)
}
ctxs.m[req] = c
ctxs.dec[req] = decorate
return req, func() {
ctxs.Lock()
delete(ctxs.m, req)
delete(ctxs.dec, req)
ctxs.Unlock()
}
}
var errTimeout = &CallError{
Detail: "Deadline exceeded",
Code: int32(remotepb.RpcError_CANCELLED),
Timeout: true,
}
func (c *context) Header() http.Header { return c.outHeader }
// Copied from $GOROOT/src/pkg/net/http/transfer.go. Some response status
// codes do not permit a response body (nor response entity headers such as
// Content-Length, Content-Type, etc).
func bodyAllowedForStatus(status int) bool {
switch {
case status >= 100 && status <= 199:
return false
case status == 204:
return false
case status == 304:
return false
}
return true
}
func (c *context) Write(b []byte) (int, error) {
if c.outCode == 0 {
c.WriteHeader(http.StatusOK)
}
if len(b) > 0 && !bodyAllowedForStatus(c.outCode) {
return 0, http.ErrBodyNotAllowed
}
c.outBody = append(c.outBody, b...)
return len(b), nil
}
func (c *context) WriteHeader(code int) {
if c.outCode != 0 {
logf(c, 3, "WriteHeader called multiple times on request.") // error level
return
}
c.outCode = code
}
func (c *context) post(body []byte, timeout time.Duration) (b []byte, err error) {
hreq := &http.Request{
Method: "POST",
URL: c.apiURL,
Header: http.Header{
apiEndpointHeader: apiEndpointHeaderValue,
apiMethodHeader: apiMethodHeaderValue,
apiContentType: apiContentTypeValue,
apiDeadlineHeader: []string{strconv.FormatFloat(timeout.Seconds(), 'f', -1, 64)},
},
Body: ioutil.NopCloser(bytes.NewReader(body)),
ContentLength: int64(len(body)),
Host: c.apiURL.Host,
}
if info := c.req.Header.Get(dapperHeader); info != "" {
hreq.Header.Set(dapperHeader, info)
}
if info := c.req.Header.Get(traceHeader); info != "" {
hreq.Header.Set(traceHeader, info)
}
tr := apiHTTPClient.Transport.(*http.Transport)
var timedOut int32 // atomic; set to 1 if timed out
t := time.AfterFunc(timeout, func() {
atomic.StoreInt32(&timedOut, 1)
tr.CancelRequest(hreq)
})
defer t.Stop()
defer func() {
// Check if timeout was exceeded.
if atomic.LoadInt32(&timedOut) != 0 {
err = errTimeout
}
}()
hresp, err := apiHTTPClient.Do(hreq)
if err != nil {
return nil, &CallError{
Detail: fmt.Sprintf("service bridge HTTP failed: %v", err),
Code: int32(remotepb.RpcError_UNKNOWN),
}
}
defer hresp.Body.Close()
hrespBody, err := ioutil.ReadAll(hresp.Body)
if hresp.StatusCode != 200 {
return nil, &CallError{
Detail: fmt.Sprintf("service bridge returned HTTP %d (%q)", hresp.StatusCode, hrespBody),
Code: int32(remotepb.RpcError_UNKNOWN),
}
}
if err != nil {
return nil, &CallError{
Detail: fmt.Sprintf("service bridge response bad: %v", err),
Code: int32(remotepb.RpcError_UNKNOWN),
}
}
return hrespBody, nil
}
func Call(ctx netcontext.Context, service, method string, in, out proto.Message) error {
if ns := NamespaceFromContext(ctx); ns != "" {
if fn, ok := NamespaceMods[service]; ok {
fn(in, ns)
}
}
if f, ctx, ok := callOverrideFromContext(ctx); ok {
return f(ctx, service, method, in, out)
}
// Handle already-done contexts quickly.
select {
case <-ctx.Done():
return ctx.Err()
default:
}
c := fromContext(ctx)
if c == nil {
// Give a good error message rather than a panic lower down.
return errNotAppEngineContext
}
// Apply transaction modifications if we're in a transaction.
if t := transactionFromContext(ctx); t != nil {
if t.finished {
return errors.New("transaction context has expired")
}
applyTransaction(in, &t.transaction)
}
// Default RPC timeout is 60s.
timeout := 60 * time.Second
if deadline, ok := ctx.Deadline(); ok {
timeout = deadline.Sub(time.Now())
}
data, err := proto.Marshal(in)
if err != nil {
return err
}
ticket := c.req.Header.Get(ticketHeader)
// Use a test ticket under test environment.
if ticket == "" {
if appid := ctx.Value(&appIDOverrideKey); appid != nil {
ticket = appid.(string) + defaultTicketSuffix
}
}
// Fall back to use background ticket when the request ticket is not available in Flex or dev_appserver.
if ticket == "" {
ticket = DefaultTicket()
}
req := &remotepb.Request{
ServiceName: &service,
Method: &method,
Request: data,
RequestId: &ticket,
}
hreqBody, err := proto.Marshal(req)
if err != nil {
return err
}
hrespBody, err := c.post(hreqBody, timeout)
if err != nil {
return err
}
res := &remotepb.Response{}
if err := proto.Unmarshal(hrespBody, res); err != nil {
return err
}
if res.RpcError != nil {
ce := &CallError{
Detail: res.RpcError.GetDetail(),
Code: *res.RpcError.Code,
}
switch remotepb.RpcError_ErrorCode(ce.Code) {
case remotepb.RpcError_CANCELLED, remotepb.RpcError_DEADLINE_EXCEEDED:
ce.Timeout = true
}
return ce
}
if res.ApplicationError != nil {
return &APIError{
Service: *req.ServiceName,
Detail: res.ApplicationError.GetDetail(),
Code: *res.ApplicationError.Code,
}
}
if res.Exception != nil || res.JavaException != nil {
// This shouldn't happen, but let's be defensive.
return &CallError{
Detail: "service bridge returned exception",
Code: int32(remotepb.RpcError_UNKNOWN),
}
}
return proto.Unmarshal(res.Response, out)
}
func (c *context) Request() *http.Request {
return c.req
}
func (c *context) addLogLine(ll *logpb.UserAppLogLine) {
// Truncate long log lines.
// TODO(dsymonds): Check if this is still necessary.
const lim = 8 << 10
if len(*ll.Message) > lim {
suffix := fmt.Sprintf("...(length %d)", len(*ll.Message))
ll.Message = proto.String((*ll.Message)[:lim-len(suffix)] + suffix)
}
c.pendingLogs.Lock()
c.pendingLogs.lines = append(c.pendingLogs.lines, ll)
c.pendingLogs.Unlock()
}
var logLevelName = map[int64]string{
0: "DEBUG",
1: "INFO",
2: "WARNING",
3: "ERROR",
4: "CRITICAL",
}
func logf(c *context, level int64, format string, args ...interface{}) {
if c == nil {
panic("not an App Engine context")
}
s := fmt.Sprintf(format, args...)
s = strings.TrimRight(s, "\n") // Remove any trailing newline characters.
c.addLogLine(&logpb.UserAppLogLine{
TimestampUsec: proto.Int64(time.Now().UnixNano() / 1e3),
Level: &level,
Message: &s,
})
log.Print(logLevelName[level] + ": " + s)
}
// flushLog attempts to flush any pending logs to the appserver.
// It should not be called concurrently.
func (c *context) flushLog(force bool) (flushed bool) {
c.pendingLogs.Lock()
// Grab up to 30 MB. We can get away with up to 32 MB, but let's be cautious.
n, rem := 0, 30<<20
for ; n < len(c.pendingLogs.lines); n++ {
ll := c.pendingLogs.lines[n]
// Each log line will require about 3 bytes of overhead.
nb := proto.Size(ll) + 3
if nb > rem {
break
}
rem -= nb
}
lines := c.pendingLogs.lines[:n]
c.pendingLogs.lines = c.pendingLogs.lines[n:]
c.pendingLogs.Unlock()
if len(lines) == 0 && !force {
// Nothing to flush.
return false
}
rescueLogs := false
defer func() {
if rescueLogs {
c.pendingLogs.Lock()
c.pendingLogs.lines = append(lines, c.pendingLogs.lines...)
c.pendingLogs.Unlock()
}
}()
buf, err := proto.Marshal(&logpb.UserAppLogGroup{
LogLine: lines,
})
if err != nil {
log.Printf("internal.flushLog: marshaling UserAppLogGroup: %v", err)
rescueLogs = true
return false
}
req := &logpb.FlushRequest{
Logs: buf,
}
res := &basepb.VoidProto{}
c.pendingLogs.Lock()
c.pendingLogs.flushes++
c.pendingLogs.Unlock()
if err := Call(toContext(c), "logservice", "Flush", req, res); err != nil {
log.Printf("internal.flushLog: Flush RPC: %v", err)
rescueLogs = true
return false
}
return true
}
const (
// Log flushing parameters.
flushInterval = 1 * time.Second
forceFlushInterval = 60 * time.Second
)
func (c *context) logFlusher(stop <-chan int) {
lastFlush := time.Now()
tick := time.NewTicker(flushInterval)
for {
select {
case <-stop:
// Request finished.
tick.Stop()
return
case <-tick.C:
force := time.Now().Sub(lastFlush) > forceFlushInterval
if c.flushLog(force) {
lastFlush = time.Now()
}
}
}
}
func ContextForTesting(req *http.Request) netcontext.Context {
return toContext(&context{req: req})
}

28
vendor/google.golang.org/appengine/internal/app_id.go generated vendored Normal file
View file

@ -0,0 +1,28 @@
// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.
package internal
import (
"strings"
)
func parseFullAppID(appid string) (partition, domain, displayID string) {
if i := strings.Index(appid, "~"); i != -1 {
partition, appid = appid[:i], appid[i+1:]
}
if i := strings.Index(appid, ":"); i != -1 {
domain, appid = appid[:i], appid[i+1:]
}
return partition, domain, appid
}
// appID returns "appid" or "domain.com:appid".
func appID(fullAppID string) string {
_, dom, dis := parseFullAppID(fullAppID)
if dom != "" {
return dom + ":" + dis
}
return dis
}

View file

@ -0,0 +1,308 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: google.golang.org/appengine/internal/base/api_base.proto
package base
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type StringProto struct {
Value *string `protobuf:"bytes,1,req,name=value" json:"value,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *StringProto) Reset() { *m = StringProto{} }
func (m *StringProto) String() string { return proto.CompactTextString(m) }
func (*StringProto) ProtoMessage() {}
func (*StringProto) Descriptor() ([]byte, []int) {
return fileDescriptor_api_base_9d49f8792e0c1140, []int{0}
}
func (m *StringProto) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StringProto.Unmarshal(m, b)
}
func (m *StringProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_StringProto.Marshal(b, m, deterministic)
}
func (dst *StringProto) XXX_Merge(src proto.Message) {
xxx_messageInfo_StringProto.Merge(dst, src)
}
func (m *StringProto) XXX_Size() int {
return xxx_messageInfo_StringProto.Size(m)
}
func (m *StringProto) XXX_DiscardUnknown() {
xxx_messageInfo_StringProto.DiscardUnknown(m)
}
var xxx_messageInfo_StringProto proto.InternalMessageInfo
func (m *StringProto) GetValue() string {
if m != nil && m.Value != nil {
return *m.Value
}
return ""
}
type Integer32Proto struct {
Value *int32 `protobuf:"varint,1,req,name=value" json:"value,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Integer32Proto) Reset() { *m = Integer32Proto{} }
func (m *Integer32Proto) String() string { return proto.CompactTextString(m) }
func (*Integer32Proto) ProtoMessage() {}
func (*Integer32Proto) Descriptor() ([]byte, []int) {
return fileDescriptor_api_base_9d49f8792e0c1140, []int{1}
}
func (m *Integer32Proto) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Integer32Proto.Unmarshal(m, b)
}
func (m *Integer32Proto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Integer32Proto.Marshal(b, m, deterministic)
}
func (dst *Integer32Proto) XXX_Merge(src proto.Message) {
xxx_messageInfo_Integer32Proto.Merge(dst, src)
}
func (m *Integer32Proto) XXX_Size() int {
return xxx_messageInfo_Integer32Proto.Size(m)
}
func (m *Integer32Proto) XXX_DiscardUnknown() {
xxx_messageInfo_Integer32Proto.DiscardUnknown(m)
}
var xxx_messageInfo_Integer32Proto proto.InternalMessageInfo
func (m *Integer32Proto) GetValue() int32 {
if m != nil && m.Value != nil {
return *m.Value
}
return 0
}
type Integer64Proto struct {
Value *int64 `protobuf:"varint,1,req,name=value" json:"value,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Integer64Proto) Reset() { *m = Integer64Proto{} }
func (m *Integer64Proto) String() string { return proto.CompactTextString(m) }
func (*Integer64Proto) ProtoMessage() {}
func (*Integer64Proto) Descriptor() ([]byte, []int) {
return fileDescriptor_api_base_9d49f8792e0c1140, []int{2}
}
func (m *Integer64Proto) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Integer64Proto.Unmarshal(m, b)
}
func (m *Integer64Proto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Integer64Proto.Marshal(b, m, deterministic)
}
func (dst *Integer64Proto) XXX_Merge(src proto.Message) {
xxx_messageInfo_Integer64Proto.Merge(dst, src)
}
func (m *Integer64Proto) XXX_Size() int {
return xxx_messageInfo_Integer64Proto.Size(m)
}
func (m *Integer64Proto) XXX_DiscardUnknown() {
xxx_messageInfo_Integer64Proto.DiscardUnknown(m)
}
var xxx_messageInfo_Integer64Proto proto.InternalMessageInfo
func (m *Integer64Proto) GetValue() int64 {
if m != nil && m.Value != nil {
return *m.Value
}
return 0
}
type BoolProto struct {
Value *bool `protobuf:"varint,1,req,name=value" json:"value,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *BoolProto) Reset() { *m = BoolProto{} }
func (m *BoolProto) String() string { return proto.CompactTextString(m) }
func (*BoolProto) ProtoMessage() {}
func (*BoolProto) Descriptor() ([]byte, []int) {
return fileDescriptor_api_base_9d49f8792e0c1140, []int{3}
}
func (m *BoolProto) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_BoolProto.Unmarshal(m, b)
}
func (m *BoolProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_BoolProto.Marshal(b, m, deterministic)
}
func (dst *BoolProto) XXX_Merge(src proto.Message) {
xxx_messageInfo_BoolProto.Merge(dst, src)
}
func (m *BoolProto) XXX_Size() int {
return xxx_messageInfo_BoolProto.Size(m)
}
func (m *BoolProto) XXX_DiscardUnknown() {
xxx_messageInfo_BoolProto.DiscardUnknown(m)
}
var xxx_messageInfo_BoolProto proto.InternalMessageInfo
func (m *BoolProto) GetValue() bool {
if m != nil && m.Value != nil {
return *m.Value
}
return false
}
type DoubleProto struct {
Value *float64 `protobuf:"fixed64,1,req,name=value" json:"value,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *DoubleProto) Reset() { *m = DoubleProto{} }
func (m *DoubleProto) String() string { return proto.CompactTextString(m) }
func (*DoubleProto) ProtoMessage() {}
func (*DoubleProto) Descriptor() ([]byte, []int) {
return fileDescriptor_api_base_9d49f8792e0c1140, []int{4}
}
func (m *DoubleProto) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_DoubleProto.Unmarshal(m, b)
}
func (m *DoubleProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_DoubleProto.Marshal(b, m, deterministic)
}
func (dst *DoubleProto) XXX_Merge(src proto.Message) {
xxx_messageInfo_DoubleProto.Merge(dst, src)
}
func (m *DoubleProto) XXX_Size() int {
return xxx_messageInfo_DoubleProto.Size(m)
}
func (m *DoubleProto) XXX_DiscardUnknown() {
xxx_messageInfo_DoubleProto.DiscardUnknown(m)
}
var xxx_messageInfo_DoubleProto proto.InternalMessageInfo
func (m *DoubleProto) GetValue() float64 {
if m != nil && m.Value != nil {
return *m.Value
}
return 0
}
type BytesProto struct {
Value []byte `protobuf:"bytes,1,req,name=value" json:"value,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *BytesProto) Reset() { *m = BytesProto{} }
func (m *BytesProto) String() string { return proto.CompactTextString(m) }
func (*BytesProto) ProtoMessage() {}
func (*BytesProto) Descriptor() ([]byte, []int) {
return fileDescriptor_api_base_9d49f8792e0c1140, []int{5}
}
func (m *BytesProto) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_BytesProto.Unmarshal(m, b)
}
func (m *BytesProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_BytesProto.Marshal(b, m, deterministic)
}
func (dst *BytesProto) XXX_Merge(src proto.Message) {
xxx_messageInfo_BytesProto.Merge(dst, src)
}
func (m *BytesProto) XXX_Size() int {
return xxx_messageInfo_BytesProto.Size(m)
}
func (m *BytesProto) XXX_DiscardUnknown() {
xxx_messageInfo_BytesProto.DiscardUnknown(m)
}
var xxx_messageInfo_BytesProto proto.InternalMessageInfo
func (m *BytesProto) GetValue() []byte {
if m != nil {
return m.Value
}
return nil
}
type VoidProto struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *VoidProto) Reset() { *m = VoidProto{} }
func (m *VoidProto) String() string { return proto.CompactTextString(m) }
func (*VoidProto) ProtoMessage() {}
func (*VoidProto) Descriptor() ([]byte, []int) {
return fileDescriptor_api_base_9d49f8792e0c1140, []int{6}
}
func (m *VoidProto) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_VoidProto.Unmarshal(m, b)
}
func (m *VoidProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_VoidProto.Marshal(b, m, deterministic)
}
func (dst *VoidProto) XXX_Merge(src proto.Message) {
xxx_messageInfo_VoidProto.Merge(dst, src)
}
func (m *VoidProto) XXX_Size() int {
return xxx_messageInfo_VoidProto.Size(m)
}
func (m *VoidProto) XXX_DiscardUnknown() {
xxx_messageInfo_VoidProto.DiscardUnknown(m)
}
var xxx_messageInfo_VoidProto proto.InternalMessageInfo
func init() {
proto.RegisterType((*StringProto)(nil), "appengine.base.StringProto")
proto.RegisterType((*Integer32Proto)(nil), "appengine.base.Integer32Proto")
proto.RegisterType((*Integer64Proto)(nil), "appengine.base.Integer64Proto")
proto.RegisterType((*BoolProto)(nil), "appengine.base.BoolProto")
proto.RegisterType((*DoubleProto)(nil), "appengine.base.DoubleProto")
proto.RegisterType((*BytesProto)(nil), "appengine.base.BytesProto")
proto.RegisterType((*VoidProto)(nil), "appengine.base.VoidProto")
}
func init() {
proto.RegisterFile("google.golang.org/appengine/internal/base/api_base.proto", fileDescriptor_api_base_9d49f8792e0c1140)
}
var fileDescriptor_api_base_9d49f8792e0c1140 = []byte{
// 199 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0xcf, 0x3f, 0x4b, 0xc6, 0x30,
0x10, 0x06, 0x70, 0x5a, 0xad, 0xb4, 0x57, 0xe9, 0x20, 0x0e, 0x1d, 0xb5, 0x05, 0x71, 0x4a, 0x40,
0x45, 0x9c, 0x83, 0x8b, 0x9b, 0x28, 0x38, 0xb8, 0x48, 0x8a, 0xc7, 0x11, 0x08, 0xb9, 0x90, 0xa6,
0x82, 0xdf, 0x5e, 0xda, 0xd2, 0xfa, 0xc2, 0x9b, 0xed, 0xfe, 0xfc, 0xe0, 0xe1, 0x81, 0x27, 0x62,
0x26, 0x8b, 0x82, 0xd8, 0x6a, 0x47, 0x82, 0x03, 0x49, 0xed, 0x3d, 0x3a, 0x32, 0x0e, 0xa5, 0x71,
0x11, 0x83, 0xd3, 0x56, 0x0e, 0x7a, 0x44, 0xa9, 0xbd, 0xf9, 0x9a, 0x07, 0xe1, 0x03, 0x47, 0xbe,
0x68, 0x76, 0x27, 0xe6, 0x6b, 0xd7, 0x43, 0xfd, 0x1e, 0x83, 0x71, 0xf4, 0xba, 0xbc, 0x2f, 0xa1,
0xf8, 0xd1, 0x76, 0xc2, 0x36, 0xbb, 0xca, 0x6f, 0xab, 0xb7, 0x75, 0xe9, 0x6e, 0xa0, 0x79, 0x71,
0x11, 0x09, 0xc3, 0xfd, 0x5d, 0xc2, 0x15, 0xc7, 0xee, 0xf1, 0x21, 0xe1, 0x4e, 0x36, 0x77, 0x0d,
0x95, 0x62, 0xb6, 0x09, 0x52, 0x6e, 0xa4, 0x87, 0xfa, 0x99, 0xa7, 0xc1, 0x62, 0x02, 0x65, 0xff,
0x79, 0xa0, 0x7e, 0x23, 0x8e, 0xab, 0x69, 0x0f, 0xcd, 0xb9, 0xca, 0xcb, 0xdd, 0xd5, 0x50, 0x7d,
0xb0, 0xf9, 0x5e, 0x98, 0x3a, 0xfb, 0x3c, 0x9d, 0x9b, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0xba,
0x37, 0x25, 0xea, 0x44, 0x01, 0x00, 0x00,
}

View file

@ -0,0 +1,33 @@
// Built-in base types for API calls. Primarily useful as return types.
syntax = "proto2";
option go_package = "base";
package appengine.base;
message StringProto {
required string value = 1;
}
message Integer32Proto {
required int32 value = 1;
}
message Integer64Proto {
required int64 value = 1;
}
message BoolProto {
required bool value = 1;
}
message DoubleProto {
required double value = 1;
}
message BytesProto {
required bytes value = 1 [ctype=CORD];
}
message VoidProto {
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,551 @@
syntax = "proto2";
option go_package = "datastore";
package appengine;
message Action{}
message PropertyValue {
optional int64 int64Value = 1;
optional bool booleanValue = 2;
optional string stringValue = 3;
optional double doubleValue = 4;
optional group PointValue = 5 {
required double x = 6;
required double y = 7;
}
optional group UserValue = 8 {
required string email = 9;
required string auth_domain = 10;
optional string nickname = 11;
optional string federated_identity = 21;
optional string federated_provider = 22;
}
optional group ReferenceValue = 12 {
required string app = 13;
optional string name_space = 20;
repeated group PathElement = 14 {
required string type = 15;
optional int64 id = 16;
optional string name = 17;
}
}
}
message Property {
enum Meaning {
NO_MEANING = 0;
BLOB = 14;
TEXT = 15;
BYTESTRING = 16;
ATOM_CATEGORY = 1;
ATOM_LINK = 2;
ATOM_TITLE = 3;
ATOM_CONTENT = 4;
ATOM_SUMMARY = 5;
ATOM_AUTHOR = 6;
GD_WHEN = 7;
GD_EMAIL = 8;
GEORSS_POINT = 9;
GD_IM = 10;
GD_PHONENUMBER = 11;
GD_POSTALADDRESS = 12;
GD_RATING = 13;
BLOBKEY = 17;
ENTITY_PROTO = 19;
INDEX_VALUE = 18;
};
optional Meaning meaning = 1 [default = NO_MEANING];
optional string meaning_uri = 2;
required string name = 3;
required PropertyValue value = 5;
required bool multiple = 4;
optional bool searchable = 6 [default=false];
enum FtsTokenizationOption {
HTML = 1;
ATOM = 2;
}
optional FtsTokenizationOption fts_tokenization_option = 8;
optional string locale = 9 [default = "en"];
}
message Path {
repeated group Element = 1 {
required string type = 2;
optional int64 id = 3;
optional string name = 4;
}
}
message Reference {
required string app = 13;
optional string name_space = 20;
required Path path = 14;
}
message User {
required string email = 1;
required string auth_domain = 2;
optional string nickname = 3;
optional string federated_identity = 6;
optional string federated_provider = 7;
}
message EntityProto {
required Reference key = 13;
required Path entity_group = 16;
optional User owner = 17;
enum Kind {
GD_CONTACT = 1;
GD_EVENT = 2;
GD_MESSAGE = 3;
}
optional Kind kind = 4;
optional string kind_uri = 5;
repeated Property property = 14;
repeated Property raw_property = 15;
optional int32 rank = 18;
}
message CompositeProperty {
required int64 index_id = 1;
repeated string value = 2;
}
message Index {
required string entity_type = 1;
required bool ancestor = 5;
repeated group Property = 2 {
required string name = 3;
enum Direction {
ASCENDING = 1;
DESCENDING = 2;
}
optional Direction direction = 4 [default = ASCENDING];
}
}
message CompositeIndex {
required string app_id = 1;
required int64 id = 2;
required Index definition = 3;
enum State {
WRITE_ONLY = 1;
READ_WRITE = 2;
DELETED = 3;
ERROR = 4;
}
required State state = 4;
optional bool only_use_if_required = 6 [default = false];
}
message IndexPostfix {
message IndexValue {
required string property_name = 1;
required PropertyValue value = 2;
}
repeated IndexValue index_value = 1;
optional Reference key = 2;
optional bool before = 3 [default=true];
}
message IndexPosition {
optional string key = 1;
optional bool before = 2 [default=true];
}
message Snapshot {
enum Status {
INACTIVE = 0;
ACTIVE = 1;
}
required int64 ts = 1;
}
message InternalHeader {
optional string qos = 1;
}
message Transaction {
optional InternalHeader header = 4;
required fixed64 handle = 1;
required string app = 2;
optional bool mark_changes = 3 [default = false];
}
message Query {
optional InternalHeader header = 39;
required string app = 1;
optional string name_space = 29;
optional string kind = 3;
optional Reference ancestor = 17;
repeated group Filter = 4 {
enum Operator {
LESS_THAN = 1;
LESS_THAN_OR_EQUAL = 2;
GREATER_THAN = 3;
GREATER_THAN_OR_EQUAL = 4;
EQUAL = 5;
IN = 6;
EXISTS = 7;
}
required Operator op = 6;
repeated Property property = 14;
}
optional string search_query = 8;
repeated group Order = 9 {
enum Direction {
ASCENDING = 1;
DESCENDING = 2;
}
required string property = 10;
optional Direction direction = 11 [default = ASCENDING];
}
enum Hint {
ORDER_FIRST = 1;
ANCESTOR_FIRST = 2;
FILTER_FIRST = 3;
}
optional Hint hint = 18;
optional int32 count = 23;
optional int32 offset = 12 [default = 0];
optional int32 limit = 16;
optional CompiledCursor compiled_cursor = 30;
optional CompiledCursor end_compiled_cursor = 31;
repeated CompositeIndex composite_index = 19;
optional bool require_perfect_plan = 20 [default = false];
optional bool keys_only = 21 [default = false];
optional Transaction transaction = 22;
optional bool compile = 25 [default = false];
optional int64 failover_ms = 26;
optional bool strong = 32;
repeated string property_name = 33;
repeated string group_by_property_name = 34;
optional bool distinct = 24;
optional int64 min_safe_time_seconds = 35;
repeated string safe_replica_name = 36;
optional bool persist_offset = 37 [default=false];
}
message CompiledQuery {
required group PrimaryScan = 1 {
optional string index_name = 2;
optional string start_key = 3;
optional bool start_inclusive = 4;
optional string end_key = 5;
optional bool end_inclusive = 6;
repeated string start_postfix_value = 22;
repeated string end_postfix_value = 23;
optional int64 end_unapplied_log_timestamp_us = 19;
}
repeated group MergeJoinScan = 7 {
required string index_name = 8;
repeated string prefix_value = 9;
optional bool value_prefix = 20 [default=false];
}
optional Index index_def = 21;
optional int32 offset = 10 [default = 0];
optional int32 limit = 11;
required bool keys_only = 12;
repeated string property_name = 24;
optional int32 distinct_infix_size = 25;
optional group EntityFilter = 13 {
optional bool distinct = 14 [default=false];
optional string kind = 17;
optional Reference ancestor = 18;
}
}
message CompiledCursor {
optional group Position = 2 {
optional string start_key = 27;
repeated group IndexValue = 29 {
optional string property = 30;
required PropertyValue value = 31;
}
optional Reference key = 32;
optional bool start_inclusive = 28 [default=true];
}
}
message Cursor {
required fixed64 cursor = 1;
optional string app = 2;
}
message Error {
enum ErrorCode {
BAD_REQUEST = 1;
CONCURRENT_TRANSACTION = 2;
INTERNAL_ERROR = 3;
NEED_INDEX = 4;
TIMEOUT = 5;
PERMISSION_DENIED = 6;
BIGTABLE_ERROR = 7;
COMMITTED_BUT_STILL_APPLYING = 8;
CAPABILITY_DISABLED = 9;
TRY_ALTERNATE_BACKEND = 10;
SAFE_TIME_TOO_OLD = 11;
}
}
message Cost {
optional int32 index_writes = 1;
optional int32 index_write_bytes = 2;
optional int32 entity_writes = 3;
optional int32 entity_write_bytes = 4;
optional group CommitCost = 5 {
optional int32 requested_entity_puts = 6;
optional int32 requested_entity_deletes = 7;
};
optional int32 approximate_storage_delta = 8;
optional int32 id_sequence_updates = 9;
}
message GetRequest {
optional InternalHeader header = 6;
repeated Reference key = 1;
optional Transaction transaction = 2;
optional int64 failover_ms = 3;
optional bool strong = 4;
optional bool allow_deferred = 5 [default=false];
}
message GetResponse {
repeated group Entity = 1 {
optional EntityProto entity = 2;
optional Reference key = 4;
optional int64 version = 3;
}
repeated Reference deferred = 5;
optional bool in_order = 6 [default=true];
}
message PutRequest {
optional InternalHeader header = 11;
repeated EntityProto entity = 1;
optional Transaction transaction = 2;
repeated CompositeIndex composite_index = 3;
optional bool trusted = 4 [default = false];
optional bool force = 7 [default = false];
optional bool mark_changes = 8 [default = false];
repeated Snapshot snapshot = 9;
enum AutoIdPolicy {
CURRENT = 0;
SEQUENTIAL = 1;
}
optional AutoIdPolicy auto_id_policy = 10 [default = CURRENT];
}
message PutResponse {
repeated Reference key = 1;
optional Cost cost = 2;
repeated int64 version = 3;
}
message TouchRequest {
optional InternalHeader header = 10;
repeated Reference key = 1;
repeated CompositeIndex composite_index = 2;
optional bool force = 3 [default = false];
repeated Snapshot snapshot = 9;
}
message TouchResponse {
optional Cost cost = 1;
}
message DeleteRequest {
optional InternalHeader header = 10;
repeated Reference key = 6;
optional Transaction transaction = 5;
optional bool trusted = 4 [default = false];
optional bool force = 7 [default = false];
optional bool mark_changes = 8 [default = false];
repeated Snapshot snapshot = 9;
}
message DeleteResponse {
optional Cost cost = 1;
repeated int64 version = 3;
}
message NextRequest {
optional InternalHeader header = 5;
required Cursor cursor = 1;
optional int32 count = 2;
optional int32 offset = 4 [default = 0];
optional bool compile = 3 [default = false];
}
message QueryResult {
optional Cursor cursor = 1;
repeated EntityProto result = 2;
optional int32 skipped_results = 7;
required bool more_results = 3;
optional bool keys_only = 4;
optional bool index_only = 9;
optional bool small_ops = 10;
optional CompiledQuery compiled_query = 5;
optional CompiledCursor compiled_cursor = 6;
repeated CompositeIndex index = 8;
repeated int64 version = 11;
}
message AllocateIdsRequest {
optional InternalHeader header = 4;
optional Reference model_key = 1;
optional int64 size = 2;
optional int64 max = 3;
repeated Reference reserve = 5;
}
message AllocateIdsResponse {
required int64 start = 1;
required int64 end = 2;
optional Cost cost = 3;
}
message CompositeIndices {
repeated CompositeIndex index = 1;
}
message AddActionsRequest {
optional InternalHeader header = 3;
required Transaction transaction = 1;
repeated Action action = 2;
}
message AddActionsResponse {
}
message BeginTransactionRequest {
optional InternalHeader header = 3;
required string app = 1;
optional bool allow_multiple_eg = 2 [default = false];
optional string database_id = 4;
enum TransactionMode {
UNKNOWN = 0;
READ_ONLY = 1;
READ_WRITE = 2;
}
optional TransactionMode mode = 5 [default = UNKNOWN];
optional Transaction previous_transaction = 7;
}
message CommitResponse {
optional Cost cost = 1;
repeated group Version = 3 {
required Reference root_entity_key = 4;
required int64 version = 5;
}
}

View file

@ -0,0 +1,14 @@
// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.
package internal
import netcontext "golang.org/x/net/context"
// These functions are implementations of the wrapper functions
// in ../appengine/identity.go. See that file for commentary.
func AppID(c netcontext.Context) string {
return appID(FullyQualifiedAppID(c))
}

View file

@ -0,0 +1,57 @@
// Copyright 2015 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.
// +build appengine
package internal
import (
"appengine"
netcontext "golang.org/x/net/context"
)
func DefaultVersionHostname(ctx netcontext.Context) string {
c := fromContext(ctx)
if c == nil {
panic(errNotAppEngineContext)
}
return appengine.DefaultVersionHostname(c)
}
func Datacenter(_ netcontext.Context) string { return appengine.Datacenter() }
func ServerSoftware() string { return appengine.ServerSoftware() }
func InstanceID() string { return appengine.InstanceID() }
func IsDevAppServer() bool { return appengine.IsDevAppServer() }
func RequestID(ctx netcontext.Context) string {
c := fromContext(ctx)
if c == nil {
panic(errNotAppEngineContext)
}
return appengine.RequestID(c)
}
func ModuleName(ctx netcontext.Context) string {
c := fromContext(ctx)
if c == nil {
panic(errNotAppEngineContext)
}
return appengine.ModuleName(c)
}
func VersionID(ctx netcontext.Context) string {
c := fromContext(ctx)
if c == nil {
panic(errNotAppEngineContext)
}
return appengine.VersionID(c)
}
func fullyQualifiedAppID(ctx netcontext.Context) string {
c := fromContext(ctx)
if c == nil {
panic(errNotAppEngineContext)
}
return c.FullyQualifiedAppID()
}

View file

@ -0,0 +1,134 @@
// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.
// +build !appengine
package internal
import (
"log"
"net/http"
"os"
"strings"
netcontext "golang.org/x/net/context"
)
// These functions are implementations of the wrapper functions
// in ../appengine/identity.go. See that file for commentary.
const (
hDefaultVersionHostname = "X-AppEngine-Default-Version-Hostname"
hRequestLogId = "X-AppEngine-Request-Log-Id"
hDatacenter = "X-AppEngine-Datacenter"
)
func ctxHeaders(ctx netcontext.Context) http.Header {
c := fromContext(ctx)
if c == nil {
return nil
}
return c.Request().Header
}
func DefaultVersionHostname(ctx netcontext.Context) string {
return ctxHeaders(ctx).Get(hDefaultVersionHostname)
}
func RequestID(ctx netcontext.Context) string {
return ctxHeaders(ctx).Get(hRequestLogId)
}
func Datacenter(ctx netcontext.Context) string {
if dc := ctxHeaders(ctx).Get(hDatacenter); dc != "" {
return dc
}
// If the header isn't set, read zone from the metadata service.
// It has the format projects/[NUMERIC_PROJECT_ID]/zones/[ZONE]
zone, err := getMetadata("instance/zone")
if err != nil {
log.Printf("Datacenter: %v", err)
return ""
}
parts := strings.Split(string(zone), "/")
if len(parts) == 0 {
return ""
}
return parts[len(parts)-1]
}
func ServerSoftware() string {
// TODO(dsymonds): Remove fallback when we've verified this.
if s := os.Getenv("SERVER_SOFTWARE"); s != "" {
return s
}
if s := os.Getenv("GAE_ENV"); s != "" {
return s
}
return "Google App Engine/1.x.x"
}
// TODO(dsymonds): Remove the metadata fetches.
func ModuleName(_ netcontext.Context) string {
if s := os.Getenv("GAE_MODULE_NAME"); s != "" {
return s
}
if s := os.Getenv("GAE_SERVICE"); s != "" {
return s
}
return string(mustGetMetadata("instance/attributes/gae_backend_name"))
}
func VersionID(_ netcontext.Context) string {
if s1, s2 := os.Getenv("GAE_MODULE_VERSION"), os.Getenv("GAE_MINOR_VERSION"); s1 != "" && s2 != "" {
return s1 + "." + s2
}
if s1, s2 := os.Getenv("GAE_VERSION"), os.Getenv("GAE_DEPLOYMENT_ID"); s1 != "" && s2 != "" {
return s1 + "." + s2
}
return string(mustGetMetadata("instance/attributes/gae_backend_version")) + "." + string(mustGetMetadata("instance/attributes/gae_backend_minor_version"))
}
func InstanceID() string {
if s := os.Getenv("GAE_MODULE_INSTANCE"); s != "" {
return s
}
if s := os.Getenv("GAE_INSTANCE"); s != "" {
return s
}
return string(mustGetMetadata("instance/attributes/gae_backend_instance"))
}
func partitionlessAppID() string {
// gae_project has everything except the partition prefix.
if appID := os.Getenv("GAE_LONG_APP_ID"); appID != "" {
return appID
}
if project := os.Getenv("GOOGLE_CLOUD_PROJECT"); project != "" {
return project
}
return string(mustGetMetadata("instance/attributes/gae_project"))
}
func fullyQualifiedAppID(_ netcontext.Context) string {
if s := os.Getenv("GAE_APPLICATION"); s != "" {
return s
}
appID := partitionlessAppID()
part := os.Getenv("GAE_PARTITION")
if part == "" {
part = string(mustGetMetadata("instance/attributes/gae_partition"))
}
if part != "" {
appID = part + "~" + appID
}
return appID
}
func IsDevAppServer() bool {
return os.Getenv("RUN_WITH_DEVAPPSERVER") != ""
}

110
vendor/google.golang.org/appengine/internal/internal.go generated vendored Normal file
View file

@ -0,0 +1,110 @@
// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.
// Package internal provides support for package appengine.
//
// Programs should not use this package directly. Its API is not stable.
// Use packages appengine and appengine/* instead.
package internal
import (
"fmt"
"github.com/golang/protobuf/proto"
remotepb "google.golang.org/appengine/internal/remote_api"
)
// errorCodeMaps is a map of service name to the error code map for the service.
var errorCodeMaps = make(map[string]map[int32]string)
// RegisterErrorCodeMap is called from API implementations to register their
// error code map. This should only be called from init functions.
func RegisterErrorCodeMap(service string, m map[int32]string) {
errorCodeMaps[service] = m
}
type timeoutCodeKey struct {
service string
code int32
}
// timeoutCodes is the set of service+code pairs that represent timeouts.
var timeoutCodes = make(map[timeoutCodeKey]bool)
func RegisterTimeoutErrorCode(service string, code int32) {
timeoutCodes[timeoutCodeKey{service, code}] = true
}
// APIError is the type returned by appengine.Context's Call method
// when an API call fails in an API-specific way. This may be, for instance,
// a taskqueue API call failing with TaskQueueServiceError::UNKNOWN_QUEUE.
type APIError struct {
Service string
Detail string
Code int32 // API-specific error code
}
func (e *APIError) Error() string {
if e.Code == 0 {
if e.Detail == "" {
return "APIError <empty>"
}
return e.Detail
}
s := fmt.Sprintf("API error %d", e.Code)
if m, ok := errorCodeMaps[e.Service]; ok {
s += " (" + e.Service + ": " + m[e.Code] + ")"
} else {
// Shouldn't happen, but provide a bit more detail if it does.
s = e.Service + " " + s
}
if e.Detail != "" {
s += ": " + e.Detail
}
return s
}
func (e *APIError) IsTimeout() bool {
return timeoutCodes[timeoutCodeKey{e.Service, e.Code}]
}
// CallError is the type returned by appengine.Context's Call method when an
// API call fails in a generic way, such as RpcError::CAPABILITY_DISABLED.
type CallError struct {
Detail string
Code int32
// TODO: Remove this if we get a distinguishable error code.
Timeout bool
}
func (e *CallError) Error() string {
var msg string
switch remotepb.RpcError_ErrorCode(e.Code) {
case remotepb.RpcError_UNKNOWN:
return e.Detail
case remotepb.RpcError_OVER_QUOTA:
msg = "Over quota"
case remotepb.RpcError_CAPABILITY_DISABLED:
msg = "Capability disabled"
case remotepb.RpcError_CANCELLED:
msg = "Canceled"
default:
msg = fmt.Sprintf("Call error %d", e.Code)
}
s := msg + ": " + e.Detail
if e.Timeout {
s += " (timeout)"
}
return s
}
func (e *CallError) IsTimeout() bool {
return e.Timeout
}
// NamespaceMods is a map from API service to a function that will mutate an RPC request to attach a namespace.
// The function should be prepared to be called on the same message more than once; it should only modify the
// RPC request the first time.
var NamespaceMods = make(map[string]func(m proto.Message, namespace string))

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,150 @@
syntax = "proto2";
option go_package = "log";
package appengine;
message LogServiceError {
enum ErrorCode {
OK = 0;
INVALID_REQUEST = 1;
STORAGE_ERROR = 2;
}
}
message UserAppLogLine {
required int64 timestamp_usec = 1;
required int64 level = 2;
required string message = 3;
}
message UserAppLogGroup {
repeated UserAppLogLine log_line = 2;
}
message FlushRequest {
optional bytes logs = 1;
}
message SetStatusRequest {
required string status = 1;
}
message LogOffset {
optional bytes request_id = 1;
}
message LogLine {
required int64 time = 1;
required int32 level = 2;
required string log_message = 3;
}
message RequestLog {
required string app_id = 1;
optional string module_id = 37 [default="default"];
required string version_id = 2;
required bytes request_id = 3;
optional LogOffset offset = 35;
required string ip = 4;
optional string nickname = 5;
required int64 start_time = 6;
required int64 end_time = 7;
required int64 latency = 8;
required int64 mcycles = 9;
required string method = 10;
required string resource = 11;
required string http_version = 12;
required int32 status = 13;
required int64 response_size = 14;
optional string referrer = 15;
optional string user_agent = 16;
required string url_map_entry = 17;
required string combined = 18;
optional int64 api_mcycles = 19;
optional string host = 20;
optional double cost = 21;
optional string task_queue_name = 22;
optional string task_name = 23;
optional bool was_loading_request = 24;
optional int64 pending_time = 25;
optional int32 replica_index = 26 [default = -1];
optional bool finished = 27 [default = true];
optional bytes clone_key = 28;
repeated LogLine line = 29;
optional bool lines_incomplete = 36;
optional bytes app_engine_release = 38;
optional int32 exit_reason = 30;
optional bool was_throttled_for_time = 31;
optional bool was_throttled_for_requests = 32;
optional int64 throttled_time = 33;
optional bytes server_name = 34;
}
message LogModuleVersion {
optional string module_id = 1 [default="default"];
optional string version_id = 2;
}
message LogReadRequest {
required string app_id = 1;
repeated string version_id = 2;
repeated LogModuleVersion module_version = 19;
optional int64 start_time = 3;
optional int64 end_time = 4;
optional LogOffset offset = 5;
repeated bytes request_id = 6;
optional int32 minimum_log_level = 7;
optional bool include_incomplete = 8;
optional int64 count = 9;
optional string combined_log_regex = 14;
optional string host_regex = 15;
optional int32 replica_index = 16;
optional bool include_app_logs = 10;
optional int32 app_logs_per_request = 17;
optional bool include_host = 11;
optional bool include_all = 12;
optional bool cache_iterator = 13;
optional int32 num_shards = 18;
}
message LogReadResponse {
repeated RequestLog log = 1;
optional LogOffset offset = 2;
optional int64 last_end_time = 3;
}
message LogUsageRecord {
optional string version_id = 1;
optional int32 start_time = 2;
optional int32 end_time = 3;
optional int64 count = 4;
optional int64 total_size = 5;
optional int32 records = 6;
}
message LogUsageRequest {
required string app_id = 1;
repeated string version_id = 2;
optional int32 start_time = 3;
optional int32 end_time = 4;
optional uint32 resolution_hours = 5 [default = 1];
optional bool combine_versions = 6;
optional int32 usage_version = 7;
optional bool versions_only = 8;
}
message LogUsageResponse {
repeated LogUsageRecord usage = 1;
optional LogUsageRecord summary = 2;
}

15
vendor/google.golang.org/appengine/internal/main.go generated vendored Normal file
View file

@ -0,0 +1,15 @@
// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.
// +build appengine
package internal
import (
"appengine_internal"
)
func Main() {
appengine_internal.Main()
}

48
vendor/google.golang.org/appengine/internal/main_vm.go generated vendored Normal file
View file

@ -0,0 +1,48 @@
// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.
// +build !appengine
package internal
import (
"io"
"log"
"net/http"
"net/url"
"os"
)
func Main() {
installHealthChecker(http.DefaultServeMux)
port := "8080"
if s := os.Getenv("PORT"); s != "" {
port = s
}
host := ""
if IsDevAppServer() {
host = "127.0.0.1"
}
if err := http.ListenAndServe(host+":"+port, http.HandlerFunc(handleHTTP)); err != nil {
log.Fatalf("http.ListenAndServe: %v", err)
}
}
func installHealthChecker(mux *http.ServeMux) {
// If no health check handler has been installed by this point, add a trivial one.
const healthPath = "/_ah/health"
hreq := &http.Request{
Method: "GET",
URL: &url.URL{
Path: healthPath,
},
}
if _, pat := mux.Handler(hreq); pat != healthPath {
mux.HandleFunc(healthPath, func(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "ok")
})
}
}

View file

@ -0,0 +1,60 @@
// Copyright 2014 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.
package internal
// This file has code for accessing metadata.
//
// References:
// https://cloud.google.com/compute/docs/metadata
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
)
const (
metadataHost = "metadata"
metadataPath = "/computeMetadata/v1/"
)
var (
metadataRequestHeaders = http.Header{
"Metadata-Flavor": []string{"Google"},
}
)
// TODO(dsymonds): Do we need to support default values, like Python?
func mustGetMetadata(key string) []byte {
b, err := getMetadata(key)
if err != nil {
panic(fmt.Sprintf("Metadata fetch failed for '%s': %v", key, err))
}
return b
}
func getMetadata(key string) ([]byte, error) {
// TODO(dsymonds): May need to use url.Parse to support keys with query args.
req := &http.Request{
Method: "GET",
URL: &url.URL{
Scheme: "http",
Host: metadataHost,
Path: metadataPath + key,
},
Header: metadataRequestHeaders,
Host: metadataHost,
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return nil, fmt.Errorf("metadata server returned HTTP %d", resp.StatusCode)
}
return ioutil.ReadAll(resp.Body)
}

56
vendor/google.golang.org/appengine/internal/net.go generated vendored Normal file
View file

@ -0,0 +1,56 @@
// Copyright 2014 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.
package internal
// This file implements a network dialer that limits the number of concurrent connections.
// It is only used for API calls.
import (
"log"
"net"
"runtime"
"sync"
"time"
)
var limitSem = make(chan int, 100) // TODO(dsymonds): Use environment variable.
func limitRelease() {
// non-blocking
select {
case <-limitSem:
default:
// This should not normally happen.
log.Print("appengine: unbalanced limitSem release!")
}
}
func limitDial(network, addr string) (net.Conn, error) {
limitSem <- 1
// Dial with a timeout in case the API host is MIA.
// The connection should normally be very fast.
conn, err := net.DialTimeout(network, addr, 500*time.Millisecond)
if err != nil {
limitRelease()
return nil, err
}
lc := &limitConn{Conn: conn}
runtime.SetFinalizer(lc, (*limitConn).Close) // shouldn't usually be required
return lc, nil
}
type limitConn struct {
close sync.Once
net.Conn
}
func (lc *limitConn) Close() error {
defer lc.close.Do(func() {
limitRelease()
runtime.SetFinalizer(lc, nil)
})
return lc.Conn.Close()
}

40
vendor/google.golang.org/appengine/internal/regen.sh generated vendored Normal file
View file

@ -0,0 +1,40 @@
#!/bin/bash -e
#
# This script rebuilds the generated code for the protocol buffers.
# To run this you will need protoc and goprotobuf installed;
# see https://github.com/golang/protobuf for instructions.
PKG=google.golang.org/appengine
function die() {
echo 1>&2 $*
exit 1
}
# Sanity check that the right tools are accessible.
for tool in go protoc protoc-gen-go; do
q=$(which $tool) || die "didn't find $tool"
echo 1>&2 "$tool: $q"
done
echo -n 1>&2 "finding package dir... "
pkgdir=$(go list -f '{{.Dir}}' $PKG)
echo 1>&2 $pkgdir
base=$(echo $pkgdir | sed "s,/$PKG\$,,")
echo 1>&2 "base: $base"
cd $base
# Run protoc once per package.
for dir in $(find $PKG/internal -name '*.proto' | xargs dirname | sort | uniq); do
echo 1>&2 "* $dir"
protoc --go_out=. $dir/*.proto
done
for f in $(find $PKG/internal -name '*.pb.go'); do
# Remove proto.RegisterEnum calls.
# These cause duplicate registration panics when these packages
# are used on classic App Engine. proto.RegisterEnum only affects
# parsing the text format; we don't care about that.
# https://code.google.com/p/googleappengine/issues/detail?id=11670#c17
sed -i '/proto.RegisterEnum/d' $f
done

View file

@ -0,0 +1,361 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: google.golang.org/appengine/internal/remote_api/remote_api.proto
package remote_api
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type RpcError_ErrorCode int32
const (
RpcError_UNKNOWN RpcError_ErrorCode = 0
RpcError_CALL_NOT_FOUND RpcError_ErrorCode = 1
RpcError_PARSE_ERROR RpcError_ErrorCode = 2
RpcError_SECURITY_VIOLATION RpcError_ErrorCode = 3
RpcError_OVER_QUOTA RpcError_ErrorCode = 4
RpcError_REQUEST_TOO_LARGE RpcError_ErrorCode = 5
RpcError_CAPABILITY_DISABLED RpcError_ErrorCode = 6
RpcError_FEATURE_DISABLED RpcError_ErrorCode = 7
RpcError_BAD_REQUEST RpcError_ErrorCode = 8
RpcError_RESPONSE_TOO_LARGE RpcError_ErrorCode = 9
RpcError_CANCELLED RpcError_ErrorCode = 10
RpcError_REPLAY_ERROR RpcError_ErrorCode = 11
RpcError_DEADLINE_EXCEEDED RpcError_ErrorCode = 12
)
var RpcError_ErrorCode_name = map[int32]string{
0: "UNKNOWN",
1: "CALL_NOT_FOUND",
2: "PARSE_ERROR",
3: "SECURITY_VIOLATION",
4: "OVER_QUOTA",
5: "REQUEST_TOO_LARGE",
6: "CAPABILITY_DISABLED",
7: "FEATURE_DISABLED",
8: "BAD_REQUEST",
9: "RESPONSE_TOO_LARGE",
10: "CANCELLED",
11: "REPLAY_ERROR",
12: "DEADLINE_EXCEEDED",
}
var RpcError_ErrorCode_value = map[string]int32{
"UNKNOWN": 0,
"CALL_NOT_FOUND": 1,
"PARSE_ERROR": 2,
"SECURITY_VIOLATION": 3,
"OVER_QUOTA": 4,
"REQUEST_TOO_LARGE": 5,
"CAPABILITY_DISABLED": 6,
"FEATURE_DISABLED": 7,
"BAD_REQUEST": 8,
"RESPONSE_TOO_LARGE": 9,
"CANCELLED": 10,
"REPLAY_ERROR": 11,
"DEADLINE_EXCEEDED": 12,
}
func (x RpcError_ErrorCode) Enum() *RpcError_ErrorCode {
p := new(RpcError_ErrorCode)
*p = x
return p
}
func (x RpcError_ErrorCode) String() string {
return proto.EnumName(RpcError_ErrorCode_name, int32(x))
}
func (x *RpcError_ErrorCode) UnmarshalJSON(data []byte) error {
value, err := proto.UnmarshalJSONEnum(RpcError_ErrorCode_value, data, "RpcError_ErrorCode")
if err != nil {
return err
}
*x = RpcError_ErrorCode(value)
return nil
}
func (RpcError_ErrorCode) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_remote_api_1978114ec33a273d, []int{2, 0}
}
type Request struct {
ServiceName *string `protobuf:"bytes,2,req,name=service_name,json=serviceName" json:"service_name,omitempty"`
Method *string `protobuf:"bytes,3,req,name=method" json:"method,omitempty"`
Request []byte `protobuf:"bytes,4,req,name=request" json:"request,omitempty"`
RequestId *string `protobuf:"bytes,5,opt,name=request_id,json=requestId" json:"request_id,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Request) Reset() { *m = Request{} }
func (m *Request) String() string { return proto.CompactTextString(m) }
func (*Request) ProtoMessage() {}
func (*Request) Descriptor() ([]byte, []int) {
return fileDescriptor_remote_api_1978114ec33a273d, []int{0}
}
func (m *Request) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Request.Unmarshal(m, b)
}
func (m *Request) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Request.Marshal(b, m, deterministic)
}
func (dst *Request) XXX_Merge(src proto.Message) {
xxx_messageInfo_Request.Merge(dst, src)
}
func (m *Request) XXX_Size() int {
return xxx_messageInfo_Request.Size(m)
}
func (m *Request) XXX_DiscardUnknown() {
xxx_messageInfo_Request.DiscardUnknown(m)
}
var xxx_messageInfo_Request proto.InternalMessageInfo
func (m *Request) GetServiceName() string {
if m != nil && m.ServiceName != nil {
return *m.ServiceName
}
return ""
}
func (m *Request) GetMethod() string {
if m != nil && m.Method != nil {
return *m.Method
}
return ""
}
func (m *Request) GetRequest() []byte {
if m != nil {
return m.Request
}
return nil
}
func (m *Request) GetRequestId() string {
if m != nil && m.RequestId != nil {
return *m.RequestId
}
return ""
}
type ApplicationError struct {
Code *int32 `protobuf:"varint,1,req,name=code" json:"code,omitempty"`
Detail *string `protobuf:"bytes,2,req,name=detail" json:"detail,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ApplicationError) Reset() { *m = ApplicationError{} }
func (m *ApplicationError) String() string { return proto.CompactTextString(m) }
func (*ApplicationError) ProtoMessage() {}
func (*ApplicationError) Descriptor() ([]byte, []int) {
return fileDescriptor_remote_api_1978114ec33a273d, []int{1}
}
func (m *ApplicationError) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ApplicationError.Unmarshal(m, b)
}
func (m *ApplicationError) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ApplicationError.Marshal(b, m, deterministic)
}
func (dst *ApplicationError) XXX_Merge(src proto.Message) {
xxx_messageInfo_ApplicationError.Merge(dst, src)
}
func (m *ApplicationError) XXX_Size() int {
return xxx_messageInfo_ApplicationError.Size(m)
}
func (m *ApplicationError) XXX_DiscardUnknown() {
xxx_messageInfo_ApplicationError.DiscardUnknown(m)
}
var xxx_messageInfo_ApplicationError proto.InternalMessageInfo
func (m *ApplicationError) GetCode() int32 {
if m != nil && m.Code != nil {
return *m.Code
}
return 0
}
func (m *ApplicationError) GetDetail() string {
if m != nil && m.Detail != nil {
return *m.Detail
}
return ""
}
type RpcError struct {
Code *int32 `protobuf:"varint,1,req,name=code" json:"code,omitempty"`
Detail *string `protobuf:"bytes,2,opt,name=detail" json:"detail,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *RpcError) Reset() { *m = RpcError{} }
func (m *RpcError) String() string { return proto.CompactTextString(m) }
func (*RpcError) ProtoMessage() {}
func (*RpcError) Descriptor() ([]byte, []int) {
return fileDescriptor_remote_api_1978114ec33a273d, []int{2}
}
func (m *RpcError) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_RpcError.Unmarshal(m, b)
}
func (m *RpcError) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_RpcError.Marshal(b, m, deterministic)
}
func (dst *RpcError) XXX_Merge(src proto.Message) {
xxx_messageInfo_RpcError.Merge(dst, src)
}
func (m *RpcError) XXX_Size() int {
return xxx_messageInfo_RpcError.Size(m)
}
func (m *RpcError) XXX_DiscardUnknown() {
xxx_messageInfo_RpcError.DiscardUnknown(m)
}
var xxx_messageInfo_RpcError proto.InternalMessageInfo
func (m *RpcError) GetCode() int32 {
if m != nil && m.Code != nil {
return *m.Code
}
return 0
}
func (m *RpcError) GetDetail() string {
if m != nil && m.Detail != nil {
return *m.Detail
}
return ""
}
type Response struct {
Response []byte `protobuf:"bytes,1,opt,name=response" json:"response,omitempty"`
Exception []byte `protobuf:"bytes,2,opt,name=exception" json:"exception,omitempty"`
ApplicationError *ApplicationError `protobuf:"bytes,3,opt,name=application_error,json=applicationError" json:"application_error,omitempty"`
JavaException []byte `protobuf:"bytes,4,opt,name=java_exception,json=javaException" json:"java_exception,omitempty"`
RpcError *RpcError `protobuf:"bytes,5,opt,name=rpc_error,json=rpcError" json:"rpc_error,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Response) Reset() { *m = Response{} }
func (m *Response) String() string { return proto.CompactTextString(m) }
func (*Response) ProtoMessage() {}
func (*Response) Descriptor() ([]byte, []int) {
return fileDescriptor_remote_api_1978114ec33a273d, []int{3}
}
func (m *Response) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Response.Unmarshal(m, b)
}
func (m *Response) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Response.Marshal(b, m, deterministic)
}
func (dst *Response) XXX_Merge(src proto.Message) {
xxx_messageInfo_Response.Merge(dst, src)
}
func (m *Response) XXX_Size() int {
return xxx_messageInfo_Response.Size(m)
}
func (m *Response) XXX_DiscardUnknown() {
xxx_messageInfo_Response.DiscardUnknown(m)
}
var xxx_messageInfo_Response proto.InternalMessageInfo
func (m *Response) GetResponse() []byte {
if m != nil {
return m.Response
}
return nil
}
func (m *Response) GetException() []byte {
if m != nil {
return m.Exception
}
return nil
}
func (m *Response) GetApplicationError() *ApplicationError {
if m != nil {
return m.ApplicationError
}
return nil
}
func (m *Response) GetJavaException() []byte {
if m != nil {
return m.JavaException
}
return nil
}
func (m *Response) GetRpcError() *RpcError {
if m != nil {
return m.RpcError
}
return nil
}
func init() {
proto.RegisterType((*Request)(nil), "remote_api.Request")
proto.RegisterType((*ApplicationError)(nil), "remote_api.ApplicationError")
proto.RegisterType((*RpcError)(nil), "remote_api.RpcError")
proto.RegisterType((*Response)(nil), "remote_api.Response")
}
func init() {
proto.RegisterFile("google.golang.org/appengine/internal/remote_api/remote_api.proto", fileDescriptor_remote_api_1978114ec33a273d)
}
var fileDescriptor_remote_api_1978114ec33a273d = []byte{
// 531 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x93, 0x51, 0x6e, 0xd3, 0x40,
0x10, 0x86, 0xb1, 0x9b, 0x34, 0xf1, 0xc4, 0x2d, 0xdb, 0xa5, 0x14, 0x0b, 0x15, 0x29, 0x44, 0x42,
0xca, 0x53, 0x2a, 0x38, 0x00, 0x62, 0x63, 0x6f, 0x91, 0x85, 0x65, 0xa7, 0x6b, 0xbb, 0x50, 0x5e,
0x56, 0x2b, 0x67, 0x65, 0x8c, 0x12, 0xaf, 0xd9, 0x98, 0x8a, 0x17, 0x6e, 0xc0, 0xb5, 0x38, 0x0c,
0xb7, 0x40, 0x36, 0x6e, 0x63, 0xf5, 0x89, 0xb7, 0x7f, 0x7e, 0x7b, 0xe6, 0x1b, 0xcd, 0xcc, 0xc2,
0xbb, 0x5c, 0xa9, 0x7c, 0x23, 0x17, 0xb9, 0xda, 0x88, 0x32, 0x5f, 0x28, 0x9d, 0x5f, 0x88, 0xaa,
0x92, 0x65, 0x5e, 0x94, 0xf2, 0xa2, 0x28, 0x6b, 0xa9, 0x4b, 0xb1, 0xb9, 0xd0, 0x72, 0xab, 0x6a,
0xc9, 0x45, 0x55, 0xf4, 0xe4, 0xa2, 0xd2, 0xaa, 0x56, 0x18, 0xf6, 0xce, 0xec, 0x27, 0x8c, 0x98,
0xfc, 0xf6, 0x5d, 0xee, 0x6a, 0xfc, 0x12, 0xec, 0x9d, 0xd4, 0xb7, 0x45, 0x26, 0x79, 0x29, 0xb6,
0xd2, 0x31, 0xa7, 0xe6, 0xdc, 0x62, 0x93, 0xce, 0x0b, 0xc5, 0x56, 0xe2, 0x33, 0x38, 0xdc, 0xca,
0xfa, 0x8b, 0x5a, 0x3b, 0x07, 0xed, 0xc7, 0x2e, 0xc2, 0x0e, 0x8c, 0xf4, 0xbf, 0x2a, 0xce, 0x60,
0x6a, 0xce, 0x6d, 0x76, 0x17, 0xe2, 0x17, 0x00, 0x9d, 0xe4, 0xc5, 0xda, 0x19, 0x4e, 0x8d, 0xb9,
0xc5, 0xac, 0xce, 0xf1, 0xd7, 0xb3, 0xb7, 0x80, 0x48, 0x55, 0x6d, 0x8a, 0x4c, 0xd4, 0x85, 0x2a,
0xa9, 0xd6, 0x4a, 0x63, 0x0c, 0x83, 0x4c, 0xad, 0xa5, 0x63, 0x4c, 0xcd, 0xf9, 0x90, 0xb5, 0xba,
0x01, 0xaf, 0x65, 0x2d, 0x8a, 0x4d, 0xd7, 0x55, 0x17, 0xcd, 0x7e, 0x9b, 0x30, 0x66, 0x55, 0xf6,
0x7f, 0x89, 0x46, 0x2f, 0xf1, 0x97, 0x09, 0x56, 0x9b, 0xe5, 0x36, 0x7f, 0x4d, 0x60, 0x94, 0x86,
0x1f, 0xc2, 0xe8, 0x63, 0x88, 0x1e, 0x61, 0x0c, 0xc7, 0x2e, 0x09, 0x02, 0x1e, 0x46, 0x09, 0xbf,
0x8c, 0xd2, 0xd0, 0x43, 0x06, 0x7e, 0x0c, 0x93, 0x15, 0x61, 0x31, 0xe5, 0x94, 0xb1, 0x88, 0x21,
0x13, 0x9f, 0x01, 0x8e, 0xa9, 0x9b, 0x32, 0x3f, 0xb9, 0xe1, 0xd7, 0x7e, 0x14, 0x90, 0xc4, 0x8f,
0x42, 0x74, 0x80, 0x8f, 0x01, 0xa2, 0x6b, 0xca, 0xf8, 0x55, 0x1a, 0x25, 0x04, 0x0d, 0xf0, 0x53,
0x38, 0x61, 0xf4, 0x2a, 0xa5, 0x71, 0xc2, 0x93, 0x28, 0xe2, 0x01, 0x61, 0xef, 0x29, 0x1a, 0xe2,
0x67, 0xf0, 0xc4, 0x25, 0x2b, 0xb2, 0xf4, 0x83, 0xa6, 0x80, 0xe7, 0xc7, 0x64, 0x19, 0x50, 0x0f,
0x1d, 0xe2, 0x53, 0x40, 0x97, 0x94, 0x24, 0x29, 0xa3, 0x7b, 0x77, 0xd4, 0xe0, 0x97, 0xc4, 0xe3,
0x5d, 0x25, 0x34, 0x6e, 0xf0, 0x8c, 0xc6, 0xab, 0x28, 0x8c, 0x69, 0xaf, 0xae, 0x85, 0x8f, 0xc0,
0x72, 0x49, 0xe8, 0xd2, 0xa0, 0xc9, 0x03, 0x8c, 0xc0, 0x66, 0x74, 0x15, 0x90, 0x9b, 0xae, 0xef,
0x49, 0xd3, 0x8f, 0x47, 0x89, 0x17, 0xf8, 0x21, 0xe5, 0xf4, 0x93, 0x4b, 0xa9, 0x47, 0x3d, 0x64,
0xcf, 0xfe, 0x18, 0x30, 0x66, 0x72, 0x57, 0xa9, 0x72, 0x27, 0xf1, 0x73, 0x18, 0xeb, 0x4e, 0x3b,
0xc6, 0xd4, 0x98, 0xdb, 0xec, 0x3e, 0xc6, 0xe7, 0x60, 0xc9, 0x1f, 0x99, 0xac, 0x9a, 0x75, 0xb5,
0x23, 0xb5, 0xd9, 0xde, 0xc0, 0x3e, 0x9c, 0x88, 0xfd, 0x3a, 0xb9, 0x6c, 0x06, 0xec, 0x1c, 0x4c,
0x8d, 0xf9, 0xe4, 0xcd, 0xf9, 0xa2, 0x77, 0x87, 0x0f, 0x77, 0xce, 0x90, 0x78, 0x78, 0x05, 0xaf,
0xe0, 0xf8, 0xab, 0xb8, 0x15, 0x7c, 0x4f, 0x1b, 0xb4, 0xb4, 0xa3, 0xc6, 0xa5, 0xf7, 0xc4, 0xd7,
0x60, 0xe9, 0x2a, 0xeb, 0x48, 0xc3, 0x96, 0x74, 0xda, 0x27, 0xdd, 0x1d, 0x07, 0x1b, 0xeb, 0x4e,
0x2d, 0xed, 0xcf, 0xbd, 0x07, 0xf0, 0x37, 0x00, 0x00, 0xff, 0xff, 0x38, 0xd1, 0x0f, 0x22, 0x4f,
0x03, 0x00, 0x00,
}

View file

@ -0,0 +1,44 @@
syntax = "proto2";
option go_package = "remote_api";
package remote_api;
message Request {
required string service_name = 2;
required string method = 3;
required bytes request = 4;
optional string request_id = 5;
}
message ApplicationError {
required int32 code = 1;
required string detail = 2;
}
message RpcError {
enum ErrorCode {
UNKNOWN = 0;
CALL_NOT_FOUND = 1;
PARSE_ERROR = 2;
SECURITY_VIOLATION = 3;
OVER_QUOTA = 4;
REQUEST_TOO_LARGE = 5;
CAPABILITY_DISABLED = 6;
FEATURE_DISABLED = 7;
BAD_REQUEST = 8;
RESPONSE_TOO_LARGE = 9;
CANCELLED = 10;
REPLAY_ERROR = 11;
DEADLINE_EXCEEDED = 12;
}
required int32 code = 1;
optional string detail = 2;
}
message Response {
optional bytes response = 1;
optional bytes exception = 2;
optional ApplicationError application_error = 3;
optional bytes java_exception = 4;
optional RpcError rpc_error = 5;
}

View file

@ -0,0 +1,115 @@
// Copyright 2014 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.
package internal
// This file implements hooks for applying datastore transactions.
import (
"errors"
"reflect"
"github.com/golang/protobuf/proto"
netcontext "golang.org/x/net/context"
basepb "google.golang.org/appengine/internal/base"
pb "google.golang.org/appengine/internal/datastore"
)
var transactionSetters = make(map[reflect.Type]reflect.Value)
// RegisterTransactionSetter registers a function that sets transaction information
// in a protocol buffer message. f should be a function with two arguments,
// the first being a protocol buffer type, and the second being *datastore.Transaction.
func RegisterTransactionSetter(f interface{}) {
v := reflect.ValueOf(f)
transactionSetters[v.Type().In(0)] = v
}
// applyTransaction applies the transaction t to message pb
// by using the relevant setter passed to RegisterTransactionSetter.
func applyTransaction(pb proto.Message, t *pb.Transaction) {
v := reflect.ValueOf(pb)
if f, ok := transactionSetters[v.Type()]; ok {
f.Call([]reflect.Value{v, reflect.ValueOf(t)})
}
}
var transactionKey = "used for *Transaction"
func transactionFromContext(ctx netcontext.Context) *transaction {
t, _ := ctx.Value(&transactionKey).(*transaction)
return t
}
func withTransaction(ctx netcontext.Context, t *transaction) netcontext.Context {
return netcontext.WithValue(ctx, &transactionKey, t)
}
type transaction struct {
transaction pb.Transaction
finished bool
}
var ErrConcurrentTransaction = errors.New("internal: concurrent transaction")
func RunTransactionOnce(c netcontext.Context, f func(netcontext.Context) error, xg bool, readOnly bool, previousTransaction *pb.Transaction) (*pb.Transaction, error) {
if transactionFromContext(c) != nil {
return nil, errors.New("nested transactions are not supported")
}
// Begin the transaction.
t := &transaction{}
req := &pb.BeginTransactionRequest{
App: proto.String(FullyQualifiedAppID(c)),
}
if xg {
req.AllowMultipleEg = proto.Bool(true)
}
if previousTransaction != nil {
req.PreviousTransaction = previousTransaction
}
if readOnly {
req.Mode = pb.BeginTransactionRequest_READ_ONLY.Enum()
} else {
req.Mode = pb.BeginTransactionRequest_READ_WRITE.Enum()
}
if err := Call(c, "datastore_v3", "BeginTransaction", req, &t.transaction); err != nil {
return nil, err
}
// Call f, rolling back the transaction if f returns a non-nil error, or panics.
// The panic is not recovered.
defer func() {
if t.finished {
return
}
t.finished = true
// Ignore the error return value, since we are already returning a non-nil
// error (or we're panicking).
Call(c, "datastore_v3", "Rollback", &t.transaction, &basepb.VoidProto{})
}()
if err := f(withTransaction(c, t)); err != nil {
return &t.transaction, err
}
t.finished = true
// Commit the transaction.
res := &pb.CommitResponse{}
err := Call(c, "datastore_v3", "Commit", &t.transaction, res)
if ae, ok := err.(*APIError); ok {
/* TODO: restore this conditional
if appengine.IsDevAppServer() {
*/
// The Python Dev AppServer raises an ApplicationError with error code 2 (which is
// Error.CONCURRENT_TRANSACTION) and message "Concurrency exception.".
if ae.Code == int32(pb.Error_BAD_REQUEST) && ae.Detail == "ApplicationError: 2 Concurrency exception." {
return &t.transaction, ErrConcurrentTransaction
}
if ae.Code == int32(pb.Error_CONCURRENT_TRANSACTION) {
return &t.transaction, ErrConcurrentTransaction
}
}
return &t.transaction, err
}

View file

@ -0,0 +1,527 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto
package urlfetch
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type URLFetchServiceError_ErrorCode int32
const (
URLFetchServiceError_OK URLFetchServiceError_ErrorCode = 0
URLFetchServiceError_INVALID_URL URLFetchServiceError_ErrorCode = 1
URLFetchServiceError_FETCH_ERROR URLFetchServiceError_ErrorCode = 2
URLFetchServiceError_UNSPECIFIED_ERROR URLFetchServiceError_ErrorCode = 3
URLFetchServiceError_RESPONSE_TOO_LARGE URLFetchServiceError_ErrorCode = 4
URLFetchServiceError_DEADLINE_EXCEEDED URLFetchServiceError_ErrorCode = 5
URLFetchServiceError_SSL_CERTIFICATE_ERROR URLFetchServiceError_ErrorCode = 6
URLFetchServiceError_DNS_ERROR URLFetchServiceError_ErrorCode = 7
URLFetchServiceError_CLOSED URLFetchServiceError_ErrorCode = 8
URLFetchServiceError_INTERNAL_TRANSIENT_ERROR URLFetchServiceError_ErrorCode = 9
URLFetchServiceError_TOO_MANY_REDIRECTS URLFetchServiceError_ErrorCode = 10
URLFetchServiceError_MALFORMED_REPLY URLFetchServiceError_ErrorCode = 11
URLFetchServiceError_CONNECTION_ERROR URLFetchServiceError_ErrorCode = 12
)
var URLFetchServiceError_ErrorCode_name = map[int32]string{
0: "OK",
1: "INVALID_URL",
2: "FETCH_ERROR",
3: "UNSPECIFIED_ERROR",
4: "RESPONSE_TOO_LARGE",
5: "DEADLINE_EXCEEDED",
6: "SSL_CERTIFICATE_ERROR",
7: "DNS_ERROR",
8: "CLOSED",
9: "INTERNAL_TRANSIENT_ERROR",
10: "TOO_MANY_REDIRECTS",
11: "MALFORMED_REPLY",
12: "CONNECTION_ERROR",
}
var URLFetchServiceError_ErrorCode_value = map[string]int32{
"OK": 0,
"INVALID_URL": 1,
"FETCH_ERROR": 2,
"UNSPECIFIED_ERROR": 3,
"RESPONSE_TOO_LARGE": 4,
"DEADLINE_EXCEEDED": 5,
"SSL_CERTIFICATE_ERROR": 6,
"DNS_ERROR": 7,
"CLOSED": 8,
"INTERNAL_TRANSIENT_ERROR": 9,
"TOO_MANY_REDIRECTS": 10,
"MALFORMED_REPLY": 11,
"CONNECTION_ERROR": 12,
}
func (x URLFetchServiceError_ErrorCode) Enum() *URLFetchServiceError_ErrorCode {
p := new(URLFetchServiceError_ErrorCode)
*p = x
return p
}
func (x URLFetchServiceError_ErrorCode) String() string {
return proto.EnumName(URLFetchServiceError_ErrorCode_name, int32(x))
}
func (x *URLFetchServiceError_ErrorCode) UnmarshalJSON(data []byte) error {
value, err := proto.UnmarshalJSONEnum(URLFetchServiceError_ErrorCode_value, data, "URLFetchServiceError_ErrorCode")
if err != nil {
return err
}
*x = URLFetchServiceError_ErrorCode(value)
return nil
}
func (URLFetchServiceError_ErrorCode) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_urlfetch_service_b245a7065f33bced, []int{0, 0}
}
type URLFetchRequest_RequestMethod int32
const (
URLFetchRequest_GET URLFetchRequest_RequestMethod = 1
URLFetchRequest_POST URLFetchRequest_RequestMethod = 2
URLFetchRequest_HEAD URLFetchRequest_RequestMethod = 3
URLFetchRequest_PUT URLFetchRequest_RequestMethod = 4
URLFetchRequest_DELETE URLFetchRequest_RequestMethod = 5
URLFetchRequest_PATCH URLFetchRequest_RequestMethod = 6
)
var URLFetchRequest_RequestMethod_name = map[int32]string{
1: "GET",
2: "POST",
3: "HEAD",
4: "PUT",
5: "DELETE",
6: "PATCH",
}
var URLFetchRequest_RequestMethod_value = map[string]int32{
"GET": 1,
"POST": 2,
"HEAD": 3,
"PUT": 4,
"DELETE": 5,
"PATCH": 6,
}
func (x URLFetchRequest_RequestMethod) Enum() *URLFetchRequest_RequestMethod {
p := new(URLFetchRequest_RequestMethod)
*p = x
return p
}
func (x URLFetchRequest_RequestMethod) String() string {
return proto.EnumName(URLFetchRequest_RequestMethod_name, int32(x))
}
func (x *URLFetchRequest_RequestMethod) UnmarshalJSON(data []byte) error {
value, err := proto.UnmarshalJSONEnum(URLFetchRequest_RequestMethod_value, data, "URLFetchRequest_RequestMethod")
if err != nil {
return err
}
*x = URLFetchRequest_RequestMethod(value)
return nil
}
func (URLFetchRequest_RequestMethod) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_urlfetch_service_b245a7065f33bced, []int{1, 0}
}
type URLFetchServiceError struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *URLFetchServiceError) Reset() { *m = URLFetchServiceError{} }
func (m *URLFetchServiceError) String() string { return proto.CompactTextString(m) }
func (*URLFetchServiceError) ProtoMessage() {}
func (*URLFetchServiceError) Descriptor() ([]byte, []int) {
return fileDescriptor_urlfetch_service_b245a7065f33bced, []int{0}
}
func (m *URLFetchServiceError) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_URLFetchServiceError.Unmarshal(m, b)
}
func (m *URLFetchServiceError) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_URLFetchServiceError.Marshal(b, m, deterministic)
}
func (dst *URLFetchServiceError) XXX_Merge(src proto.Message) {
xxx_messageInfo_URLFetchServiceError.Merge(dst, src)
}
func (m *URLFetchServiceError) XXX_Size() int {
return xxx_messageInfo_URLFetchServiceError.Size(m)
}
func (m *URLFetchServiceError) XXX_DiscardUnknown() {
xxx_messageInfo_URLFetchServiceError.DiscardUnknown(m)
}
var xxx_messageInfo_URLFetchServiceError proto.InternalMessageInfo
type URLFetchRequest struct {
Method *URLFetchRequest_RequestMethod `protobuf:"varint,1,req,name=Method,enum=appengine.URLFetchRequest_RequestMethod" json:"Method,omitempty"`
Url *string `protobuf:"bytes,2,req,name=Url" json:"Url,omitempty"`
Header []*URLFetchRequest_Header `protobuf:"group,3,rep,name=Header,json=header" json:"header,omitempty"`
Payload []byte `protobuf:"bytes,6,opt,name=Payload" json:"Payload,omitempty"`
FollowRedirects *bool `protobuf:"varint,7,opt,name=FollowRedirects,def=1" json:"FollowRedirects,omitempty"`
Deadline *float64 `protobuf:"fixed64,8,opt,name=Deadline" json:"Deadline,omitempty"`
MustValidateServerCertificate *bool `protobuf:"varint,9,opt,name=MustValidateServerCertificate,def=1" json:"MustValidateServerCertificate,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *URLFetchRequest) Reset() { *m = URLFetchRequest{} }
func (m *URLFetchRequest) String() string { return proto.CompactTextString(m) }
func (*URLFetchRequest) ProtoMessage() {}
func (*URLFetchRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_urlfetch_service_b245a7065f33bced, []int{1}
}
func (m *URLFetchRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_URLFetchRequest.Unmarshal(m, b)
}
func (m *URLFetchRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_URLFetchRequest.Marshal(b, m, deterministic)
}
func (dst *URLFetchRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_URLFetchRequest.Merge(dst, src)
}
func (m *URLFetchRequest) XXX_Size() int {
return xxx_messageInfo_URLFetchRequest.Size(m)
}
func (m *URLFetchRequest) XXX_DiscardUnknown() {
xxx_messageInfo_URLFetchRequest.DiscardUnknown(m)
}
var xxx_messageInfo_URLFetchRequest proto.InternalMessageInfo
const Default_URLFetchRequest_FollowRedirects bool = true
const Default_URLFetchRequest_MustValidateServerCertificate bool = true
func (m *URLFetchRequest) GetMethod() URLFetchRequest_RequestMethod {
if m != nil && m.Method != nil {
return *m.Method
}
return URLFetchRequest_GET
}
func (m *URLFetchRequest) GetUrl() string {
if m != nil && m.Url != nil {
return *m.Url
}
return ""
}
func (m *URLFetchRequest) GetHeader() []*URLFetchRequest_Header {
if m != nil {
return m.Header
}
return nil
}
func (m *URLFetchRequest) GetPayload() []byte {
if m != nil {
return m.Payload
}
return nil
}
func (m *URLFetchRequest) GetFollowRedirects() bool {
if m != nil && m.FollowRedirects != nil {
return *m.FollowRedirects
}
return Default_URLFetchRequest_FollowRedirects
}
func (m *URLFetchRequest) GetDeadline() float64 {
if m != nil && m.Deadline != nil {
return *m.Deadline
}
return 0
}
func (m *URLFetchRequest) GetMustValidateServerCertificate() bool {
if m != nil && m.MustValidateServerCertificate != nil {
return *m.MustValidateServerCertificate
}
return Default_URLFetchRequest_MustValidateServerCertificate
}
type URLFetchRequest_Header struct {
Key *string `protobuf:"bytes,4,req,name=Key" json:"Key,omitempty"`
Value *string `protobuf:"bytes,5,req,name=Value" json:"Value,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *URLFetchRequest_Header) Reset() { *m = URLFetchRequest_Header{} }
func (m *URLFetchRequest_Header) String() string { return proto.CompactTextString(m) }
func (*URLFetchRequest_Header) ProtoMessage() {}
func (*URLFetchRequest_Header) Descriptor() ([]byte, []int) {
return fileDescriptor_urlfetch_service_b245a7065f33bced, []int{1, 0}
}
func (m *URLFetchRequest_Header) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_URLFetchRequest_Header.Unmarshal(m, b)
}
func (m *URLFetchRequest_Header) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_URLFetchRequest_Header.Marshal(b, m, deterministic)
}
func (dst *URLFetchRequest_Header) XXX_Merge(src proto.Message) {
xxx_messageInfo_URLFetchRequest_Header.Merge(dst, src)
}
func (m *URLFetchRequest_Header) XXX_Size() int {
return xxx_messageInfo_URLFetchRequest_Header.Size(m)
}
func (m *URLFetchRequest_Header) XXX_DiscardUnknown() {
xxx_messageInfo_URLFetchRequest_Header.DiscardUnknown(m)
}
var xxx_messageInfo_URLFetchRequest_Header proto.InternalMessageInfo
func (m *URLFetchRequest_Header) GetKey() string {
if m != nil && m.Key != nil {
return *m.Key
}
return ""
}
func (m *URLFetchRequest_Header) GetValue() string {
if m != nil && m.Value != nil {
return *m.Value
}
return ""
}
type URLFetchResponse struct {
Content []byte `protobuf:"bytes,1,opt,name=Content" json:"Content,omitempty"`
StatusCode *int32 `protobuf:"varint,2,req,name=StatusCode" json:"StatusCode,omitempty"`
Header []*URLFetchResponse_Header `protobuf:"group,3,rep,name=Header,json=header" json:"header,omitempty"`
ContentWasTruncated *bool `protobuf:"varint,6,opt,name=ContentWasTruncated,def=0" json:"ContentWasTruncated,omitempty"`
ExternalBytesSent *int64 `protobuf:"varint,7,opt,name=ExternalBytesSent" json:"ExternalBytesSent,omitempty"`
ExternalBytesReceived *int64 `protobuf:"varint,8,opt,name=ExternalBytesReceived" json:"ExternalBytesReceived,omitempty"`
FinalUrl *string `protobuf:"bytes,9,opt,name=FinalUrl" json:"FinalUrl,omitempty"`
ApiCpuMilliseconds *int64 `protobuf:"varint,10,opt,name=ApiCpuMilliseconds,def=0" json:"ApiCpuMilliseconds,omitempty"`
ApiBytesSent *int64 `protobuf:"varint,11,opt,name=ApiBytesSent,def=0" json:"ApiBytesSent,omitempty"`
ApiBytesReceived *int64 `protobuf:"varint,12,opt,name=ApiBytesReceived,def=0" json:"ApiBytesReceived,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *URLFetchResponse) Reset() { *m = URLFetchResponse{} }
func (m *URLFetchResponse) String() string { return proto.CompactTextString(m) }
func (*URLFetchResponse) ProtoMessage() {}
func (*URLFetchResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_urlfetch_service_b245a7065f33bced, []int{2}
}
func (m *URLFetchResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_URLFetchResponse.Unmarshal(m, b)
}
func (m *URLFetchResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_URLFetchResponse.Marshal(b, m, deterministic)
}
func (dst *URLFetchResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_URLFetchResponse.Merge(dst, src)
}
func (m *URLFetchResponse) XXX_Size() int {
return xxx_messageInfo_URLFetchResponse.Size(m)
}
func (m *URLFetchResponse) XXX_DiscardUnknown() {
xxx_messageInfo_URLFetchResponse.DiscardUnknown(m)
}
var xxx_messageInfo_URLFetchResponse proto.InternalMessageInfo
const Default_URLFetchResponse_ContentWasTruncated bool = false
const Default_URLFetchResponse_ApiCpuMilliseconds int64 = 0
const Default_URLFetchResponse_ApiBytesSent int64 = 0
const Default_URLFetchResponse_ApiBytesReceived int64 = 0
func (m *URLFetchResponse) GetContent() []byte {
if m != nil {
return m.Content
}
return nil
}
func (m *URLFetchResponse) GetStatusCode() int32 {
if m != nil && m.StatusCode != nil {
return *m.StatusCode
}
return 0
}
func (m *URLFetchResponse) GetHeader() []*URLFetchResponse_Header {
if m != nil {
return m.Header
}
return nil
}
func (m *URLFetchResponse) GetContentWasTruncated() bool {
if m != nil && m.ContentWasTruncated != nil {
return *m.ContentWasTruncated
}
return Default_URLFetchResponse_ContentWasTruncated
}
func (m *URLFetchResponse) GetExternalBytesSent() int64 {
if m != nil && m.ExternalBytesSent != nil {
return *m.ExternalBytesSent
}
return 0
}
func (m *URLFetchResponse) GetExternalBytesReceived() int64 {
if m != nil && m.ExternalBytesReceived != nil {
return *m.ExternalBytesReceived
}
return 0
}
func (m *URLFetchResponse) GetFinalUrl() string {
if m != nil && m.FinalUrl != nil {
return *m.FinalUrl
}
return ""
}
func (m *URLFetchResponse) GetApiCpuMilliseconds() int64 {
if m != nil && m.ApiCpuMilliseconds != nil {
return *m.ApiCpuMilliseconds
}
return Default_URLFetchResponse_ApiCpuMilliseconds
}
func (m *URLFetchResponse) GetApiBytesSent() int64 {
if m != nil && m.ApiBytesSent != nil {
return *m.ApiBytesSent
}
return Default_URLFetchResponse_ApiBytesSent
}
func (m *URLFetchResponse) GetApiBytesReceived() int64 {
if m != nil && m.ApiBytesReceived != nil {
return *m.ApiBytesReceived
}
return Default_URLFetchResponse_ApiBytesReceived
}
type URLFetchResponse_Header struct {
Key *string `protobuf:"bytes,4,req,name=Key" json:"Key,omitempty"`
Value *string `protobuf:"bytes,5,req,name=Value" json:"Value,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *URLFetchResponse_Header) Reset() { *m = URLFetchResponse_Header{} }
func (m *URLFetchResponse_Header) String() string { return proto.CompactTextString(m) }
func (*URLFetchResponse_Header) ProtoMessage() {}
func (*URLFetchResponse_Header) Descriptor() ([]byte, []int) {
return fileDescriptor_urlfetch_service_b245a7065f33bced, []int{2, 0}
}
func (m *URLFetchResponse_Header) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_URLFetchResponse_Header.Unmarshal(m, b)
}
func (m *URLFetchResponse_Header) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_URLFetchResponse_Header.Marshal(b, m, deterministic)
}
func (dst *URLFetchResponse_Header) XXX_Merge(src proto.Message) {
xxx_messageInfo_URLFetchResponse_Header.Merge(dst, src)
}
func (m *URLFetchResponse_Header) XXX_Size() int {
return xxx_messageInfo_URLFetchResponse_Header.Size(m)
}
func (m *URLFetchResponse_Header) XXX_DiscardUnknown() {
xxx_messageInfo_URLFetchResponse_Header.DiscardUnknown(m)
}
var xxx_messageInfo_URLFetchResponse_Header proto.InternalMessageInfo
func (m *URLFetchResponse_Header) GetKey() string {
if m != nil && m.Key != nil {
return *m.Key
}
return ""
}
func (m *URLFetchResponse_Header) GetValue() string {
if m != nil && m.Value != nil {
return *m.Value
}
return ""
}
func init() {
proto.RegisterType((*URLFetchServiceError)(nil), "appengine.URLFetchServiceError")
proto.RegisterType((*URLFetchRequest)(nil), "appengine.URLFetchRequest")
proto.RegisterType((*URLFetchRequest_Header)(nil), "appengine.URLFetchRequest.Header")
proto.RegisterType((*URLFetchResponse)(nil), "appengine.URLFetchResponse")
proto.RegisterType((*URLFetchResponse_Header)(nil), "appengine.URLFetchResponse.Header")
}
func init() {
proto.RegisterFile("google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto", fileDescriptor_urlfetch_service_b245a7065f33bced)
}
var fileDescriptor_urlfetch_service_b245a7065f33bced = []byte{
// 770 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0xdd, 0x6e, 0xe3, 0x54,
0x10, 0xc6, 0x76, 0x7e, 0xa7, 0x5d, 0x7a, 0x76, 0xb6, 0x45, 0x66, 0xb5, 0xa0, 0x10, 0x09, 0x29,
0x17, 0x90, 0x2e, 0x2b, 0x24, 0x44, 0xaf, 0x70, 0xed, 0x93, 0xad, 0xa9, 0x63, 0x47, 0xc7, 0x4e,
0x61, 0xb9, 0xb1, 0xac, 0x78, 0x9a, 0x5a, 0xb2, 0xec, 0x60, 0x9f, 0x2c, 0xf4, 0x35, 0x78, 0x0d,
0xde, 0x87, 0xa7, 0xe1, 0x02, 0x9d, 0xc4, 0xc9, 0x6e, 0xbb, 0xd1, 0x4a, 0x5c, 0x65, 0xe6, 0x9b,
0xef, 0xcc, 0x99, 0x7c, 0xdf, 0xf8, 0x80, 0xb3, 0x2c, 0xcb, 0x65, 0x4e, 0xe3, 0x65, 0x99, 0x27,
0xc5, 0x72, 0x5c, 0x56, 0xcb, 0xf3, 0x64, 0xb5, 0xa2, 0x62, 0x99, 0x15, 0x74, 0x9e, 0x15, 0x92,
0xaa, 0x22, 0xc9, 0xcf, 0xd7, 0x55, 0x7e, 0x4b, 0x72, 0x71, 0xb7, 0x0f, 0xe2, 0x9a, 0xaa, 0xb7,
0xd9, 0x82, 0xc6, 0xab, 0xaa, 0x94, 0x25, 0xf6, 0xf7, 0x67, 0x86, 0x7f, 0xeb, 0x70, 0x3a, 0x17,
0xde, 0x44, 0xb1, 0xc2, 0x2d, 0x89, 0x57, 0x55, 0x59, 0x0d, 0xff, 0xd2, 0xa1, 0xbf, 0x89, 0xec,
0x32, 0x25, 0xec, 0x80, 0x1e, 0x5c, 0xb3, 0x4f, 0xf0, 0x04, 0x8e, 0x5c, 0xff, 0xc6, 0xf2, 0x5c,
0x27, 0x9e, 0x0b, 0x8f, 0x69, 0x0a, 0x98, 0xf0, 0xc8, 0xbe, 0x8a, 0xb9, 0x10, 0x81, 0x60, 0x3a,
0x9e, 0xc1, 0xd3, 0xb9, 0x1f, 0xce, 0xb8, 0xed, 0x4e, 0x5c, 0xee, 0x34, 0xb0, 0x81, 0x9f, 0x01,
0x0a, 0x1e, 0xce, 0x02, 0x3f, 0xe4, 0x71, 0x14, 0x04, 0xb1, 0x67, 0x89, 0xd7, 0x9c, 0xb5, 0x14,
0xdd, 0xe1, 0x96, 0xe3, 0xb9, 0x3e, 0x8f, 0xf9, 0xaf, 0x36, 0xe7, 0x0e, 0x77, 0x58, 0x1b, 0x3f,
0x87, 0xb3, 0x30, 0xf4, 0x62, 0x9b, 0x8b, 0xc8, 0x9d, 0xb8, 0xb6, 0x15, 0xf1, 0xa6, 0x53, 0x07,
0x9f, 0x40, 0xdf, 0xf1, 0xc3, 0x26, 0xed, 0x22, 0x40, 0xc7, 0xf6, 0x82, 0x90, 0x3b, 0xac, 0x87,
0x2f, 0xc0, 0x74, 0xfd, 0x88, 0x0b, 0xdf, 0xf2, 0xe2, 0x48, 0x58, 0x7e, 0xe8, 0x72, 0x3f, 0x6a,
0x98, 0x7d, 0x35, 0x82, 0xba, 0x79, 0x6a, 0xf9, 0x6f, 0x62, 0xc1, 0x1d, 0x57, 0x70, 0x3b, 0x0a,
0x19, 0xe0, 0x33, 0x38, 0x99, 0x5a, 0xde, 0x24, 0x10, 0x53, 0xee, 0xc4, 0x82, 0xcf, 0xbc, 0x37,
0xec, 0x08, 0x4f, 0x81, 0xd9, 0x81, 0xef, 0x73, 0x3b, 0x72, 0x03, 0xbf, 0x69, 0x71, 0x3c, 0xfc,
0xc7, 0x80, 0x93, 0x9d, 0x5a, 0x82, 0x7e, 0x5f, 0x53, 0x2d, 0xf1, 0x27, 0xe8, 0x4c, 0x49, 0xde,
0x95, 0xa9, 0xa9, 0x0d, 0xf4, 0xd1, 0xa7, 0xaf, 0x46, 0xe3, 0xbd, 0xba, 0xe3, 0x47, 0xdc, 0x71,
0xf3, 0xbb, 0xe5, 0x8b, 0xe6, 0x1c, 0x32, 0x30, 0xe6, 0x55, 0x6e, 0xea, 0x03, 0x7d, 0xd4, 0x17,
0x2a, 0xc4, 0x1f, 0xa1, 0x73, 0x47, 0x49, 0x4a, 0x95, 0x69, 0x0c, 0x8c, 0x11, 0xbc, 0xfa, 0xea,
0x23, 0x3d, 0xaf, 0x36, 0x44, 0xd1, 0x1c, 0xc0, 0x17, 0xd0, 0x9d, 0x25, 0xf7, 0x79, 0x99, 0xa4,
0x66, 0x67, 0xa0, 0x8d, 0x8e, 0x2f, 0xf5, 0x9e, 0x26, 0x76, 0x10, 0x8e, 0xe1, 0x64, 0x52, 0xe6,
0x79, 0xf9, 0x87, 0xa0, 0x34, 0xab, 0x68, 0x21, 0x6b, 0xb3, 0x3b, 0xd0, 0x46, 0xbd, 0x8b, 0x96,
0xac, 0xd6, 0x24, 0x1e, 0x17, 0xf1, 0x39, 0xf4, 0x1c, 0x4a, 0xd2, 0x3c, 0x2b, 0xc8, 0xec, 0x0d,
0xb4, 0x91, 0x26, 0xf6, 0x39, 0xfe, 0x0c, 0x5f, 0x4c, 0xd7, 0xb5, 0xbc, 0x49, 0xf2, 0x2c, 0x4d,
0x24, 0xa9, 0xed, 0xa1, 0xca, 0xa6, 0x4a, 0x66, 0xb7, 0xd9, 0x22, 0x91, 0x64, 0xf6, 0xdf, 0xeb,
0xfc, 0x71, 0xea, 0xf3, 0x97, 0xd0, 0xd9, 0xfe, 0x0f, 0x25, 0xc6, 0x35, 0xdd, 0x9b, 0xad, 0xad,
0x18, 0xd7, 0x74, 0x8f, 0xa7, 0xd0, 0xbe, 0x49, 0xf2, 0x35, 0x99, 0xed, 0x0d, 0xb6, 0x4d, 0x86,
0x1e, 0x3c, 0x79, 0xa0, 0x26, 0x76, 0xc1, 0x78, 0xcd, 0x23, 0xa6, 0x61, 0x0f, 0x5a, 0xb3, 0x20,
0x8c, 0x98, 0xae, 0xa2, 0x2b, 0x6e, 0x39, 0xcc, 0x50, 0xc5, 0xd9, 0x3c, 0x62, 0x2d, 0xb5, 0x2e,
0x0e, 0xf7, 0x78, 0xc4, 0x59, 0x1b, 0xfb, 0xd0, 0x9e, 0x59, 0x91, 0x7d, 0xc5, 0x3a, 0xc3, 0x7f,
0x0d, 0x60, 0xef, 0x84, 0xad, 0x57, 0x65, 0x51, 0x13, 0x9a, 0xd0, 0xb5, 0xcb, 0x42, 0x52, 0x21,
0x4d, 0x4d, 0x49, 0x29, 0x76, 0x29, 0x7e, 0x09, 0x10, 0xca, 0x44, 0xae, 0x6b, 0xf5, 0x71, 0x6c,
0x8c, 0x6b, 0x8b, 0xf7, 0x10, 0xbc, 0x78, 0xe4, 0xdf, 0xf0, 0xa0, 0x7f, 0xdb, 0x6b, 0x1e, 0x1b,
0xf8, 0x03, 0x3c, 0x6b, 0xae, 0xf9, 0x25, 0xa9, 0xa3, 0x6a, 0x5d, 0x28, 0x81, 0xb6, 0x66, 0xf6,
0x2e, 0xda, 0xb7, 0x49, 0x5e, 0x93, 0x38, 0xc4, 0xc0, 0x6f, 0xe0, 0x29, 0xff, 0x73, 0xfb, 0x02,
0x5c, 0xde, 0x4b, 0xaa, 0x43, 0x35, 0xb8, 0x72, 0xd7, 0x10, 0x1f, 0x16, 0xf0, 0x7b, 0x38, 0x7b,
0x00, 0x0a, 0x5a, 0x50, 0xf6, 0x96, 0xd2, 0x8d, 0xcd, 0x86, 0x38, 0x5c, 0x54, 0xfb, 0x30, 0xc9,
0x8a, 0x24, 0x57, 0xfb, 0xaa, 0xec, 0xed, 0x8b, 0x7d, 0x8e, 0xdf, 0x01, 0x5a, 0xab, 0xcc, 0x5e,
0xad, 0xa7, 0x59, 0x9e, 0x67, 0x35, 0x2d, 0xca, 0x22, 0xad, 0x4d, 0x50, 0xed, 0x2e, 0xb4, 0x97,
0xe2, 0x40, 0x11, 0xbf, 0x86, 0x63, 0x6b, 0x95, 0xbd, 0x9b, 0xf6, 0x68, 0x47, 0x7e, 0x00, 0xe3,
0xb7, 0xc0, 0x76, 0xf9, 0x7e, 0xcc, 0xe3, 0x1d, 0xf5, 0x83, 0xd2, 0xff, 0x5f, 0xa6, 0x4b, 0xf8,
0xad, 0xb7, 0x7b, 0x2a, 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x1d, 0x9f, 0x6d, 0x24, 0x63, 0x05,
0x00, 0x00,
}

View file

@ -0,0 +1,64 @@
syntax = "proto2";
option go_package = "urlfetch";
package appengine;
message URLFetchServiceError {
enum ErrorCode {
OK = 0;
INVALID_URL = 1;
FETCH_ERROR = 2;
UNSPECIFIED_ERROR = 3;
RESPONSE_TOO_LARGE = 4;
DEADLINE_EXCEEDED = 5;
SSL_CERTIFICATE_ERROR = 6;
DNS_ERROR = 7;
CLOSED = 8;
INTERNAL_TRANSIENT_ERROR = 9;
TOO_MANY_REDIRECTS = 10;
MALFORMED_REPLY = 11;
CONNECTION_ERROR = 12;
}
}
message URLFetchRequest {
enum RequestMethod {
GET = 1;
POST = 2;
HEAD = 3;
PUT = 4;
DELETE = 5;
PATCH = 6;
}
required RequestMethod Method = 1;
required string Url = 2;
repeated group Header = 3 {
required string Key = 4;
required string Value = 5;
}
optional bytes Payload = 6 [ctype=CORD];
optional bool FollowRedirects = 7 [default=true];
optional double Deadline = 8;
optional bool MustValidateServerCertificate = 9 [default=true];
}
message URLFetchResponse {
optional bytes Content = 1;
required int32 StatusCode = 2;
repeated group Header = 3 {
required string Key = 4;
required string Value = 5;
}
optional bool ContentWasTruncated = 6 [default=false];
optional int64 ExternalBytesSent = 7;
optional int64 ExternalBytesReceived = 8;
optional string FinalUrl = 9;
optional int64 ApiCpuMilliseconds = 10 [default=0];
optional int64 ApiBytesSent = 11 [default=0];
optional int64 ApiBytesReceived = 12 [default=0];
}

210
vendor/google.golang.org/appengine/urlfetch/urlfetch.go generated vendored Normal file
View file

@ -0,0 +1,210 @@
// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.
// Package urlfetch provides an http.RoundTripper implementation
// for fetching URLs via App Engine's urlfetch service.
package urlfetch // import "google.golang.org/appengine/urlfetch"
import (
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"strconv"
"strings"
"time"
"github.com/golang/protobuf/proto"
"golang.org/x/net/context"
"google.golang.org/appengine/internal"
pb "google.golang.org/appengine/internal/urlfetch"
)
// Transport is an implementation of http.RoundTripper for
// App Engine. Users should generally create an http.Client using
// this transport and use the Client rather than using this transport
// directly.
type Transport struct {
Context context.Context
// Controls whether the application checks the validity of SSL certificates
// over HTTPS connections. A value of false (the default) instructs the
// application to send a request to the server only if the certificate is
// valid and signed by a trusted certificate authority (CA), and also
// includes a hostname that matches the certificate. A value of true
// instructs the application to perform no certificate validation.
AllowInvalidServerCertificate bool
}
// Verify statically that *Transport implements http.RoundTripper.
var _ http.RoundTripper = (*Transport)(nil)
// Client returns an *http.Client using a default urlfetch Transport. This
// client will have the default deadline of 5 seconds, and will check the
// validity of SSL certificates.
//
// Any deadline of the provided context will be used for requests through this client;
// if the client does not have a deadline then a 5 second default is used.
func Client(ctx context.Context) *http.Client {
return &http.Client{
Transport: &Transport{
Context: ctx,
},
}
}
type bodyReader struct {
content []byte
truncated bool
closed bool
}
// ErrTruncatedBody is the error returned after the final Read() from a
// response's Body if the body has been truncated by App Engine's proxy.
var ErrTruncatedBody = errors.New("urlfetch: truncated body")
func statusCodeToText(code int) string {
if t := http.StatusText(code); t != "" {
return t
}
return strconv.Itoa(code)
}
func (br *bodyReader) Read(p []byte) (n int, err error) {
if br.closed {
if br.truncated {
return 0, ErrTruncatedBody
}
return 0, io.EOF
}
n = copy(p, br.content)
if n > 0 {
br.content = br.content[n:]
return
}
if br.truncated {
br.closed = true
return 0, ErrTruncatedBody
}
return 0, io.EOF
}
func (br *bodyReader) Close() error {
br.closed = true
br.content = nil
return nil
}
// A map of the URL Fetch-accepted methods that take a request body.
var methodAcceptsRequestBody = map[string]bool{
"POST": true,
"PUT": true,
"PATCH": true,
}
// urlString returns a valid string given a URL. This function is necessary because
// the String method of URL doesn't correctly handle URLs with non-empty Opaque values.
// See http://code.google.com/p/go/issues/detail?id=4860.
func urlString(u *url.URL) string {
if u.Opaque == "" || strings.HasPrefix(u.Opaque, "//") {
return u.String()
}
aux := *u
aux.Opaque = "//" + aux.Host + aux.Opaque
return aux.String()
}
// RoundTrip issues a single HTTP request and returns its response. Per the
// http.RoundTripper interface, RoundTrip only returns an error if there
// was an unsupported request or the URL Fetch proxy fails.
// Note that HTTP response codes such as 5xx, 403, 404, etc are not
// errors as far as the transport is concerned and will be returned
// with err set to nil.
func (t *Transport) RoundTrip(req *http.Request) (res *http.Response, err error) {
methNum, ok := pb.URLFetchRequest_RequestMethod_value[req.Method]
if !ok {
return nil, fmt.Errorf("urlfetch: unsupported HTTP method %q", req.Method)
}
method := pb.URLFetchRequest_RequestMethod(methNum)
freq := &pb.URLFetchRequest{
Method: &method,
Url: proto.String(urlString(req.URL)),
FollowRedirects: proto.Bool(false), // http.Client's responsibility
MustValidateServerCertificate: proto.Bool(!t.AllowInvalidServerCertificate),
}
if deadline, ok := t.Context.Deadline(); ok {
freq.Deadline = proto.Float64(deadline.Sub(time.Now()).Seconds())
}
for k, vals := range req.Header {
for _, val := range vals {
freq.Header = append(freq.Header, &pb.URLFetchRequest_Header{
Key: proto.String(k),
Value: proto.String(val),
})
}
}
if methodAcceptsRequestBody[req.Method] && req.Body != nil {
// Avoid a []byte copy if req.Body has a Bytes method.
switch b := req.Body.(type) {
case interface {
Bytes() []byte
}:
freq.Payload = b.Bytes()
default:
freq.Payload, err = ioutil.ReadAll(req.Body)
if err != nil {
return nil, err
}
}
}
fres := &pb.URLFetchResponse{}
if err := internal.Call(t.Context, "urlfetch", "Fetch", freq, fres); err != nil {
return nil, err
}
res = &http.Response{}
res.StatusCode = int(*fres.StatusCode)
res.Status = fmt.Sprintf("%d %s", res.StatusCode, statusCodeToText(res.StatusCode))
res.Header = make(http.Header)
res.Request = req
// Faked:
res.ProtoMajor = 1
res.ProtoMinor = 1
res.Proto = "HTTP/1.1"
res.Close = true
for _, h := range fres.Header {
hkey := http.CanonicalHeaderKey(*h.Key)
hval := *h.Value
if hkey == "Content-Length" {
// Will get filled in below for all but HEAD requests.
if req.Method == "HEAD" {
res.ContentLength, _ = strconv.ParseInt(hval, 10, 64)
}
continue
}
res.Header.Add(hkey, hval)
}
if req.Method != "HEAD" {
res.ContentLength = int64(len(fres.Content))
}
truncated := fres.GetContentWasTruncated()
res.Body = &bodyReader{content: fres.Content, truncated: truncated}
return
}
func init() {
internal.RegisterErrorCodeMap("urlfetch", pb.URLFetchServiceError_ErrorCode_name)
internal.RegisterTimeoutErrorCode("urlfetch", int32(pb.URLFetchServiceError_DEADLINE_EXCEEDED))
}