| 359 | } |
| 360 | |
| 361 | func post(ctx context.Context, body []byte, timeout time.Duration) (b []byte, err error) { |
| 362 | apiURL := apiURL(ctx) |
| 363 | hreq := &http.Request{ |
| 364 | Method: "POST", |
| 365 | URL: apiURL, |
| 366 | Header: http.Header{ |
| 367 | apiEndpointHeader: apiEndpointHeaderValue, |
| 368 | apiMethodHeader: apiMethodHeaderValue, |
| 369 | apiContentType: apiContentTypeValue, |
| 370 | apiDeadlineHeader: []string{strconv.FormatFloat(timeout.Seconds(), 'f', -1, 64)}, |
| 371 | }, |
| 372 | Body: ioutil.NopCloser(bytes.NewReader(body)), |
| 373 | ContentLength: int64(len(body)), |
| 374 | Host: apiURL.Host, |
| 375 | } |
| 376 | c := fromContext(ctx) |
| 377 | if c != nil { |
| 378 | if info := c.req.Header.Get(dapperHeader); info != "" { |
| 379 | hreq.Header.Set(dapperHeader, info) |
| 380 | } |
| 381 | if info := c.req.Header.Get(traceHeader); info != "" { |
| 382 | hreq.Header.Set(traceHeader, info) |
| 383 | } |
| 384 | } |
| 385 | |
| 386 | tr := apiHTTPClient.Transport.(*http.Transport) |
| 387 | |
| 388 | var timedOut int32 // atomic; set to 1 if timed out |
| 389 | t := time.AfterFunc(timeout, func() { |
| 390 | atomic.StoreInt32(&timedOut, 1) |
| 391 | tr.CancelRequest(hreq) |
| 392 | }) |
| 393 | defer t.Stop() |
| 394 | defer func() { |
| 395 | // Check if timeout was exceeded. |
| 396 | if atomic.LoadInt32(&timedOut) != 0 { |
| 397 | err = errTimeout |
| 398 | } |
| 399 | }() |
| 400 | |
| 401 | hresp, err := apiHTTPClient.Do(hreq) |
| 402 | if err != nil { |
| 403 | return nil, &CallError{ |
| 404 | Detail: fmt.Sprintf("service bridge HTTP failed: %v", err), |
| 405 | Code: int32(remotepb.RpcError_UNKNOWN), |
| 406 | } |
| 407 | } |
| 408 | defer hresp.Body.Close() |
| 409 | hrespBody, err := ioutil.ReadAll(hresp.Body) |
| 410 | if hresp.StatusCode != 200 { |
| 411 | return nil, &CallError{ |
| 412 | Detail: fmt.Sprintf("service bridge returned HTTP %d (%q)", hresp.StatusCode, hrespBody), |
| 413 | Code: int32(remotepb.RpcError_UNKNOWN), |
| 414 | } |
| 415 | } |
| 416 | if err != nil { |
| 417 | return nil, &CallError{ |
| 418 | Detail: fmt.Sprintf("service bridge response bad: %v", err), |