Friday, December 13, 2024
HomeGolangHTTP request and response duplication for a number of use - Code...

HTTP request and response duplication for a number of use – Code Overview


Hello,

I’m auditing http request and response by dumping each right into a flat file which works in the mean time. Nevertheless, I’ve a sense this may be improved as a result of so far as I see, useful resource utilization is excessive (RAM and so on.).

Do you suppose there’s higher method or can we enhance this code? Notably excited about AUDIT REQUEST and AUDIT RESPONSE blocks.

Thanks

Bench outcomes under displays 100 concurrent customers sending requests for 10 seconds.

Alloc = 12 MiB	TotalAlloc = 534 MiB	Sys = 27 MiB	NumGC = 190
Alloc =  2 MiB	TotalAlloc = 309 MiB	Sys = 15 MiB	NumGC = 148
Alloc =  4 MiB	TotalAlloc = 348 MiB	Sys = 11 MiB	NumGC = 172
Alloc = 10 MiB	TotalAlloc = 223 MiB	Sys = 23 MiB	NumGC = 39
Alloc =  3 MiB	TotalAlloc = 167 MiB	Sys = 11 MiB	NumGC = 76
...
bundle xhttp

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"internet/http"
	"internet/http/httputil"
	"os"
	"path/filepath"

	"github.com/google/uuid"
)

sort Consumer struct {
	Consumer http.RoundTripper
}

func (c Consumer) Request(ctx context.Context, met, url string, bdy io.Reader, hdrs map[string]string) (*http.Response, error) {
	req, err := http.NewRequestWithContext(ctx, met, url, bdy)
	if err != nil {
		return nil, err
	}

	for ok, v := vary hdrs {
		req.Header.Add(ok, v)
	}

	id := uuid.NewString()

	// AUDIT REQUEST -----------------------------------------------------------
	reqCopy := req.Clone(req.Context())
	if req.Physique != nil || req.Physique != http.NoBody {
		var buff bytes.Buffer
		if _, err := io.Copy(&buff, req.Physique); err == nil {
			req.Physique = io.NopCloser(bytes.NewReader(buff.Bytes()))
			reqCopy.Physique = io.NopCloser(bytes.NewReader(buff.Bytes()))
		}
	}
	go LogRequest(reqCopy, id)
	// -------------------------------------------------------------------------

	res, err := c.Consumer.RoundTrip(req)
	if err != nil {
		return nil, err
	}

	// AUDIT RESPONSE ----------------------------------------------------------
	resCopy := *res
	if res.Physique != nil || res.Physique != http.NoBody {
		var buff bytes.Buffer
		if _, err := io.Copy(&buff, res.Physique); err == nil {
			res.Physique = io.NopCloser(bytes.NewReader(buff.Bytes()))
			resCopy.Physique = io.NopCloser(bytes.NewReader(buff.Bytes()))
		}
	}
	go LogResponse(&resCopy, req, id)
	// -------------------------------------------------------------------------

	return res, nil
}

func LogRequest(req *http.Request, id string) {
	dump, err := httputil.DumpRequest(req, true)
	if err != nil {
		fmt.Println("dump request", err)
		return
	}

	path := id + "_request.log"

	if err := os.MkdirAll(filepath.Dir(path), os.ModePerm); err != nil {
		fmt.Println("mkdir all:", err)
		return
	}

	file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.FileMode(0600))
	if err != nil {
		fmt.Println("open file:", err)
		return
	}
	defer file.Shut()

	if _, err := file.Write(dump); err != nil {
		fmt.Println("file write:", err)
		return
	}
}

func LogResponse(res *http.Response, req *http.Request, id string) {
	dump, err := httputil.DumpResponse(res, true)
	if err != nil {
		fmt.Println("dump response", err)
		return
	}
	defer res.Physique.Shut()

	technique := http.MethodGet
	if req.Methodology != "" {
		technique = req.Methodology
	}

	uri := req.RequestURI
	if uri == "" {
		uri = req.URL.RequestURI()
	}

	dump = append(
		[]byte(fmt.Sprintf("%s %s HTTP/%d.%dnHost: %sn", technique, uri, req.ProtoMajor, req.ProtoMinor, req.URL.Host)),
		dump...,
	)

	path := id + "_response.log"

	if err := os.MkdirAll(filepath.Dir(path), os.ModePerm); err != nil {
		fmt.Println("mkdir all:", err)
		return
	}

	file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.FileMode(0600))
	if err != nil {
		fmt.Println("open file:", err)
		return
	}
	defer file.Shut()

	if _, err := file.Write(dump); err != nil {
		fmt.Println("file write:", err)
		return
	}
}

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments