1// +build go1.8 2 3// Copyright 2017 Microsoft Corporation 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 17package autorest 18 19import ( 20 "bytes" 21 "io" 22 "io/ioutil" 23 "net/http" 24) 25 26// RetriableRequest provides facilities for retrying an HTTP request. 27type RetriableRequest struct { 28 req *http.Request 29 rc io.ReadCloser 30 br *bytes.Reader 31} 32 33// Prepare signals that the request is about to be sent. 34func (rr *RetriableRequest) Prepare() (err error) { 35 // preserve the request body; this is to support retry logic as 36 // the underlying transport will always close the reqeust body 37 if rr.req.Body != nil { 38 if rr.rc != nil { 39 rr.req.Body = rr.rc 40 } else if rr.br != nil { 41 _, err = rr.br.Seek(0, io.SeekStart) 42 rr.req.Body = ioutil.NopCloser(rr.br) 43 } 44 if err != nil { 45 return err 46 } 47 if rr.req.GetBody != nil { 48 // this will allow us to preserve the body without having to 49 // make a copy. note we need to do this on each iteration 50 rr.rc, err = rr.req.GetBody() 51 if err != nil { 52 return err 53 } 54 } else if rr.br == nil { 55 // fall back to making a copy (only do this once) 56 err = rr.prepareFromByteReader() 57 } 58 } 59 return err 60} 61 62func removeRequestBody(req *http.Request) { 63 req.Body = nil 64 req.GetBody = nil 65 req.ContentLength = 0 66} 67