MCPcopy
hub / github.com/grpc-ecosystem/grpc-gateway / ForwardResponseMessage

Function ForwardResponseMessage

runtime/handler.go:156–210  ·  view source on GitHub ↗

ForwardResponseMessage forwards the message "resp" from gRPC server to REST client.

(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, req *http.Request, resp proto.Message, opts ...func(context.Context, http.ResponseWriter, proto.Message) error)

Source from the content-addressed store, hash-verified

154
155// ForwardResponseMessage forwards the message "resp" from gRPC server to REST client.
156func ForwardResponseMessage(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, req *http.Request, resp proto.Message, opts ...func(context.Context, http.ResponseWriter, proto.Message) error) {
157 md, ok := ServerMetadataFromContext(ctx)
158 if ok {
159 handleForwardResponseServerMetadata(w, mux, md)
160 }
161
162 // RFC 7230 https://tools.ietf.org/html/rfc7230#section-4.1.2
163 // Unless the request includes a TE header field indicating "trailers"
164 // is acceptable, as described in Section 4.3, a server SHOULD NOT
165 // generate trailer fields that it believes are necessary for the user
166 // agent to receive.
167 doForwardTrailers := requestAcceptsTrailers(req)
168
169 if ok && doForwardTrailers {
170 handleForwardResponseTrailerHeader(w, mux, md)
171 w.Header().Set("Transfer-Encoding", "chunked")
172 }
173
174 contentType := marshaler.ContentType(resp)
175 w.Header().Set("Content-Type", contentType)
176
177 if err := handleForwardResponseOptions(ctx, w, resp, opts); err != nil {
178 HTTPError(ctx, mux, marshaler, w, req, err)
179 return
180 }
181 respRw, err := mux.forwardResponseRewriter(ctx, resp)
182 if err != nil {
183 grpclog.Errorf("Rewrite error: %v", err)
184 HTTPError(ctx, mux, marshaler, w, req, err)
185 return
186 }
187 var buf []byte
188 if rb, ok := respRw.(responseBody); ok {
189 buf, err = marshaler.Marshal(rb.XXX_ResponseBody())
190 } else {
191 buf, err = marshaler.Marshal(respRw)
192 }
193 if err != nil {
194 grpclog.Errorf("Marshal error: %v", err)
195 HTTPError(ctx, mux, marshaler, w, req, err)
196 return
197 }
198
199 if !doForwardTrailers && mux.writeContentLength {
200 w.Header().Set("Content-Length", strconv.Itoa(len(buf)))
201 }
202
203 if _, err = w.Write(buf); err != nil && !errors.Is(err, http.ErrBodyNotAllowed) {
204 grpclog.Errorf("Failed to write response: %v", err)
205 }
206
207 if ok && doForwardTrailers {
208 handleForwardResponseTrailer(w, mux, md)
209 }
210}
211
212func requestAcceptsTrailers(req *http.Request) bool {
213 te := req.Header.Get("TE")

Calls 12

requestAcceptsTrailersFunction · 0.85
HTTPErrorFunction · 0.85
SetMethod · 0.80
HeaderMethod · 0.80
ContentTypeMethod · 0.65
MarshalMethod · 0.65
XXX_ResponseBodyMethod · 0.65