Documentation
¶
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func RepeatableReadCloser ¶ added in v0.0.16
func RepeatableReadCloser(body io.ReadCloser, buf *bytes.Buffer) io.ReadCloser
RepeatableReadCloser returns a ReadCloser that can be read an unlimited number of times.
payload := strings.NewReader(`{"some":"payload"}`) body := RepeatableReadCloser( ioutil.NopCloser(payload), bytes.NewBuffer(make([]byte, 0, payload.Len())), ) req, err := http.NewRequest(http.MethodPost, "/api", body) if err != nil { log.Fatal(err) } for { resp, err := http.DefaultClient.Do(req) if err == nil && resp.StatusCode == http.StatusOK { break } time.Sleep(time.Second) }
Example ¶
i, responses := int32(-1), []int{ http.StatusInternalServerError, http.StatusServiceUnavailable, http.StatusOK, } var ( handler http.HandlerFunc = func(rw http.ResponseWriter, req *http.Request) { unsafe.DoSilent(io.Copy(ioutil.Discard, req.Body)) unsafe.Ignore(req.Body.Close()) code := responses[atomic.AddInt32(&i, 1)] http.Error(rw, http.StatusText(code), code) } request = http.Request{ Method: http.MethodPost, Body: RepeatableReadCloser( ioutil.NopCloser(strings.NewReader("echo")), bytes.NewBuffer(make([]byte, 0, 4)), ), } ) for { recorder := httptest.NewRecorder() handler.ServeHTTP(recorder, &request) unsafe.DoSilent(io.Copy(os.Stdout, recorder.Body)) if recorder.Code == http.StatusOK { break } }
Output: Internal Server Error Service Unavailable OK
func TeeReadCloser ¶
func TeeReadCloser(rc io.ReadCloser, w io.Writer) io.ReadCloser
TeeReadCloser returns a ReadCloser that writes to w what it reads from rc. All reads from rc performed through it are matched with corresponding writes to w. There is no internal buffering - the write must complete before the read completes. Any error encountered while writing is reported as a read error.
func Handler(rw http.ResponseWriter, req *http.Request) { buf := bytes.NewBuffer(make([]byte, 0, req.ContentLength)) body := io.TeeReadCloser(req.Body, buf) defer safe.Close(body, unsafe.Ignore) var payload interface{} if err := json.NewDecoder(body).Decode(&payload); err != nil { message := fmt.Sprintf("invalid json: %s", buf.String()) http.Error(rw, message, http.StatusBadRequest) } }
Example ¶
var ( handler http.HandlerFunc = func(rw http.ResponseWriter, req *http.Request) { buf := bytes.NewBuffer(make([]byte, 0, req.ContentLength)) body := TeeReadCloser(req.Body, buf) defer safe.Close(body, unsafe.Ignore) var payload interface{} if err := json.NewDecoder(body).Decode(&payload); err != nil { message := fmt.Sprintf("invalid json: %s", buf.String()) http.Error(rw, message, http.StatusBadRequest) } } request = http.Request{ Method: http.MethodPost, Body: ioutil.NopCloser(strings.NewReader(`{bad: "json"}`)), } ) recorder := httptest.NewRecorder() handler.ServeHTTP(recorder, &request) unsafe.DoSilent(io.Copy(os.Stdout, recorder.Body))
Output: invalid json: {bad: "json"}
Types ¶
This section is empty.
Click to show internal directories.
Click to hide internal directories.