feat: add custom header support to PHT protocol

- Add Header field to PHT Client and clientConn structs
- Support custom headers in authorize, push, and pull requests
- Add metadata parsing for header configuration as map[string]string
- Enables PHT usage with header-based authentication (e.g., Cloudflare Access)

Backwards compatible - headers are optional.
This commit is contained in:
Vasileios Papadimas
2026-01-16 14:35:48 +02:00
committed by ginuerzh
parent cd7bf9521f
commit 96f35bd7aa
4 changed files with 44 additions and 0 deletions
+1
View File
@@ -109,6 +109,7 @@ func (d *phtDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOp
PushPath: d.md.pushPath, PushPath: d.md.pushPath,
PullPath: d.md.pullPath, PullPath: d.md.pullPath,
TLSEnabled: d.tlsEnabled, TLSEnabled: d.tlsEnabled,
Header: d.md.header,
Logger: d.options.Logger, Logger: d.options.Logger,
} }
d.clients[addr] = client d.clients[addr] = client
+13
View File
@@ -1,6 +1,7 @@
package pht package pht
import ( import (
"net/http"
"strings" "strings"
mdata "github.com/go-gost/core/metadata" mdata "github.com/go-gost/core/metadata"
@@ -19,6 +20,7 @@ type metadata struct {
pushPath string pushPath string
pullPath string pullPath string
host string host string
header http.Header
} }
func (d *phtDialer) parseMetadata(md mdata.Metadata) (err error) { func (d *phtDialer) parseMetadata(md mdata.Metadata) (err error) {
@@ -27,6 +29,7 @@ func (d *phtDialer) parseMetadata(md mdata.Metadata) (err error) {
pushPath = "pushPath" pushPath = "pushPath"
pullPath = "pullPath" pullPath = "pullPath"
host = "host" host = "host"
header = "header"
) )
d.md.authorizePath = mdutil.GetString(md, authorizePath) d.md.authorizePath = mdutil.GetString(md, authorizePath)
@@ -43,5 +46,15 @@ func (d *phtDialer) parseMetadata(md mdata.Metadata) (err error) {
} }
d.md.host = mdutil.GetString(md, host) d.md.host = mdutil.GetString(md, host)
// Parse custom headers
if m := mdutil.GetStringMapString(md, header); len(m) > 0 {
h := http.Header{}
for k, v := range m {
h.Add(k, v)
}
d.md.header = h
}
return return
} }
+11
View File
@@ -21,6 +21,7 @@ type Client struct {
PushPath string PushPath string
PullPath string PullPath string
TLSEnabled bool TLSEnabled bool
Header http.Header
Logger logger.Logger Logger logger.Logger
} }
@@ -43,6 +44,7 @@ func (c *Client) Dial(ctx context.Context, addr string) (net.Conn, error) {
cn := &clientConn{ cn := &clientConn{
client: c.Client, client: c.Client,
header: c.Header,
rxc: make(chan []byte, 128), rxc: make(chan []byte, 128),
closed: make(chan struct{}), closed: make(chan struct{}),
localAddr: &net.TCPAddr{}, localAddr: &net.TCPAddr{},
@@ -74,6 +76,15 @@ func (c *Client) authorize(ctx context.Context, addr string) (token string, err
return return
} }
// Inject custom headers
if c.Header != nil {
for k, values := range c.Header {
for _, v := range values {
r.Header.Add(k, v)
}
}
}
if c.Logger.IsLevelEnabled(logger.TraceLevel) { if c.Logger.IsLevelEnabled(logger.TraceLevel) {
dump, _ := httputil.DumpRequest(r, false) dump, _ := httputil.DumpRequest(r, false)
c.Logger.Trace(string(dump)) c.Logger.Trace(string(dump))
+19
View File
@@ -17,6 +17,7 @@ import (
type clientConn struct { type clientConn struct {
client *http.Client client *http.Client
header http.Header
pushURL string pushURL string
pullURL string pullURL string
buf []byte buf []byte
@@ -69,6 +70,15 @@ func (c *clientConn) write(b []byte) (n int, err error) {
return return
} }
// Add custom headers
if c.header != nil {
for k, values := range c.header {
for _, v := range values {
req.Header.Add(k, v)
}
}
}
if c.logger.IsLevelEnabled(logger.TraceLevel) { if c.logger.IsLevelEnabled(logger.TraceLevel) {
dump, _ := httputil.DumpRequest(req, false) dump, _ := httputil.DumpRequest(req, false)
c.logger.Trace(string(dump)) c.logger.Trace(string(dump))
@@ -109,6 +119,15 @@ func (c *clientConn) readLoop() {
return err return err
} }
// Add custom headers
if c.header != nil {
for k, values := range c.header {
for _, v := range values {
r.Header.Add(k, v)
}
}
}
if c.logger.IsLevelEnabled(logger.TraceLevel) { if c.logger.IsLevelEnabled(logger.TraceLevel) {
dump, _ := httputil.DumpRequest(r, false) dump, _ := httputil.DumpRequest(r, false)
c.logger.Trace(string(dump)) c.logger.Trace(string(dump))