io

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 27, 2020 License: MIT Imports: 3 Imported by: 0

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL