Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(177)

Side by Side Diff: server/prpc/decoding.go

Issue 1637193002: common/prpc, tools/cmd/cproto: prpc client (Closed) Base URL: https://github.com/luci/luci-go@prpc-server
Patch Set: Add some content length tests. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « common/retry/transient.go ('k') | server/prpc/decoding_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package prpc 5 package prpc
6 6
7 import ( 7 import (
8 "bytes" 8 "bytes"
9 "encoding/base64" 9 "encoding/base64"
10 "fmt" 10 "fmt"
11 "io/ioutil" 11 "io/ioutil"
12 "mime" 12 "mime"
13 "net/http" 13 "net/http"
14 "strings" 14 "strings"
15 15
16 "github.com/golang/protobuf/jsonpb" 16 "github.com/golang/protobuf/jsonpb"
17 "github.com/golang/protobuf/proto" 17 "github.com/golang/protobuf/proto"
18 "golang.org/x/net/context" 18 "golang.org/x/net/context"
19 "google.golang.org/grpc/metadata" 19 "google.golang.org/grpc/metadata"
20 20
21 "github.com/luci/luci-go/common/clock" 21 "github.com/luci/luci-go/common/clock"
22 prpccommon "github.com/luci/luci-go/common/prpc"
22 ) 23 )
23 24
24 // This file implements decoding of HTTP requests to RPC parameters. 25 // This file implements decoding of HTTP requests to RPC parameters.
25 26
26 const ( 27 const (
27 // headerSuffixBinary is a suffix of an HTTP header that specifies that 28 // headerSuffixBinary is a suffix of an HTTP header that specifies that
28 // the header value is encoded in std base64. 29 // the header value is encoded in std base64.
29 // After decoding, a handler must process the header without the suffix. 30 // After decoding, a handler must process the header without the suffix.
30 headerSuffixBinary = "-Bin" 31 headerSuffixBinary = "-Bin"
31 headerContentType = "Content-Type" 32 headerContentType = "Content-Type"
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 default: 88 default:
88 err = fmt.Errorf("unknown message format: %d", format) 89 err = fmt.Errorf("unknown message format: %d", format)
89 } 90 }
90 if err != nil { 91 if err != nil {
91 return errorf(http.StatusBadRequest, "could not decode body: %s" , err) 92 return errorf(http.StatusBadRequest, "could not decode body: %s" , err)
92 } 93 }
93 return nil 94 return nil
94 } 95 }
95 96
96 // parseHeader parses HTTP headers and derives a new context. 97 // parseHeader parses HTTP headers and derives a new context.
97 // Supports headerTimeout. 98 // Supports HeaderTimeout.
98 // Ignores "Accept" and "Content-Type" headers. 99 // Ignores "Accept" and "Content-Type" headers.
99 // 100 //
100 // If there are unrecognized HTTP headers, with or without headerSuffixBinary, 101 // If there are unrecognized HTTP headers, with or without headerSuffixBinary,
101 // they are added to a metadata.MD and a new context is derived. 102 // they are added to a metadata.MD and a new context is derived.
102 // If c already has metadata, the latter is copied. 103 // If c already has metadata, the latter is copied.
103 // 104 //
104 // In case of an error, returns c unmodified. 105 // In case of an error, returns c unmodified.
105 func parseHeader(c context.Context, header http.Header) (context.Context, error) { 106 func parseHeader(c context.Context, header http.Header) (context.Context, error) {
106 origC := c 107 origC := c
107 108
108 md, ok := metadata.FromContext(c) 109 md, ok := metadata.FromContext(c)
109 if ok { 110 if ok {
110 md = md.Copy() 111 md = md.Copy()
111 } else { 112 } else {
112 md = metadata.MD{} 113 md = metadata.MD{}
113 } 114 }
114 115
115 addedMeta := false 116 addedMeta := false
116 for name, values := range header { 117 for name, values := range header {
117 if len(values) == 0 { 118 if len(values) == 0 {
118 continue 119 continue
119 } 120 }
120 name = http.CanonicalHeaderKey(name) 121 name = http.CanonicalHeaderKey(name)
121 switch name { 122 switch name {
122 123
123 » » case headerTimeout: 124 » » case prpccommon.HeaderTimeout:
124 // Decode only first value, ignore the rest 125 // Decode only first value, ignore the rest
125 // to be consistent with http.Header.Get. 126 // to be consistent with http.Header.Get.
126 » » » timeout, err := decodeTimeout(values[0]) 127 » » » timeout, err := prpccommon.DecodeTimeout(values[0])
127 if err != nil { 128 if err != nil {
128 » » » » return origC, fmt.Errorf("%s header: %s", header Timeout, err) 129 » » » » return origC, fmt.Errorf("%s header: %s", prpcco mmon.HeaderTimeout, err)
129 } 130 }
130 c, _ = clock.WithTimeout(c, timeout) 131 c, _ = clock.WithTimeout(c, timeout)
131 132
132 case headerAccept, headerContentType: 133 case headerAccept, headerContentType:
133 // readMessage and writeMessage handle these headers. 134 // readMessage and writeMessage handle these headers.
134 135
135 default: 136 default:
136 addedMeta = true 137 addedMeta = true
137 if !strings.HasSuffix(name, headerSuffixBinary) { 138 if !strings.HasSuffix(name, headerSuffixBinary) {
138 md[name] = append(md[name], values...) 139 md[name] = append(md[name], values...)
139 break // switch name 140 break // switch name
140 } 141 }
141 trimmedName := strings.TrimSuffix(name, headerSuffixBina ry) 142 trimmedName := strings.TrimSuffix(name, headerSuffixBina ry)
142 for _, v := range values { 143 for _, v := range values {
143 decoded, err := base64.StdEncoding.DecodeString( v) 144 decoded, err := base64.StdEncoding.DecodeString( v)
144 if err != nil { 145 if err != nil {
145 return origC, fmt.Errorf("%s header: %s" , name, err) 146 return origC, fmt.Errorf("%s header: %s" , name, err)
146 } 147 }
147 md[trimmedName] = append(md[trimmedName], string (decoded)) 148 md[trimmedName] = append(md[trimmedName], string (decoded))
148 } 149 }
149 } 150 }
150 } 151 }
151 if addedMeta { 152 if addedMeta {
152 c = metadata.NewContext(c, md) 153 c = metadata.NewContext(c, md)
153 } 154 }
154 return c, nil 155 return c, nil
155 } 156 }
OLDNEW
« no previous file with comments | « common/retry/transient.go ('k') | server/prpc/decoding_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698