1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 |
- // Package network provides network utilities for the 3x-ui web panel,
- // including automatic HTTP to HTTPS redirection functionality.
- package network
- import (
- "bufio"
- "bytes"
- "fmt"
- "net"
- "net/http"
- "sync"
- )
- // AutoHttpsConn wraps a net.Conn to provide automatic HTTP to HTTPS redirection.
- // It intercepts the first read to detect HTTP requests and responds with a 307 redirect
- // to the HTTPS equivalent URL. Subsequent reads work normally for HTTPS connections.
- type AutoHttpsConn struct {
- net.Conn
- firstBuf []byte
- bufStart int
- readRequestOnce sync.Once
- }
- // NewAutoHttpsConn creates a new AutoHttpsConn that wraps the given connection.
- // It enables automatic redirection of HTTP requests to HTTPS.
- func NewAutoHttpsConn(conn net.Conn) net.Conn {
- return &AutoHttpsConn{
- Conn: conn,
- }
- }
- func (c *AutoHttpsConn) readRequest() bool {
- c.firstBuf = make([]byte, 2048)
- n, err := c.Conn.Read(c.firstBuf)
- c.firstBuf = c.firstBuf[:n]
- if err != nil {
- return false
- }
- reader := bytes.NewReader(c.firstBuf)
- bufReader := bufio.NewReader(reader)
- request, err := http.ReadRequest(bufReader)
- if err != nil {
- return false
- }
- resp := http.Response{
- Header: http.Header{},
- }
- resp.StatusCode = http.StatusTemporaryRedirect
- location := fmt.Sprintf("https://%v%v", request.Host, request.RequestURI)
- resp.Header.Set("Location", location)
- resp.Write(c.Conn)
- c.Close()
- c.firstBuf = nil
- return true
- }
- // Read implements the net.Conn Read method with automatic HTTPS redirection.
- // On the first read, it checks if the request is HTTP and redirects to HTTPS if so.
- // Subsequent reads work normally.
- func (c *AutoHttpsConn) Read(buf []byte) (int, error) {
- c.readRequestOnce.Do(func() {
- c.readRequest()
- })
- if c.firstBuf != nil {
- n := copy(buf, c.firstBuf[c.bufStart:])
- c.bufStart += n
- if c.bufStart >= len(c.firstBuf) {
- c.firstBuf = nil
- }
- return n, nil
- }
- return c.Conn.Read(buf)
- }
|