http_util.go 17 KB

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