// proxy proxies provided connection to upstream.
proxy proxies provided connection to upstream.
// proxy proxies provided connection to upstream .
func (p *Proxy) proxy(ctx context.Context, conn net.Conn) error {
	defer func() {
		if err := conn.Close(); err != nil {
			p.logErrf("proxy: downstream: conn close: %v", err)
		}
	}()
	if err := conn.SetReadDeadline(time.Now().Add(proxyReadTimeout)); err != nil {
		return fmt.Errorf("downstream: conn set read deadline: %v", err)
	}
	var buf bytes.Buffer
	_, err := io.CopyN(&buf, conn, 1)
	if err != nil && errors.Is(err, io.EOF) {
		return nil
	}
	if err != nil {
		return fmt.Errorf("downstream: conn read first byte: %v", err)
	}
	if err := conn.SetReadDeadline(time.Time{}); err != nil {
		return fmt.Errorf("downstream: conn unset read deadline: %v", err)
	}
	firstByte := buf.Bytes()[0]
	pc := customReaderConn{
		Conn: conn,
		rdr:  io.MultiReader(bytes.NewReader([]byte{firstByte}), conn),
	}
	if !p.UpstreamTLS {
		return p.connectAndTransfer(ctx, pc)
	}
	if p.UpstreamTLS && (firstByte == httpsFirstByte) {
		return p.connectAndTransfer(ctx, pc)
	}
	if err := pc.SetReadDeadline(time.Now().Add(proxyReadTimeout)); err != nil {
		return fmt.Errorf("downstream: conn set read deadline: %v", err)
	}
	buf = bytes.Buffer{}
	req, err := http.ReadRequest(bufio.NewReader(io.TeeReader(pc, &buf)))
	if err != nil {
		pc = customReaderConn{Conn: conn, rdr: &buf}
		return p.connectAndTransfer(ctx, pc)
	}
	if err := pc.SetReadDeadline(time.Time{}); err != nil {
		return fmt.Errorf("downstream: conn unset read deadline: %v", err)
	}
	pc = customReaderConn{Conn: conn, rdr: &buf}
	if req.Header.Get(headerUpgradeInsecureRequests) != strconv.Itoa(1) {
		return p.connectAndTransfer(ctx, pc)
	}
	redirectLoc := fmt.Sprintf("https://%s%s", req.Host, req.URL.Path)
	res := temporaryRedirect(req.Proto, redirectLoc)
	if _, err := conn.Write(res); err != nil {
		return fmt.Errorf("downstream: conn write redirect response: %v", err)
	}
	return nil
}
func ( p * Proxy ) proxy ( ctx context . Context , conn net . Conn ) error { defer func ( ) { if err := conn . Close ( ) ; err != nil { p . logErrf ( " " , err ) } } ( ) if err := conn . SetReadDeadline ( time . Now ( ) . Add ( proxyReadTimeout ) ) ; err != nil { return fmt . Errorf ( " " , err ) } var buf bytes . Buffer _ , err := io . CopyN ( & buf , conn , 1 ) if err != nil && errors . Is ( err , io . EOF ) { return nil } if err != nil { return fmt . Errorf ( " " , err ) } if err := conn . SetReadDeadline ( time . Time { } ) ; err != nil { return fmt . Errorf ( " " , err ) } firstByte := buf . Bytes ( ) [ 0 ] pc := customReaderConn { Conn : conn , rdr : io . MultiReader ( bytes . NewReader ( [ ] byte { firstByte } ) , conn ) , } if ! p . UpstreamTLS { return p . connectAndTransfer ( ctx , pc ) } if p . UpstreamTLS && ( firstByte == httpsFirstByte ) { return p . connectAndTransfer ( ctx , pc ) } if err := pc . SetReadDeadline ( time . Now ( ) . Add ( proxyReadTimeout ) ) ; err != nil { return fmt . Errorf ( " " , err ) } buf = bytes . Buffer { } req , err := http . ReadRequest ( bufio . NewReader ( io . TeeReader ( pc , & buf ) ) ) if err != nil { pc = customReaderConn { Conn : conn , rdr : & buf } return p . connectAndTransfer ( ctx , pc ) } if err := pc . SetReadDeadline ( time . Time { } ) ; err != nil { return fmt . Errorf ( " " , err ) } pc = customReaderConn { Conn : conn , rdr : & buf } if req . Header . Get ( headerUpgradeInsecureRequests ) != strconv . Itoa ( 1 ) { return p . connectAndTransfer ( ctx , pc ) } redirectLoc := fmt . Sprintf ( " " , req . Host , req . URL . Path ) res := temporaryRedirect ( req . Proto , redirectLoc ) if _ , err := conn . Write ( res ) ; err != nil { return fmt . Errorf ( " " , err ) } return nil }
proxy proxies provided connection to upstream.
proxy proxies provided connection to upstream .