将http.Response转换为字节数组。

huangapple go评论95阅读模式
英文:

Transform http.Response into array of bytes

问题

我正在尝试开发一个TCP代理,在这个TCP代理中,我需要同时处理HTTP和TCP请求。

目前,对于传入的请求,我会检测它是HTTP请求还是TCP请求,如果是HTTP请求,我会将其解析为http.Request


func (s *TcpProxy) OnMessage(c *connection.Connection, ctx interface{}, data []byte) interface{} {
	reader := bytes.NewReader(data)
	newReader := bufio.NewReader(reader)
	req, err := http.ReadRequest(newReader)
    // 这是一个HTTP请求
}

现在,我可以方便地操作请求,因为我可以使用该接口提供的方法,然后最终将响应从代理发送回接收传入请求的服务。


func (s *TcpProxy) OnMessage(c *connection.Connection, ctx interface{}, data []byte) interface{} {
    reader := bytes.NewReader(data)
	newReader := bufio.NewReader(reader)
	req, err := http.ReadRequest(newReader)
	// 操作HTTP请求
    // ...
    // 代理请求
    proxyReq, err := http.NewRequest(req.Method, proxyUrl, req.Body)

	// 在向目标服务发出请求时捕获持续时间。
	res, err := httpClient.Do(proxyReq)
    
    buf := res.ToBuffer() // <= 我该如何实现这一步
   
	c.Send(buf)

	c.Close()
	return nil
}

然而,我找不到将响应转换回字节数组或字符串的方法,我是否遗漏了什么?

英文:

I am trying to develop a tcp proxy, in this tcp proxy I will have to manipulate both http and tcp requests.

At the moment for the incoming request I detect if it is an http or tcp request, if it is an http then I parse it into an http.Request:


func (s *TcpProxy) OnMessage(c *connection.Connection, ctx interface{}, data []byte) interface{} {
	reader := bytes.NewReader(data)
	newReader := bufio.NewReader(reader)
	req, err := http.ReadRequest(newReader)
    // This is an http request
}

Now I manipulate the request conveniently since I can use the methods exposed from that interface, then eventually I will send the response back from my proxy to the service that received the inbound request.


func (s *TcpProxy) OnMessage(c *connection.Connection, ctx interface{}, data []byte) interface{} {
    reader := bytes.NewReader(data)
	newReader := bufio.NewReader(reader)
	req, err := http.ReadRequest(newReader)
	// Manipulate http request
    // ...
    // Proxy the request
    proxyReq, err := http.NewRequest(req.Method, proxyUrl, req.Body)

	// Capture the duration while making a request to the destination service.
	res, err := httpClient.Do(proxyReq)
    
    buf := res.ToBuffer() // <= How can I achieve this
   
	c.Send(buf)

	c.Close()
	return nil
}

However I cannot find a way to convert back the response into an array of bytes or string, am I missing something?

答案1

得分: 1

一个http.Request对象有一个Write方法:

func (r *Request) Write(w io.Writer) error

Write方法以二进制格式写入HTTP/1.1请求的头部和正文。

你可以使用这个方法将字节写入一个缓冲区对象。例如:

package main

import (
	"bytes"
	"fmt"
	"net/http"
)

func main() {
	var buf bytes.Buffer

	req, err := http.NewRequest("GET", "http://google.com", nil)
	if err != nil {
		panic(err)
	}

	client := &http.Client{}
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	if err := res.Write(&buf); err != nil {
		panic(err)
	}

	// ...在这里对缓冲区进行任何操作...
	fmt.Println(buf.String())
}

一个缓冲区对象有一个Bytes方法,如果你需要的话,它会返回一个字节数组。

英文:

An http.Request object has a Write method:

>
> func (r *Request) Write(w io.Writer) error
>

>
> Write writes an HTTP/1.1 request, which is the header and body, in wire format.

You can use this to write the bytes into a buffer object. For example:

package main

import (
	"bytes"
	"fmt"
	"net/http"
)

func main() {
	var buf bytes.Buffer

	req, err := http.NewRequest("GET", "http://google.com", nil)
	if err != nil {
		panic(err)
	}

	client := &http.Client{}
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
    defer res.Body.Close()

	if err := res.Write(&buf); err != nil {
		panic(err)
	}

	// ...do whatever you want with the buffer here...
	fmt.Println(buf.String())
}

A Buffer object has a Bytes method that will return a byte array, if that's what you want.

huangapple
  • 本文由 发表于 2021年9月4日 20:40:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/69055373.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定