equal
deleted
inserted
replaced
1 // Copyright 2011 Google Inc. All rights reserved. |
1 // Copyright 2011 Google Inc. All rights reserved. |
2 // Use of this source code is governed by the Apache 2.0 |
2 // Use of this source code is governed by the Apache 2.0 |
3 // license that can be found in the LICENSE file. |
3 // license that can be found in the LICENSE file. |
4 |
4 |
5 // +build !appengine |
5 // +build !appengine |
6 // +build go1.7 |
|
7 |
6 |
8 package internal |
7 package internal |
9 |
8 |
10 import ( |
9 import ( |
11 "bytes" |
10 "bytes" |
43 dapperHeader = http.CanonicalHeaderKey("X-Google-DapperTraceInfo") |
42 dapperHeader = http.CanonicalHeaderKey("X-Google-DapperTraceInfo") |
44 traceHeader = http.CanonicalHeaderKey("X-Cloud-Trace-Context") |
43 traceHeader = http.CanonicalHeaderKey("X-Cloud-Trace-Context") |
45 curNamespaceHeader = http.CanonicalHeaderKey("X-AppEngine-Current-Namespace") |
44 curNamespaceHeader = http.CanonicalHeaderKey("X-AppEngine-Current-Namespace") |
46 userIPHeader = http.CanonicalHeaderKey("X-AppEngine-User-IP") |
45 userIPHeader = http.CanonicalHeaderKey("X-AppEngine-User-IP") |
47 remoteAddrHeader = http.CanonicalHeaderKey("X-AppEngine-Remote-Addr") |
46 remoteAddrHeader = http.CanonicalHeaderKey("X-AppEngine-Remote-Addr") |
|
47 devRequestIdHeader = http.CanonicalHeaderKey("X-Appengine-Dev-Request-Id") |
48 |
48 |
49 // Outgoing headers. |
49 // Outgoing headers. |
50 apiEndpointHeader = http.CanonicalHeaderKey("X-Google-RPC-Service-Endpoint") |
50 apiEndpointHeader = http.CanonicalHeaderKey("X-Google-RPC-Service-Endpoint") |
51 apiEndpointHeaderValue = []string{"app-engine-apis"} |
51 apiEndpointHeaderValue = []string{"app-engine-apis"} |
52 apiMethodHeader = http.CanonicalHeaderKey("X-Google-RPC-Service-Method") |
52 apiMethodHeader = http.CanonicalHeaderKey("X-Google-RPC-Service-Method") |
128 flushes := c.pendingLogs.flushes |
128 flushes := c.pendingLogs.flushes |
129 if len(c.pendingLogs.lines) > 0 { |
129 if len(c.pendingLogs.lines) > 0 { |
130 flushes++ |
130 flushes++ |
131 } |
131 } |
132 c.pendingLogs.Unlock() |
132 c.pendingLogs.Unlock() |
133 go c.flushLog(false) |
133 flushed := make(chan struct{}) |
|
134 go func() { |
|
135 defer close(flushed) |
|
136 // Force a log flush, because with very short requests we |
|
137 // may not ever flush logs. |
|
138 c.flushLog(true) |
|
139 }() |
134 w.Header().Set(logFlushHeader, strconv.Itoa(flushes)) |
140 w.Header().Set(logFlushHeader, strconv.Itoa(flushes)) |
135 |
141 |
136 // Avoid nil Write call if c.Write is never called. |
142 // Avoid nil Write call if c.Write is never called. |
137 if c.outCode != 0 { |
143 if c.outCode != 0 { |
138 w.WriteHeader(c.outCode) |
144 w.WriteHeader(c.outCode) |
139 } |
145 } |
140 if c.outBody != nil { |
146 if c.outBody != nil { |
141 w.Write(c.outBody) |
147 w.Write(c.outBody) |
142 } |
148 } |
|
149 // Wait for the last flush to complete before returning, |
|
150 // otherwise the security ticket will not be valid. |
|
151 <-flushed |
143 } |
152 } |
144 |
153 |
145 func executeRequestSafely(c *context, r *http.Request) { |
154 func executeRequestSafely(c *context, r *http.Request) { |
146 defer func() { |
155 defer func() { |
147 if x := recover(); x != nil { |
156 if x := recover(); x != nil { |
484 } |
493 } |
485 // Fall back to use background ticket when the request ticket is not available in Flex or dev_appserver. |
494 // Fall back to use background ticket when the request ticket is not available in Flex or dev_appserver. |
486 if ticket == "" { |
495 if ticket == "" { |
487 ticket = DefaultTicket() |
496 ticket = DefaultTicket() |
488 } |
497 } |
|
498 if dri := c.req.Header.Get(devRequestIdHeader); IsDevAppServer() && dri != "" { |
|
499 ticket = dri |
|
500 } |
489 req := &remotepb.Request{ |
501 req := &remotepb.Request{ |
490 ServiceName: &service, |
502 ServiceName: &service, |
491 Method: &method, |
503 Method: &method, |
492 Request: data, |
504 Request: data, |
493 RequestId: &ticket, |
505 RequestId: &ticket, |
569 c.addLogLine(&logpb.UserAppLogLine{ |
581 c.addLogLine(&logpb.UserAppLogLine{ |
570 TimestampUsec: proto.Int64(time.Now().UnixNano() / 1e3), |
582 TimestampUsec: proto.Int64(time.Now().UnixNano() / 1e3), |
571 Level: &level, |
583 Level: &level, |
572 Message: &s, |
584 Message: &s, |
573 }) |
585 }) |
574 log.Print(logLevelName[level] + ": " + s) |
586 // Only duplicate log to stderr if not running on App Engine second generation |
|
587 if !IsSecondGen() { |
|
588 log.Print(logLevelName[level] + ": " + s) |
|
589 } |
575 } |
590 } |
576 |
591 |
577 // flushLog attempts to flush any pending logs to the appserver. |
592 // flushLog attempts to flush any pending logs to the appserver. |
578 // It should not be called concurrently. |
593 // It should not be called concurrently. |
579 func (c *context) flushLog(force bool) (flushed bool) { |
594 func (c *context) flushLog(force bool) (flushed bool) { |