Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 

450 wiersze
12 KiB

  1. /*
  2. *
  3. * Copyright 2016 gRPC authors.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. // This file is the implementation of a gRPC server using HTTP/2 which
  19. // uses the standard Go http2 Server implementation (via the
  20. // http.Handler interface), rather than speaking low-level HTTP/2
  21. // frames itself. It is the implementation of *grpc.Server.ServeHTTP.
  22. package transport
  23. import (
  24. "context"
  25. "errors"
  26. "fmt"
  27. "io"
  28. "net"
  29. "net/http"
  30. "strings"
  31. "sync"
  32. "time"
  33. "github.com/golang/protobuf/proto"
  34. "golang.org/x/net/http2"
  35. "google.golang.org/grpc/codes"
  36. "google.golang.org/grpc/credentials"
  37. "google.golang.org/grpc/metadata"
  38. "google.golang.org/grpc/peer"
  39. "google.golang.org/grpc/stats"
  40. "google.golang.org/grpc/status"
  41. )
  42. // NewServerHandlerTransport returns a ServerTransport handling gRPC
  43. // from inside an http.Handler. It requires that the http Server
  44. // supports HTTP/2.
  45. func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request, stats stats.Handler) (ServerTransport, error) {
  46. if r.ProtoMajor != 2 {
  47. return nil, errors.New("gRPC requires HTTP/2")
  48. }
  49. if r.Method != "POST" {
  50. return nil, errors.New("invalid gRPC request method")
  51. }
  52. contentType := r.Header.Get("Content-Type")
  53. // TODO: do we assume contentType is lowercase? we did before
  54. contentSubtype, validContentType := contentSubtype(contentType)
  55. if !validContentType {
  56. return nil, errors.New("invalid gRPC request content-type")
  57. }
  58. if _, ok := w.(http.Flusher); !ok {
  59. return nil, errors.New("gRPC requires a ResponseWriter supporting http.Flusher")
  60. }
  61. if _, ok := w.(http.CloseNotifier); !ok {
  62. return nil, errors.New("gRPC requires a ResponseWriter supporting http.CloseNotifier")
  63. }
  64. st := &serverHandlerTransport{
  65. rw: w,
  66. req: r,
  67. closedCh: make(chan struct{}),
  68. writes: make(chan func()),
  69. contentType: contentType,
  70. contentSubtype: contentSubtype,
  71. stats: stats,
  72. }
  73. if v := r.Header.Get("grpc-timeout"); v != "" {
  74. to, err := decodeTimeout(v)
  75. if err != nil {
  76. return nil, status.Errorf(codes.Internal, "malformed time-out: %v", err)
  77. }
  78. st.timeoutSet = true
  79. st.timeout = to
  80. }
  81. metakv := []string{"content-type", contentType}
  82. if r.Host != "" {
  83. metakv = append(metakv, ":authority", r.Host)
  84. }
  85. for k, vv := range r.Header {
  86. k = strings.ToLower(k)
  87. if isReservedHeader(k) && !isWhitelistedHeader(k) {
  88. continue
  89. }
  90. for _, v := range vv {
  91. v, err := decodeMetadataHeader(k, v)
  92. if err != nil {
  93. return nil, status.Errorf(codes.Internal, "malformed binary metadata: %v", err)
  94. }
  95. metakv = append(metakv, k, v)
  96. }
  97. }
  98. st.headerMD = metadata.Pairs(metakv...)
  99. return st, nil
  100. }
  101. // serverHandlerTransport is an implementation of ServerTransport
  102. // which replies to exactly one gRPC request (exactly one HTTP request),
  103. // using the net/http.Handler interface. This http.Handler is guaranteed
  104. // at this point to be speaking over HTTP/2, so it's able to speak valid
  105. // gRPC.
  106. type serverHandlerTransport struct {
  107. rw http.ResponseWriter
  108. req *http.Request
  109. timeoutSet bool
  110. timeout time.Duration
  111. didCommonHeaders bool
  112. headerMD metadata.MD
  113. closeOnce sync.Once
  114. closedCh chan struct{} // closed on Close
  115. // writes is a channel of code to run serialized in the
  116. // ServeHTTP (HandleStreams) goroutine. The channel is closed
  117. // when WriteStatus is called.
  118. writes chan func()
  119. // block concurrent WriteStatus calls
  120. // e.g. grpc/(*serverStream).SendMsg/RecvMsg
  121. writeStatusMu sync.Mutex
  122. // we just mirror the request content-type
  123. contentType string
  124. // we store both contentType and contentSubtype so we don't keep recreating them
  125. // TODO make sure this is consistent across handler_server and http2_server
  126. contentSubtype string
  127. stats stats.Handler
  128. }
  129. func (ht *serverHandlerTransport) Close() error {
  130. ht.closeOnce.Do(ht.closeCloseChanOnce)
  131. return nil
  132. }
  133. func (ht *serverHandlerTransport) closeCloseChanOnce() { close(ht.closedCh) }
  134. func (ht *serverHandlerTransport) RemoteAddr() net.Addr { return strAddr(ht.req.RemoteAddr) }
  135. // strAddr is a net.Addr backed by either a TCP "ip:port" string, or
  136. // the empty string if unknown.
  137. type strAddr string
  138. func (a strAddr) Network() string {
  139. if a != "" {
  140. // Per the documentation on net/http.Request.RemoteAddr, if this is
  141. // set, it's set to the IP:port of the peer (hence, TCP):
  142. // https://golang.org/pkg/net/http/#Request
  143. //
  144. // If we want to support Unix sockets later, we can
  145. // add our own grpc-specific convention within the
  146. // grpc codebase to set RemoteAddr to a different
  147. // format, or probably better: we can attach it to the
  148. // context and use that from serverHandlerTransport.RemoteAddr.
  149. return "tcp"
  150. }
  151. return ""
  152. }
  153. func (a strAddr) String() string { return string(a) }
  154. // do runs fn in the ServeHTTP goroutine.
  155. func (ht *serverHandlerTransport) do(fn func()) error {
  156. // Avoid a panic writing to closed channel. Imperfect but maybe good enough.
  157. select {
  158. case <-ht.closedCh:
  159. return ErrConnClosing
  160. default:
  161. select {
  162. case ht.writes <- fn:
  163. return nil
  164. case <-ht.closedCh:
  165. return ErrConnClosing
  166. }
  167. }
  168. }
  169. func (ht *serverHandlerTransport) WriteStatus(s *Stream, st *status.Status) error {
  170. ht.writeStatusMu.Lock()
  171. defer ht.writeStatusMu.Unlock()
  172. err := ht.do(func() {
  173. ht.writeCommonHeaders(s)
  174. // And flush, in case no header or body has been sent yet.
  175. // This forces a separation of headers and trailers if this is the
  176. // first call (for example, in end2end tests's TestNoService).
  177. ht.rw.(http.Flusher).Flush()
  178. h := ht.rw.Header()
  179. h.Set("Grpc-Status", fmt.Sprintf("%d", st.Code()))
  180. if m := st.Message(); m != "" {
  181. h.Set("Grpc-Message", encodeGrpcMessage(m))
  182. }
  183. if p := st.Proto(); p != nil && len(p.Details) > 0 {
  184. stBytes, err := proto.Marshal(p)
  185. if err != nil {
  186. // TODO: return error instead, when callers are able to handle it.
  187. panic(err)
  188. }
  189. h.Set("Grpc-Status-Details-Bin", encodeBinHeader(stBytes))
  190. }
  191. if md := s.Trailer(); len(md) > 0 {
  192. for k, vv := range md {
  193. // Clients don't tolerate reading restricted headers after some non restricted ones were sent.
  194. if isReservedHeader(k) {
  195. continue
  196. }
  197. for _, v := range vv {
  198. // http2 ResponseWriter mechanism to send undeclared Trailers after
  199. // the headers have possibly been written.
  200. h.Add(http2.TrailerPrefix+k, encodeMetadataHeader(k, v))
  201. }
  202. }
  203. }
  204. })
  205. if err == nil { // transport has not been closed
  206. if ht.stats != nil {
  207. ht.stats.HandleRPC(s.Context(), &stats.OutTrailer{})
  208. }
  209. close(ht.writes)
  210. }
  211. ht.Close()
  212. return err
  213. }
  214. // writeCommonHeaders sets common headers on the first write
  215. // call (Write, WriteHeader, or WriteStatus).
  216. func (ht *serverHandlerTransport) writeCommonHeaders(s *Stream) {
  217. if ht.didCommonHeaders {
  218. return
  219. }
  220. ht.didCommonHeaders = true
  221. h := ht.rw.Header()
  222. h["Date"] = nil // suppress Date to make tests happy; TODO: restore
  223. h.Set("Content-Type", ht.contentType)
  224. // Predeclare trailers we'll set later in WriteStatus (after the body).
  225. // This is a SHOULD in the HTTP RFC, and the way you add (known)
  226. // Trailers per the net/http.ResponseWriter contract.
  227. // See https://golang.org/pkg/net/http/#ResponseWriter
  228. // and https://golang.org/pkg/net/http/#example_ResponseWriter_trailers
  229. h.Add("Trailer", "Grpc-Status")
  230. h.Add("Trailer", "Grpc-Message")
  231. h.Add("Trailer", "Grpc-Status-Details-Bin")
  232. if s.sendCompress != "" {
  233. h.Set("Grpc-Encoding", s.sendCompress)
  234. }
  235. }
  236. func (ht *serverHandlerTransport) Write(s *Stream, hdr []byte, data []byte, opts *Options) error {
  237. return ht.do(func() {
  238. ht.writeCommonHeaders(s)
  239. ht.rw.Write(hdr)
  240. ht.rw.Write(data)
  241. ht.rw.(http.Flusher).Flush()
  242. })
  243. }
  244. func (ht *serverHandlerTransport) WriteHeader(s *Stream, md metadata.MD) error {
  245. err := ht.do(func() {
  246. ht.writeCommonHeaders(s)
  247. h := ht.rw.Header()
  248. for k, vv := range md {
  249. // Clients don't tolerate reading restricted headers after some non restricted ones were sent.
  250. if isReservedHeader(k) {
  251. continue
  252. }
  253. for _, v := range vv {
  254. v = encodeMetadataHeader(k, v)
  255. h.Add(k, v)
  256. }
  257. }
  258. ht.rw.WriteHeader(200)
  259. ht.rw.(http.Flusher).Flush()
  260. })
  261. if err == nil {
  262. if ht.stats != nil {
  263. ht.stats.HandleRPC(s.Context(), &stats.OutHeader{})
  264. }
  265. }
  266. return err
  267. }
  268. func (ht *serverHandlerTransport) HandleStreams(startStream func(*Stream), traceCtx func(context.Context, string) context.Context) {
  269. // With this transport type there will be exactly 1 stream: this HTTP request.
  270. ctx := ht.req.Context()
  271. var cancel context.CancelFunc
  272. if ht.timeoutSet {
  273. ctx, cancel = context.WithTimeout(ctx, ht.timeout)
  274. } else {
  275. ctx, cancel = context.WithCancel(ctx)
  276. }
  277. // requestOver is closed when either the request's context is done
  278. // or the status has been written via WriteStatus.
  279. requestOver := make(chan struct{})
  280. // clientGone receives a single value if peer is gone, either
  281. // because the underlying connection is dead or because the
  282. // peer sends an http2 RST_STREAM.
  283. clientGone := ht.rw.(http.CloseNotifier).CloseNotify()
  284. go func() {
  285. select {
  286. case <-requestOver:
  287. case <-ht.closedCh:
  288. case <-clientGone:
  289. }
  290. cancel()
  291. ht.Close()
  292. }()
  293. req := ht.req
  294. s := &Stream{
  295. id: 0, // irrelevant
  296. requestRead: func(int) {},
  297. cancel: cancel,
  298. buf: newRecvBuffer(),
  299. st: ht,
  300. method: req.URL.Path,
  301. recvCompress: req.Header.Get("grpc-encoding"),
  302. contentSubtype: ht.contentSubtype,
  303. }
  304. pr := &peer.Peer{
  305. Addr: ht.RemoteAddr(),
  306. }
  307. if req.TLS != nil {
  308. pr.AuthInfo = credentials.TLSInfo{State: *req.TLS}
  309. }
  310. ctx = metadata.NewIncomingContext(ctx, ht.headerMD)
  311. s.ctx = peer.NewContext(ctx, pr)
  312. if ht.stats != nil {
  313. s.ctx = ht.stats.TagRPC(s.ctx, &stats.RPCTagInfo{FullMethodName: s.method})
  314. inHeader := &stats.InHeader{
  315. FullMethod: s.method,
  316. RemoteAddr: ht.RemoteAddr(),
  317. Compression: s.recvCompress,
  318. }
  319. ht.stats.HandleRPC(s.ctx, inHeader)
  320. }
  321. s.trReader = &transportReader{
  322. reader: &recvBufferReader{ctx: s.ctx, ctxDone: s.ctx.Done(), recv: s.buf},
  323. windowHandler: func(int) {},
  324. }
  325. // readerDone is closed when the Body.Read-ing goroutine exits.
  326. readerDone := make(chan struct{})
  327. go func() {
  328. defer close(readerDone)
  329. // TODO: minimize garbage, optimize recvBuffer code/ownership
  330. const readSize = 8196
  331. for buf := make([]byte, readSize); ; {
  332. n, err := req.Body.Read(buf)
  333. if n > 0 {
  334. s.buf.put(recvMsg{data: buf[:n:n]})
  335. buf = buf[n:]
  336. }
  337. if err != nil {
  338. s.buf.put(recvMsg{err: mapRecvMsgError(err)})
  339. return
  340. }
  341. if len(buf) == 0 {
  342. buf = make([]byte, readSize)
  343. }
  344. }
  345. }()
  346. // startStream is provided by the *grpc.Server's serveStreams.
  347. // It starts a goroutine serving s and exits immediately.
  348. // The goroutine that is started is the one that then calls
  349. // into ht, calling WriteHeader, Write, WriteStatus, Close, etc.
  350. startStream(s)
  351. ht.runStream()
  352. close(requestOver)
  353. // Wait for reading goroutine to finish.
  354. req.Body.Close()
  355. <-readerDone
  356. }
  357. func (ht *serverHandlerTransport) runStream() {
  358. for {
  359. select {
  360. case fn, ok := <-ht.writes:
  361. if !ok {
  362. return
  363. }
  364. fn()
  365. case <-ht.closedCh:
  366. return
  367. }
  368. }
  369. }
  370. func (ht *serverHandlerTransport) IncrMsgSent() {}
  371. func (ht *serverHandlerTransport) IncrMsgRecv() {}
  372. func (ht *serverHandlerTransport) Drain() {
  373. panic("Drain() is not implemented")
  374. }
  375. // mapRecvMsgError returns the non-nil err into the appropriate
  376. // error value as expected by callers of *grpc.parser.recvMsg.
  377. // In particular, in can only be:
  378. // * io.EOF
  379. // * io.ErrUnexpectedEOF
  380. // * of type transport.ConnectionError
  381. // * an error from the status package
  382. func mapRecvMsgError(err error) error {
  383. if err == io.EOF || err == io.ErrUnexpectedEOF {
  384. return err
  385. }
  386. if se, ok := err.(http2.StreamError); ok {
  387. if code, ok := http2ErrConvTab[se.Code]; ok {
  388. return status.Error(code, se.Error())
  389. }
  390. }
  391. if strings.Contains(err.Error(), "body closed by handler") {
  392. return status.Error(codes.Canceled, err.Error())
  393. }
  394. return connectionErrorf(true, err, err.Error())
  395. }