github.com/xmplusdev/xray-core@v1.8.10/transport/internet/headers/http/http_test.go (about)

     1  package http_test
     2  
     3  import (
     4  	"bufio"
     5  	"bytes"
     6  	"context"
     7  	"crypto/rand"
     8  	"strings"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/xmplusdev/xray-core/common"
    13  	"github.com/xmplusdev/xray-core/common/buf"
    14  	"github.com/xmplusdev/xray-core/common/net"
    15  	. "github.com/xmplusdev/xray-core/transport/internet/headers/http"
    16  )
    17  
    18  func TestReaderWriter(t *testing.T) {
    19  	cache := buf.New()
    20  	b := buf.New()
    21  	common.Must2(b.WriteString("abcd" + ENDING))
    22  	writer := NewHeaderWriter(b)
    23  	err := writer.Write(cache)
    24  	common.Must(err)
    25  	if v := cache.Len(); v != 8 {
    26  		t.Error("cache len: ", v)
    27  	}
    28  	_, err = cache.Write([]byte{'e', 'f', 'g'})
    29  	common.Must(err)
    30  
    31  	reader := &HeaderReader{}
    32  	_, err = reader.Read(cache)
    33  	if err != nil && !strings.HasPrefix(err.Error(), "malformed HTTP request") {
    34  		t.Error("unknown error ", err)
    35  	}
    36  }
    37  
    38  func TestRequestHeader(t *testing.T) {
    39  	auth, err := NewAuthenticator(context.Background(), &Config{
    40  		Request: &RequestConfig{
    41  			Uri: []string{"/"},
    42  			Header: []*Header{
    43  				{
    44  					Name:  "Test",
    45  					Value: []string{"Value"},
    46  				},
    47  			},
    48  		},
    49  	})
    50  	common.Must(err)
    51  
    52  	cache := buf.New()
    53  	err = auth.GetClientWriter().Write(cache)
    54  	common.Must(err)
    55  
    56  	if cache.String() != "GET / HTTP/1.1\r\nTest: Value\r\n\r\n" {
    57  		t.Error("cache: ", cache.String())
    58  	}
    59  }
    60  
    61  func TestLongRequestHeader(t *testing.T) {
    62  	payload := make([]byte, buf.Size+2)
    63  	common.Must2(rand.Read(payload[:buf.Size-2]))
    64  	copy(payload[buf.Size-2:], ENDING)
    65  	payload = append(payload, []byte("abcd")...)
    66  
    67  	reader := HeaderReader{}
    68  	_, err := reader.Read(bytes.NewReader(payload))
    69  
    70  	if err != nil && !(strings.HasPrefix(err.Error(), "invalid") || strings.HasPrefix(err.Error(), "malformed")) {
    71  		t.Error("unknown error ", err)
    72  	}
    73  }
    74  
    75  func TestConnection(t *testing.T) {
    76  	auth, err := NewAuthenticator(context.Background(), &Config{
    77  		Request: &RequestConfig{
    78  			Method: &Method{Value: "Post"},
    79  			Uri:    []string{"/testpath"},
    80  			Header: []*Header{
    81  				{
    82  					Name:  "Host",
    83  					Value: []string{"www.example.com", "www.google.com"},
    84  				},
    85  				{
    86  					Name:  "User-Agent",
    87  					Value: []string{"Test-Agent"},
    88  				},
    89  			},
    90  		},
    91  		Response: &ResponseConfig{
    92  			Version: &Version{
    93  				Value: "1.1",
    94  			},
    95  			Status: &Status{
    96  				Code:   "404",
    97  				Reason: "Not Found",
    98  			},
    99  		},
   100  	})
   101  	common.Must(err)
   102  
   103  	listener, err := net.Listen("tcp", "127.0.0.1:0")
   104  	common.Must(err)
   105  
   106  	go func() {
   107  		conn, err := listener.Accept()
   108  		common.Must(err)
   109  		authConn := auth.Server(conn)
   110  		b := make([]byte, 256)
   111  		for {
   112  			n, err := authConn.Read(b)
   113  			if err != nil {
   114  				break
   115  			}
   116  			_, err = authConn.Write(b[:n])
   117  			common.Must(err)
   118  		}
   119  	}()
   120  
   121  	conn, err := net.DialTCP("tcp", nil, listener.Addr().(*net.TCPAddr))
   122  	common.Must(err)
   123  
   124  	authConn := auth.Client(conn)
   125  	defer authConn.Close()
   126  
   127  	authConn.Write([]byte("Test payload"))
   128  	authConn.Write([]byte("Test payload 2"))
   129  
   130  	expectedResponse := "Test payloadTest payload 2"
   131  	actualResponse := make([]byte, 256)
   132  	deadline := time.Now().Add(time.Second * 5)
   133  	totalBytes := 0
   134  	for {
   135  		n, err := authConn.Read(actualResponse[totalBytes:])
   136  		common.Must(err)
   137  		totalBytes += n
   138  		if totalBytes >= len(expectedResponse) || time.Now().After(deadline) {
   139  			break
   140  		}
   141  	}
   142  
   143  	if string(actualResponse[:totalBytes]) != expectedResponse {
   144  		t.Error("response: ", string(actualResponse[:totalBytes]))
   145  	}
   146  }
   147  
   148  func TestConnectionInvPath(t *testing.T) {
   149  	auth, err := NewAuthenticator(context.Background(), &Config{
   150  		Request: &RequestConfig{
   151  			Method: &Method{Value: "Post"},
   152  			Uri:    []string{"/testpath"},
   153  			Header: []*Header{
   154  				{
   155  					Name:  "Host",
   156  					Value: []string{"www.example.com", "www.google.com"},
   157  				},
   158  				{
   159  					Name:  "User-Agent",
   160  					Value: []string{"Test-Agent"},
   161  				},
   162  			},
   163  		},
   164  		Response: &ResponseConfig{
   165  			Version: &Version{
   166  				Value: "1.1",
   167  			},
   168  			Status: &Status{
   169  				Code:   "404",
   170  				Reason: "Not Found",
   171  			},
   172  		},
   173  	})
   174  	common.Must(err)
   175  
   176  	authR, err := NewAuthenticator(context.Background(), &Config{
   177  		Request: &RequestConfig{
   178  			Method: &Method{Value: "Post"},
   179  			Uri:    []string{"/testpathErr"},
   180  			Header: []*Header{
   181  				{
   182  					Name:  "Host",
   183  					Value: []string{"www.example.com", "www.google.com"},
   184  				},
   185  				{
   186  					Name:  "User-Agent",
   187  					Value: []string{"Test-Agent"},
   188  				},
   189  			},
   190  		},
   191  		Response: &ResponseConfig{
   192  			Version: &Version{
   193  				Value: "1.1",
   194  			},
   195  			Status: &Status{
   196  				Code:   "404",
   197  				Reason: "Not Found",
   198  			},
   199  		},
   200  	})
   201  	common.Must(err)
   202  
   203  	listener, err := net.Listen("tcp", "127.0.0.1:0")
   204  	common.Must(err)
   205  
   206  	go func() {
   207  		conn, err := listener.Accept()
   208  		common.Must(err)
   209  		authConn := auth.Server(conn)
   210  		b := make([]byte, 256)
   211  		for {
   212  			n, err := authConn.Read(b)
   213  			if err != nil {
   214  				authConn.Close()
   215  				break
   216  			}
   217  			_, err = authConn.Write(b[:n])
   218  			common.Must(err)
   219  		}
   220  	}()
   221  
   222  	conn, err := net.DialTCP("tcp", nil, listener.Addr().(*net.TCPAddr))
   223  	common.Must(err)
   224  
   225  	authConn := authR.Client(conn)
   226  	defer authConn.Close()
   227  
   228  	authConn.Write([]byte("Test payload"))
   229  	authConn.Write([]byte("Test payload 2"))
   230  
   231  	expectedResponse := "Test payloadTest payload 2"
   232  	actualResponse := make([]byte, 256)
   233  	deadline := time.Now().Add(time.Second * 5)
   234  	totalBytes := 0
   235  	for {
   236  		n, err := authConn.Read(actualResponse[totalBytes:])
   237  		if err == nil {
   238  			t.Error("Error Expected", err)
   239  		} else {
   240  			return
   241  		}
   242  		totalBytes += n
   243  		if totalBytes >= len(expectedResponse) || time.Now().After(deadline) {
   244  			break
   245  		}
   246  	}
   247  }
   248  
   249  func TestConnectionInvReq(t *testing.T) {
   250  	auth, err := NewAuthenticator(context.Background(), &Config{
   251  		Request: &RequestConfig{
   252  			Method: &Method{Value: "Post"},
   253  			Uri:    []string{"/testpath"},
   254  			Header: []*Header{
   255  				{
   256  					Name:  "Host",
   257  					Value: []string{"www.example.com", "www.google.com"},
   258  				},
   259  				{
   260  					Name:  "User-Agent",
   261  					Value: []string{"Test-Agent"},
   262  				},
   263  			},
   264  		},
   265  		Response: &ResponseConfig{
   266  			Version: &Version{
   267  				Value: "1.1",
   268  			},
   269  			Status: &Status{
   270  				Code:   "404",
   271  				Reason: "Not Found",
   272  			},
   273  		},
   274  	})
   275  	common.Must(err)
   276  
   277  	listener, err := net.Listen("tcp", "127.0.0.1:0")
   278  	common.Must(err)
   279  
   280  	go func() {
   281  		conn, err := listener.Accept()
   282  		common.Must(err)
   283  		authConn := auth.Server(conn)
   284  		b := make([]byte, 256)
   285  		for {
   286  			n, err := authConn.Read(b)
   287  			if err != nil {
   288  				authConn.Close()
   289  				break
   290  			}
   291  			_, err = authConn.Write(b[:n])
   292  			common.Must(err)
   293  		}
   294  	}()
   295  
   296  	conn, err := net.DialTCP("tcp", nil, listener.Addr().(*net.TCPAddr))
   297  	common.Must(err)
   298  
   299  	conn.Write([]byte("ABCDEFGHIJKMLN\r\n\r\n"))
   300  	l, _, err := bufio.NewReader(conn).ReadLine()
   301  	common.Must(err)
   302  	if !strings.HasPrefix(string(l), "HTTP/1.1 400 Bad Request") {
   303  		t.Error("Resp to non http conn", string(l))
   304  	}
   305  }