http_util.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. /*
  2. *
  3. * Copyright 2014 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. package transport
  19. import (
  20. "bufio"
  21. "bytes"
  22. "encoding/base64"
  23. "fmt"
  24. "io"
  25. "math"
  26. "net"
  27. "net/http"
  28. "strconv"
  29. "strings"
  30. "time"
  31. "unicode/utf8"
  32. "github.com/golang/protobuf/proto"
  33. "golang.org/x/net/http2"
  34. "golang.org/x/net/http2/hpack"
  35. spb "google.golang.org/genproto/googleapis/rpc/status"
  36. "google.golang.org/grpc/codes"
  37. "google.golang.org/grpc/grpclog"
  38. "google.golang.org/grpc/internal/grpcutil"
  39. "google.golang.org/grpc/status"
  40. )
  41. const (
  42. // http2MaxFrameLen specifies the max length of a HTTP2 frame.
  43. http2MaxFrameLen = 16384 // 16KB frame
  44. // http://http2.github.io/http2-spec/#SettingValues
  45. http2InitHeaderTableSize = 4096
  46. // baseContentType is the base content-type for gRPC. This is a valid
  47. // content-type on it's own, but can also include a content-subtype such as
  48. // "proto" as a suffix after "+" or ";". See
  49. // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests
  50. // for more details.
  51. )
  52. var (
  53. clientPreface = []byte(http2.ClientPreface)
  54. http2ErrConvTab = map[http2.ErrCode]codes.Code{
  55. http2.ErrCodeNo: codes.Internal,
  56. http2.ErrCodeProtocol: codes.Internal,
  57. http2.ErrCodeInternal: codes.Internal,
  58. http2.ErrCodeFlowControl: codes.ResourceExhausted,
  59. http2.ErrCodeSettingsTimeout: codes.Internal,
  60. http2.ErrCodeStreamClosed: codes.Internal,
  61. http2.ErrCodeFrameSize: codes.Internal,
  62. http2.ErrCodeRefusedStream: codes.Unavailable,
  63. http2.ErrCodeCancel: codes.Canceled,
  64. http2.ErrCodeCompression: codes.Internal,
  65. http2.ErrCodeConnect: codes.Internal,
  66. http2.ErrCodeEnhanceYourCalm: codes.ResourceExhausted,
  67. http2.ErrCodeInadequateSecurity: codes.PermissionDenied,
  68. http2.ErrCodeHTTP11Required: codes.Internal,
  69. }
  70. statusCodeConvTab = map[codes.Code]http2.ErrCode{
  71. codes.Internal: http2.ErrCodeInternal,
  72. codes.Canceled: http2.ErrCodeCancel,
  73. codes.Unavailable: http2.ErrCodeRefusedStream,
  74. codes.ResourceExhausted: http2.ErrCodeEnhanceYourCalm,
  75. codes.PermissionDenied: http2.ErrCodeInadequateSecurity,
  76. }
  77. // HTTPStatusConvTab is the HTTP status code to gRPC error code conversion table.
  78. HTTPStatusConvTab = map[int]codes.Code{
  79. // 400 Bad Request - INTERNAL.
  80. http.StatusBadRequest: codes.Internal,
  81. // 401 Unauthorized - UNAUTHENTICATED.
  82. http.StatusUnauthorized: codes.Unauthenticated,
  83. // 403 Forbidden - PERMISSION_DENIED.
  84. http.StatusForbidden: codes.PermissionDenied,
  85. // 404 Not Found - UNIMPLEMENTED.
  86. http.StatusNotFound: codes.Unimplemented,
  87. // 429 Too Many Requests - UNAVAILABLE.
  88. http.StatusTooManyRequests: codes.Unavailable,
  89. // 502 Bad Gateway - UNAVAILABLE.
  90. http.StatusBadGateway: codes.Unavailable,
  91. // 503 Service Unavailable - UNAVAILABLE.
  92. http.StatusServiceUnavailable: codes.Unavailable,
  93. // 504 Gateway timeout - UNAVAILABLE.
  94. http.StatusGatewayTimeout: codes.Unavailable,
  95. }
  96. logger = grpclog.Component("transport")
  97. )
  98. type parsedHeaderData struct {
  99. encoding string
  100. // statusGen caches the stream status received from the trailer the server
  101. // sent. Client side only. Do not access directly. After all trailers are
  102. // parsed, use the status method to retrieve the status.
  103. statusGen *status.Status
  104. // rawStatusCode and rawStatusMsg are set from the raw trailer fields and are not
  105. // intended for direct access outside of parsing.
  106. rawStatusCode *int
  107. rawStatusMsg string
  108. httpStatus *int
  109. // Server side only fields.
  110. timeoutSet bool
  111. timeout time.Duration
  112. method string
  113. // key-value metadata map from the peer.
  114. mdata map[string][]string
  115. statsTags []byte
  116. statsTrace []byte
  117. contentSubtype string
  118. // isGRPC field indicates whether the peer is speaking gRPC (otherwise HTTP).
  119. //
  120. // We are in gRPC mode (peer speaking gRPC) if:
  121. // * We are client side and have already received a HEADER frame that indicates gRPC peer.
  122. // * The header contains valid a content-type, i.e. a string starts with "application/grpc"
  123. // And we should handle error specific to gRPC.
  124. //
  125. // Otherwise (i.e. a content-type string starts without "application/grpc", or does not exist), we
  126. // are in HTTP fallback mode, and should handle error specific to HTTP.
  127. isGRPC bool
  128. grpcErr error
  129. httpErr error
  130. contentTypeErr string
  131. }
  132. // decodeState configures decoding criteria and records the decoded data.
  133. type decodeState struct {
  134. // whether decoding on server side or not
  135. serverSide bool
  136. // Records the states during HPACK decoding. It will be filled with info parsed from HTTP HEADERS
  137. // frame once decodeHeader function has been invoked and returned.
  138. data parsedHeaderData
  139. }
  140. // isReservedHeader checks whether hdr belongs to HTTP2 headers
  141. // reserved by gRPC protocol. Any other headers are classified as the
  142. // user-specified metadata.
  143. func isReservedHeader(hdr string) bool {
  144. if hdr != "" && hdr[0] == ':' {
  145. return true
  146. }
  147. switch hdr {
  148. case "content-type",
  149. "user-agent",
  150. "grpc-message-type",
  151. "grpc-encoding",
  152. "grpc-message",
  153. "grpc-status",
  154. "grpc-timeout",
  155. "grpc-status-details-bin",
  156. // Intentionally exclude grpc-previous-rpc-attempts and
  157. // grpc-retry-pushback-ms, which are "reserved", but their API
  158. // intentionally works via metadata.
  159. "te":
  160. return true
  161. default:
  162. return false
  163. }
  164. }
  165. // isWhitelistedHeader checks whether hdr should be propagated into metadata
  166. // visible to users, even though it is classified as "reserved", above.
  167. func isWhitelistedHeader(hdr string) bool {
  168. switch hdr {
  169. case ":authority", "user-agent":
  170. return true
  171. default:
  172. return false
  173. }
  174. }
  175. func (d *decodeState) status() *status.Status {
  176. if d.data.statusGen == nil {
  177. // No status-details were provided; generate status using code/msg.
  178. d.data.statusGen = status.New(codes.Code(int32(*(d.data.rawStatusCode))), d.data.rawStatusMsg)
  179. }
  180. return d.data.statusGen
  181. }
  182. const binHdrSuffix = "-bin"
  183. func encodeBinHeader(v []byte) string {
  184. return base64.RawStdEncoding.EncodeToString(v)
  185. }
  186. func decodeBinHeader(v string) ([]byte, error) {
  187. if len(v)%4 == 0 {
  188. // Input was padded, or padding was not necessary.
  189. return base64.StdEncoding.DecodeString(v)
  190. }
  191. return base64.RawStdEncoding.DecodeString(v)
  192. }
  193. func encodeMetadataHeader(k, v string) string {
  194. if strings.HasSuffix(k, binHdrSuffix) {
  195. return encodeBinHeader(([]byte)(v))
  196. }
  197. return v
  198. }
  199. func decodeMetadataHeader(k, v string) (string, error) {
  200. if strings.HasSuffix(k, binHdrSuffix) {
  201. b, err := decodeBinHeader(v)
  202. return string(b), err
  203. }
  204. return v, nil
  205. }
  206. func (d *decodeState) decodeHeader(frame *http2.MetaHeadersFrame) error {
  207. // frame.Truncated is set to true when framer detects that the current header
  208. // list size hits MaxHeaderListSize limit.
  209. if frame.Truncated {
  210. return status.Error(codes.Internal, "peer header list size exceeded limit")
  211. }
  212. for _, hf := range frame.Fields {
  213. d.processHeaderField(hf)
  214. }
  215. if d.data.isGRPC {
  216. if d.data.grpcErr != nil {
  217. return d.data.grpcErr
  218. }
  219. if d.serverSide {
  220. return nil
  221. }
  222. if d.data.rawStatusCode == nil && d.data.statusGen == nil {
  223. // gRPC status doesn't exist.
  224. // Set rawStatusCode to be unknown and return nil error.
  225. // So that, if the stream has ended this Unknown status
  226. // will be propagated to the user.
  227. // Otherwise, it will be ignored. In which case, status from
  228. // a later trailer, that has StreamEnded flag set, is propagated.
  229. code := int(codes.Unknown)
  230. d.data.rawStatusCode = &code
  231. }
  232. return nil
  233. }
  234. // HTTP fallback mode
  235. if d.data.httpErr != nil {
  236. return d.data.httpErr
  237. }
  238. var (
  239. code = codes.Internal // when header does not include HTTP status, return INTERNAL
  240. ok bool
  241. )
  242. if d.data.httpStatus != nil {
  243. code, ok = HTTPStatusConvTab[*(d.data.httpStatus)]
  244. if !ok {
  245. code = codes.Unknown
  246. }
  247. }
  248. return status.Error(code, d.constructHTTPErrMsg())
  249. }
  250. // constructErrMsg constructs error message to be returned in HTTP fallback mode.
  251. // Format: HTTP status code and its corresponding message + content-type error message.
  252. func (d *decodeState) constructHTTPErrMsg() string {
  253. var errMsgs []string
  254. if d.data.httpStatus == nil {
  255. errMsgs = append(errMsgs, "malformed header: missing HTTP status")
  256. } else {
  257. errMsgs = append(errMsgs, fmt.Sprintf("%s: HTTP status code %d", http.StatusText(*(d.data.httpStatus)), *d.data.httpStatus))
  258. }
  259. if d.data.contentTypeErr == "" {
  260. errMsgs = append(errMsgs, "transport: missing content-type field")
  261. } else {
  262. errMsgs = append(errMsgs, d.data.contentTypeErr)
  263. }
  264. return strings.Join(errMsgs, "; ")
  265. }
  266. func (d *decodeState) addMetadata(k, v string) {
  267. if d.data.mdata == nil {
  268. d.data.mdata = make(map[string][]string)
  269. }
  270. d.data.mdata[k] = append(d.data.mdata[k], v)
  271. }
  272. func (d *decodeState) processHeaderField(f hpack.HeaderField) {
  273. switch f.Name {
  274. case "content-type":
  275. contentSubtype, validContentType := grpcutil.ContentSubtype(f.Value)
  276. if !validContentType {
  277. d.data.contentTypeErr = fmt.Sprintf("transport: received the unexpected content-type %q", f.Value)
  278. return
  279. }
  280. d.data.contentSubtype = contentSubtype
  281. // TODO: do we want to propagate the whole content-type in the metadata,
  282. // or come up with a way to just propagate the content-subtype if it was set?
  283. // ie {"content-type": "application/grpc+proto"} or {"content-subtype": "proto"}
  284. // in the metadata?
  285. d.addMetadata(f.Name, f.Value)
  286. d.data.isGRPC = true
  287. case "grpc-encoding":
  288. d.data.encoding = f.Value
  289. case "grpc-status":
  290. code, err := strconv.Atoi(f.Value)
  291. if err != nil {
  292. d.data.grpcErr = status.Errorf(codes.Internal, "transport: malformed grpc-status: %v", err)
  293. return
  294. }
  295. d.data.rawStatusCode = &code
  296. case "grpc-message":
  297. d.data.rawStatusMsg = decodeGrpcMessage(f.Value)
  298. case "grpc-status-details-bin":
  299. v, err := decodeBinHeader(f.Value)
  300. if err != nil {
  301. d.data.grpcErr = status.Errorf(codes.Internal, "transport: malformed grpc-status-details-bin: %v", err)
  302. return
  303. }
  304. s := &spb.Status{}
  305. if err := proto.Unmarshal(v, s); err != nil {
  306. d.data.grpcErr = status.Errorf(codes.Internal, "transport: malformed grpc-status-details-bin: %v", err)
  307. return
  308. }
  309. d.data.statusGen = status.FromProto(s)
  310. case "grpc-timeout":
  311. d.data.timeoutSet = true
  312. var err error
  313. if d.data.timeout, err = decodeTimeout(f.Value); err != nil {
  314. d.data.grpcErr = status.Errorf(codes.Internal, "transport: malformed time-out: %v", err)
  315. }
  316. case ":path":
  317. d.data.method = f.Value
  318. case ":status":
  319. code, err := strconv.Atoi(f.Value)
  320. if err != nil {
  321. d.data.httpErr = status.Errorf(codes.Internal, "transport: malformed http-status: %v", err)
  322. return
  323. }
  324. d.data.httpStatus = &code
  325. case "grpc-tags-bin":
  326. v, err := decodeBinHeader(f.Value)
  327. if err != nil {
  328. d.data.grpcErr = status.Errorf(codes.Internal, "transport: malformed grpc-tags-bin: %v", err)
  329. return
  330. }
  331. d.data.statsTags = v
  332. d.addMetadata(f.Name, string(v))
  333. case "grpc-trace-bin":
  334. v, err := decodeBinHeader(f.Value)
  335. if err != nil {
  336. d.data.grpcErr = status.Errorf(codes.Internal, "transport: malformed grpc-trace-bin: %v", err)
  337. return
  338. }
  339. d.data.statsTrace = v
  340. d.addMetadata(f.Name, string(v))
  341. default:
  342. if isReservedHeader(f.Name) && !isWhitelistedHeader(f.Name) {
  343. break
  344. }
  345. v, err := decodeMetadataHeader(f.Name, f.Value)
  346. if err != nil {
  347. if logger.V(logLevel) {
  348. logger.Errorf("Failed to decode metadata header (%q, %q): %v", f.Name, f.Value, err)
  349. }
  350. return
  351. }
  352. d.addMetadata(f.Name, v)
  353. }
  354. }
  355. type timeoutUnit uint8
  356. const (
  357. hour timeoutUnit = 'H'
  358. minute timeoutUnit = 'M'
  359. second timeoutUnit = 'S'
  360. millisecond timeoutUnit = 'm'
  361. microsecond timeoutUnit = 'u'
  362. nanosecond timeoutUnit = 'n'
  363. )
  364. func timeoutUnitToDuration(u timeoutUnit) (d time.Duration, ok bool) {
  365. switch u {
  366. case hour:
  367. return time.Hour, true
  368. case minute:
  369. return time.Minute, true
  370. case second:
  371. return time.Second, true
  372. case millisecond:
  373. return time.Millisecond, true
  374. case microsecond:
  375. return time.Microsecond, true
  376. case nanosecond:
  377. return time.Nanosecond, true
  378. default:
  379. }
  380. return
  381. }
  382. func decodeTimeout(s string) (time.Duration, error) {
  383. size := len(s)
  384. if size < 2 {
  385. return 0, fmt.Errorf("transport: timeout string is too short: %q", s)
  386. }
  387. if size > 9 {
  388. // Spec allows for 8 digits plus the unit.
  389. return 0, fmt.Errorf("transport: timeout string is too long: %q", s)
  390. }
  391. unit := timeoutUnit(s[size-1])
  392. d, ok := timeoutUnitToDuration(unit)
  393. if !ok {
  394. return 0, fmt.Errorf("transport: timeout unit is not recognized: %q", s)
  395. }
  396. t, err := strconv.ParseInt(s[:size-1], 10, 64)
  397. if err != nil {
  398. return 0, err
  399. }
  400. const maxHours = math.MaxInt64 / int64(time.Hour)
  401. if d == time.Hour && t > maxHours {
  402. // This timeout would overflow math.MaxInt64; clamp it.
  403. return time.Duration(math.MaxInt64), nil
  404. }
  405. return d * time.Duration(t), nil
  406. }
  407. const (
  408. spaceByte = ' '
  409. tildeByte = '~'
  410. percentByte = '%'
  411. )
  412. // encodeGrpcMessage is used to encode status code in header field
  413. // "grpc-message". It does percent encoding and also replaces invalid utf-8
  414. // characters with Unicode replacement character.
  415. //
  416. // It checks to see if each individual byte in msg is an allowable byte, and
  417. // then either percent encoding or passing it through. When percent encoding,
  418. // the byte is converted into hexadecimal notation with a '%' prepended.
  419. func encodeGrpcMessage(msg string) string {
  420. if msg == "" {
  421. return ""
  422. }
  423. lenMsg := len(msg)
  424. for i := 0; i < lenMsg; i++ {
  425. c := msg[i]
  426. if !(c >= spaceByte && c <= tildeByte && c != percentByte) {
  427. return encodeGrpcMessageUnchecked(msg)
  428. }
  429. }
  430. return msg
  431. }
  432. func encodeGrpcMessageUnchecked(msg string) string {
  433. var buf bytes.Buffer
  434. for len(msg) > 0 {
  435. r, size := utf8.DecodeRuneInString(msg)
  436. for _, b := range []byte(string(r)) {
  437. if size > 1 {
  438. // If size > 1, r is not ascii. Always do percent encoding.
  439. buf.WriteString(fmt.Sprintf("%%%02X", b))
  440. continue
  441. }
  442. // The for loop is necessary even if size == 1. r could be
  443. // utf8.RuneError.
  444. //
  445. // fmt.Sprintf("%%%02X", utf8.RuneError) gives "%FFFD".
  446. if b >= spaceByte && b <= tildeByte && b != percentByte {
  447. buf.WriteByte(b)
  448. } else {
  449. buf.WriteString(fmt.Sprintf("%%%02X", b))
  450. }
  451. }
  452. msg = msg[size:]
  453. }
  454. return buf.String()
  455. }
  456. // decodeGrpcMessage decodes the msg encoded by encodeGrpcMessage.
  457. func decodeGrpcMessage(msg string) string {
  458. if msg == "" {
  459. return ""
  460. }
  461. lenMsg := len(msg)
  462. for i := 0; i < lenMsg; i++ {
  463. if msg[i] == percentByte && i+2 < lenMsg {
  464. return decodeGrpcMessageUnchecked(msg)
  465. }
  466. }
  467. return msg
  468. }
  469. func decodeGrpcMessageUnchecked(msg string) string {
  470. var buf bytes.Buffer
  471. lenMsg := len(msg)
  472. for i := 0; i < lenMsg; i++ {
  473. c := msg[i]
  474. if c == percentByte && i+2 < lenMsg {
  475. parsed, err := strconv.ParseUint(msg[i+1:i+3], 16, 8)
  476. if err != nil {
  477. buf.WriteByte(c)
  478. } else {
  479. buf.WriteByte(byte(parsed))
  480. i += 2
  481. }
  482. } else {
  483. buf.WriteByte(c)
  484. }
  485. }
  486. return buf.String()
  487. }
  488. type bufWriter struct {
  489. buf []byte
  490. offset int
  491. batchSize int
  492. conn net.Conn
  493. err error
  494. onFlush func()
  495. }
  496. func newBufWriter(conn net.Conn, batchSize int) *bufWriter {
  497. return &bufWriter{
  498. buf: make([]byte, batchSize*2),
  499. batchSize: batchSize,
  500. conn: conn,
  501. }
  502. }
  503. func (w *bufWriter) Write(b []byte) (n int, err error) {
  504. if w.err != nil {
  505. return 0, w.err
  506. }
  507. if w.batchSize == 0 { // Buffer has been disabled.
  508. return w.conn.Write(b)
  509. }
  510. for len(b) > 0 {
  511. nn := copy(w.buf[w.offset:], b)
  512. b = b[nn:]
  513. w.offset += nn
  514. n += nn
  515. if w.offset >= w.batchSize {
  516. err = w.Flush()
  517. }
  518. }
  519. return n, err
  520. }
  521. func (w *bufWriter) Flush() error {
  522. if w.err != nil {
  523. return w.err
  524. }
  525. if w.offset == 0 {
  526. return nil
  527. }
  528. if w.onFlush != nil {
  529. w.onFlush()
  530. }
  531. _, w.err = w.conn.Write(w.buf[:w.offset])
  532. w.offset = 0
  533. return w.err
  534. }
  535. type framer struct {
  536. writer *bufWriter
  537. fr *http2.Framer
  538. }
  539. func newFramer(conn net.Conn, writeBufferSize, readBufferSize int, maxHeaderListSize uint32) *framer {
  540. if writeBufferSize < 0 {
  541. writeBufferSize = 0
  542. }
  543. var r io.Reader = conn
  544. if readBufferSize > 0 {
  545. r = bufio.NewReaderSize(r, readBufferSize)
  546. }
  547. w := newBufWriter(conn, writeBufferSize)
  548. f := &framer{
  549. writer: w,
  550. fr: http2.NewFramer(w, r),
  551. }
  552. f.fr.SetMaxReadFrameSize(http2MaxFrameLen)
  553. // Opt-in to Frame reuse API on framer to reduce garbage.
  554. // Frames aren't safe to read from after a subsequent call to ReadFrame.
  555. f.fr.SetReuseFrames()
  556. f.fr.MaxHeaderListSize = maxHeaderListSize
  557. f.fr.ReadMetaHeaders = hpack.NewDecoder(http2InitHeaderTableSize, nil)
  558. return f
  559. }