Skip to content

Instantly share code, notes, and snippets.

@KaHBrat
Last active August 29, 2021 20:38
Show Gist options
  • Save KaHBrat/e11fa370e463fb361b19f2154b61ad11 to your computer and use it in GitHub Desktop.
Save KaHBrat/e11fa370e463fb361b19f2154b61ad11 to your computer and use it in GitHub Desktop.
httpencoding
package httpencoding
import (
"bytes"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/url"
"reflect"
"strings"
"testing"
)
func TestHttpencoding_Integration_ConvBackAndForth(t *testing.T) {
//Arrange
const defaultUserAgent = "Go-http-client/1.1"
type args struct {
req http.Request
}
tests := []struct {
name string
args args
want http.Request
wantErr bool
}{
{
name: "Convert a HTTP Request to a byte Array and back to HTTP Request",
args: args{http.Request{Method: http.MethodGet, URL: &url.URL{Path: "http://localhost:20000"}}},
want: http.Request{
Method: http.MethodGet,
Host: "localhost:20000",
RequestURI: "http://localhost:20000",
URL: &url.URL{
Scheme: "http",
Host: "localhost:20000"},
Proto: "HTTP/1.1",
ProtoMajor: 1,
ProtoMinor: 1,
Header: http.Header{
"User-Agent": []string{defaultUserAgent}},
Body: http.NoBody,
Close: false},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
//Act
b, err := GetHttpRawRequest(tt.args.req)
if (err != nil) != tt.wantErr {
t.Errorf("GetHttpRawMessage() error = %v, wantErr %v", err, tt.wantErr)
return
}
r := bytes.NewReader(b)
if (err != nil) != tt.wantErr {
t.Errorf("r.Read() error = %v, wantErr %v", err, tt.wantErr)
return
}
got, err := GetHttpRequest(r)
if (err != nil) != tt.wantErr {
t.Errorf("ConvByteToHttpReq() error = %v, wantErr %v", err, tt.wantErr)
return
}
//Assert
if !reflect.DeepEqual(*got, tt.want) {
t.Errorf("GetHttpRawMessage() = %v, want %v", *got, tt.want)
}
})
}
}
/*
Test Description:
RequestB will be encapsulated in the body of RequestA
RequestA will be sent to Testserver1
Testserver1 will convert the encapsulated RequestB to an httpRequest
Testserver1 will send RequestB to Testserver2
Testserver1 will encapsulate the response of Testserver2 in its response
The response of Testserver1 will be converted to a httpResponse
The body of the response of Testserver2 will be read
send: ReqA{ReqB} -> Testserver1. ReqB -> Testserver2
read: respTestServer1{respTestserver2}
*/
func TestHttpEncoding_Integration_Complete(t *testing.T) {
//Arrange
go runTestServer1()
go runTestServer2()
type args struct {
httpMethod string
url string
message string
}
tests := []struct {
name string
args args
want string
wantErr bool
}{
{
name: "Full Integration test",
args: args{httpMethod: http.MethodGet, url: httpEncodingEndpoint2, message: "Hello World"},
want: "Encapsulated HTTP Request received on test-server2 and sent back successfully",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
//Arrange
stringReader := strings.NewReader(tt.args.message)
req, err := http.NewRequest(tt.args.httpMethod, tt.args.url, stringReader)
if (err != nil) != tt.wantErr {
t.Errorf("http.NewRequest() error = %v, wantErr %v", err, tt.wantErr)
return
}
//Act
b, err := GetHttpRawRequest(*req)
if (err != nil) != tt.wantErr {
t.Errorf("GetHttpRawRequest() error = %v, wantErr %v", err, tt.wantErr)
return
}
r := bytes.NewReader(b)
resp, err := http.Post(httpEncodingEndpoint, "", r)
if (err != nil) != tt.wantErr {
t.Errorf("http.Post() error = %v, wantErr %v", err, tt.wantErr)
return
}
encapsulatedResponse, err := GetHttpResponse(resp.Body, req)
if (err != nil) != tt.wantErr {
t.Errorf("GetHttpResponse() error = %v, wantErr %v", err, tt.wantErr)
return
}
msg, err := ioutil.ReadAll(encapsulatedResponse.Body)
if (err != nil) != tt.wantErr {
t.Errorf("ioutil.ReadAll() error = %v, wantErr %v", err, tt.wantErr)
return
}
got := string(msg)
//Assert
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("GetHttpRawMessage() = %v, want %v", got, tt.want)
}
})
}
}
const httpEncodingEndpoint = "http://localhost:12000/httpEncoding"
const httpEncodingEndpoint2 = "http://localhost:20000/httpEncoding2"
const msgPath = "/httpEncoding"
const msgPath2 = "/httpEncoding2"
const msgPort = ":12000"
const msgPort2 = ":20000"
func runTestServer1() {
log.Printf("Starting test http Listener\n serving on endpoint %s", httpEncodingEndpoint)
http.HandleFunc(msgPath, httpEncodingHandler)
if err := http.ListenAndServe(msgPort, nil); err != nil {
log.Fatalf("error: %s", err)
}
}
func httpEncodingHandler(w http.ResponseWriter, r *http.Request) {
req, err := GetHttpRequest(r.Body)
if err != nil {
http.Error(w, fmt.Sprintf("Converting to HTTP Request failed: %s", err), http.StatusBadRequest)
return
}
client := http.Client{}
resp, err := client.Do(req)
if err != nil {
http.Error(w, fmt.Sprintf("calling next HTTP Request failed: %s", err), http.StatusBadRequest)
return
}
rawResponse, err := GetHttpRawResponse(*resp)
if err != nil {
http.Error(w, fmt.Sprintf("converting to rawp HTTP response failed: %s", err), http.StatusBadRequest)
return
}
fmt.Println(string(rawResponse))
w.Write(rawResponse)
}
func runTestServer2() {
log.Printf("Starting test http Listener\n serving on endpoint %s", httpEncodingEndpoint2)
http.HandleFunc(msgPath2, httpEncodingHandler2)
if err := http.ListenAndServe(msgPort2, nil); err != nil {
log.Fatalf("error: %s", err)
}
}
func httpEncodingHandler2(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Encapsulated HTTP Request received on test-server2 and sent back successfully"))
}
package httpencoding
import (
"bufio"
"bytes"
"io"
"net/http"
"net/url"
)
func GetHttpRawRequest(req http.Request) ([]byte, error) {
var b = &bytes.Buffer{}
if err := req.Write(b) ; err != nil {
return nil, err
}
return b.Bytes(), nil
}
func GetHttpRequest(r io.Reader) (*http.Request, error) {
bufReader := bufio.NewReader(r)
req, err := http.ReadRequest(bufReader)
if err != nil {
return nil, err
}
// https://stackoverflow.com/questions/19595860/http-request-requesturi-field-when-making-request-in-go
// We can't have this set. And it only contains the msg path anyway. It was set during http.ReadRequest
req.RequestURI = ""
// Since the req.URL will not have all the information set,
// such as protocol scheme and host, we create a new URL
u, err := url.Parse("http://"+req.Host+req.URL.Path)
if err != nil {
return nil, err
}
req.URL = u
return req ,err
}
func GetHttpRawResponse(resp http.Response) ([]byte, error) {
var b = &bytes.Buffer{}
if err := resp.Write(b) ; err != nil {
return nil, err
}
return b.Bytes(), nil
}
func GetHttpResponse(r io.Reader, req *http.Request) (*http.Response, error) {
bufReader := bufio.NewReader(r)
resp, err := http.ReadResponse(bufReader, req)
if err != nil {
return nil, err
}
return resp ,err
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment