| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 | 
							- package http
 
- //go:generate go run $GOPATH/src/v2ray.com/core/common/errors/errorgen/main.go -pkg http -path Transport,Internet,Headers,HTTP
 
- import (
 
- 	"bytes"
 
- 	"context"
 
- 	"io"
 
- 	"net"
 
- 	"net/http"
 
- 	"strings"
 
- 	"time"
 
- 	"v2ray.com/core/common"
 
- 	"v2ray.com/core/common/buf"
 
- 	"v2ray.com/core/common/serial"
 
- )
 
- const (
 
- 	// CRLF is the line ending in HTTP header
 
- 	CRLF = "\r\n"
 
- 	// ENDING is the double line ending between HTTP header and body.
 
- 	ENDING = CRLF + CRLF
 
- 	// max length of HTTP header. Safety precaution for DDoS attack.
 
- 	maxHeaderLength = 8192
 
- )
 
- var (
 
- 	ErrHeaderToLong = newError("Header too long.")
 
- 	writeCRLF       = serial.WriteString(CRLF)
 
- )
 
- type Reader interface {
 
- 	Read(io.Reader) (*buf.Buffer, error)
 
- }
 
- type Writer interface {
 
- 	Write(io.Writer) error
 
- }
 
- type NoOpReader struct{}
 
- func (NoOpReader) Read(io.Reader) (*buf.Buffer, error) {
 
- 	return nil, nil
 
- }
 
- type NoOpWriter struct{}
 
- func (NoOpWriter) Write(io.Writer) error {
 
- 	return nil
 
- }
 
- type HeaderReader struct {
 
- }
 
- func (*HeaderReader) Read(reader io.Reader) (*buf.Buffer, error) {
 
- 	buffer := buf.New()
 
- 	totalBytes := 0
 
- 	endingDetected := false
 
- 	for totalBytes < maxHeaderLength {
 
- 		err := buffer.AppendSupplier(buf.ReadFrom(reader))
 
- 		if err != nil {
 
- 			buffer.Release()
 
- 			return nil, err
 
- 		}
 
- 		if n := bytes.Index(buffer.Bytes(), []byte(ENDING)); n != -1 {
 
- 			buffer.SliceFrom(n + len(ENDING))
 
- 			endingDetected = true
 
- 			break
 
- 		}
 
- 		if buffer.Len() >= len(ENDING) {
 
- 			totalBytes += buffer.Len() - len(ENDING)
 
- 			leftover := buffer.BytesFrom(-len(ENDING))
 
- 			buffer.Reset(func(b []byte) (int, error) {
 
- 				return copy(b, leftover), nil
 
- 			})
 
- 		}
 
- 	}
 
- 	if buffer.IsEmpty() {
 
- 		buffer.Release()
 
- 		return nil, nil
 
- 	}
 
- 	if !endingDetected {
 
- 		buffer.Release()
 
- 		return nil, ErrHeaderToLong
 
- 	}
 
- 	return buffer, nil
 
- }
 
- type HeaderWriter struct {
 
- 	header *buf.Buffer
 
- }
 
- func NewHeaderWriter(header *buf.Buffer) *HeaderWriter {
 
- 	return &HeaderWriter{
 
- 		header: header,
 
- 	}
 
- }
 
- func (w *HeaderWriter) Write(writer io.Writer) error {
 
- 	if w.header == nil {
 
- 		return nil
 
- 	}
 
- 	_, err := writer.Write(w.header.Bytes())
 
- 	w.header.Release()
 
- 	w.header = nil
 
- 	return err
 
- }
 
- type HttpConn struct {
 
- 	net.Conn
 
- 	readBuffer    *buf.Buffer
 
- 	oneTimeReader Reader
 
- 	oneTimeWriter Writer
 
- 	errorWriter   Writer
 
- }
 
- func NewHttpConn(conn net.Conn, reader Reader, writer Writer, errorWriter Writer) *HttpConn {
 
- 	return &HttpConn{
 
- 		Conn:          conn,
 
- 		oneTimeReader: reader,
 
- 		oneTimeWriter: writer,
 
- 		errorWriter:   errorWriter,
 
- 	}
 
- }
 
- func (c *HttpConn) Read(b []byte) (int, error) {
 
- 	if c.oneTimeReader != nil {
 
- 		buffer, err := c.oneTimeReader.Read(c.Conn)
 
- 		if err != nil {
 
- 			return 0, err
 
- 		}
 
- 		c.readBuffer = buffer
 
- 		c.oneTimeReader = nil
 
- 	}
 
- 	if !c.readBuffer.IsEmpty() {
 
- 		nBytes, _ := c.readBuffer.Read(b)
 
- 		if c.readBuffer.IsEmpty() {
 
- 			c.readBuffer.Release()
 
- 			c.readBuffer = nil
 
- 		}
 
- 		return nBytes, nil
 
- 	}
 
- 	return c.Conn.Read(b)
 
- }
 
- // Write implements io.Writer.
 
- func (c *HttpConn) Write(b []byte) (int, error) {
 
- 	if c.oneTimeWriter != nil {
 
- 		err := c.oneTimeWriter.Write(c.Conn)
 
- 		c.oneTimeWriter = nil
 
- 		if err != nil {
 
- 			return 0, err
 
- 		}
 
- 	}
 
- 	return c.Conn.Write(b)
 
- }
 
- // Close implements net.Conn.Close().
 
- func (c *HttpConn) Close() error {
 
- 	if c.oneTimeWriter != nil && c.errorWriter != nil {
 
- 		// Connection is being closed but header wasn't sent. This means the client request
 
- 		// is probably not valid. Sending back a server error header in this case.
 
- 		c.errorWriter.Write(c.Conn)
 
- 	}
 
- 	return c.Conn.Close()
 
- }
 
- func formResponseHeader(config *ResponseConfig) *HeaderWriter {
 
- 	header := buf.New()
 
- 	header.AppendSupplier(serial.WriteString(strings.Join([]string{config.GetFullVersion(), config.GetStatusValue().Code, config.GetStatusValue().Reason}, " ")))
 
- 	header.AppendSupplier(writeCRLF)
 
- 	headers := config.PickHeaders()
 
- 	for _, h := range headers {
 
- 		header.AppendSupplier(serial.WriteString(h))
 
- 		header.AppendSupplier(writeCRLF)
 
- 	}
 
- 	if !config.HasHeader("Date") {
 
- 		header.AppendSupplier(serial.WriteString("Date: "))
 
- 		header.AppendSupplier(serial.WriteString(time.Now().Format(http.TimeFormat)))
 
- 		header.AppendSupplier(writeCRLF)
 
- 	}
 
- 	header.AppendSupplier(writeCRLF)
 
- 	return &HeaderWriter{
 
- 		header: header,
 
- 	}
 
- }
 
- type HttpAuthenticator struct {
 
- 	config *Config
 
- }
 
- func (a HttpAuthenticator) GetClientWriter() *HeaderWriter {
 
- 	header := buf.New()
 
- 	config := a.config.Request
 
- 	header.AppendSupplier(serial.WriteString(strings.Join([]string{config.GetMethodValue(), config.PickUri(), config.GetFullVersion()}, " ")))
 
- 	header.AppendSupplier(writeCRLF)
 
- 	headers := config.PickHeaders()
 
- 	for _, h := range headers {
 
- 		header.AppendSupplier(serial.WriteString(h))
 
- 		header.AppendSupplier(writeCRLF)
 
- 	}
 
- 	header.AppendSupplier(writeCRLF)
 
- 	return &HeaderWriter{
 
- 		header: header,
 
- 	}
 
- }
 
- func (a HttpAuthenticator) GetServerWriter() *HeaderWriter {
 
- 	return formResponseHeader(a.config.Response)
 
- }
 
- func (a HttpAuthenticator) Client(conn net.Conn) net.Conn {
 
- 	if a.config.Request == nil && a.config.Response == nil {
 
- 		return conn
 
- 	}
 
- 	var reader Reader = NoOpReader{}
 
- 	if a.config.Request != nil {
 
- 		reader = new(HeaderReader)
 
- 	}
 
- 	var writer Writer = NoOpWriter{}
 
- 	if a.config.Response != nil {
 
- 		writer = a.GetClientWriter()
 
- 	}
 
- 	return NewHttpConn(conn, reader, writer, NoOpWriter{})
 
- }
 
- func (a HttpAuthenticator) Server(conn net.Conn) net.Conn {
 
- 	if a.config.Request == nil && a.config.Response == nil {
 
- 		return conn
 
- 	}
 
- 	return NewHttpConn(conn, new(HeaderReader), a.GetServerWriter(), formResponseHeader(&ResponseConfig{
 
- 		Version: &Version{
 
- 			Value: "1.1",
 
- 		},
 
- 		Status: &Status{
 
- 			Code:   "500",
 
- 			Reason: "Internal Server Error",
 
- 		},
 
- 		Header: []*Header{
 
- 			{
 
- 				Name:  "Connection",
 
- 				Value: []string{"close"},
 
- 			},
 
- 			{
 
- 				Name:  "Cache-Control",
 
- 				Value: []string{"private"},
 
- 			},
 
- 			{
 
- 				Name:  "Content-Length",
 
- 				Value: []string{"0"},
 
- 			},
 
- 		},
 
- 	}))
 
- }
 
- func NewHttpAuthenticator(ctx context.Context, config *Config) (HttpAuthenticator, error) {
 
- 	return HttpAuthenticator{
 
- 		config: config,
 
- 	}, nil
 
- }
 
- func init() {
 
- 	common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
 
- 		return NewHttpAuthenticator(ctx, config.(*Config))
 
- 	}))
 
- }
 
 
  |