Files
sing-box/protocol/cloudflare/header.go
2026-03-31 15:32:56 +08:00

56 lines
1.6 KiB
Go

//go:build with_cloudflared
package cloudflare
import (
"encoding/base64"
"net/http"
"strings"
)
const (
h2HeaderUpgrade = "Cf-Cloudflared-Proxy-Connection-Upgrade"
h2HeaderTCPSrc = "Cf-Cloudflared-Proxy-Src"
h2HeaderResponseMeta = "Cf-Cloudflared-Response-Meta"
h2HeaderResponseUser = "Cf-Cloudflared-Response-Headers"
h2UpgradeControlStream = "control-stream"
h2UpgradeWebsocket = "websocket"
h2UpgradeConfiguration = "update-configuration"
h2ResponseMetaOrigin = `{"src":"origin"}`
)
var headerEncoding = base64.RawStdEncoding
// SerializeHeaders encodes HTTP/1 headers into base64 pairs: base64(name):base64(value);...
func SerializeHeaders(header http.Header) string {
var builder strings.Builder
for name, values := range header {
for _, value := range values {
if builder.Len() > 0 {
builder.WriteByte(';')
}
builder.WriteString(headerEncoding.EncodeToString([]byte(name)))
builder.WriteByte(':')
builder.WriteString(headerEncoding.EncodeToString([]byte(value)))
}
}
return builder.String()
}
// isControlResponseHeader returns true for headers that are internal control headers.
func isControlResponseHeader(name string) bool {
lower := strings.ToLower(name)
return strings.HasPrefix(lower, ":") ||
strings.HasPrefix(lower, "cf-int-") ||
strings.HasPrefix(lower, "cf-cloudflared-") ||
strings.HasPrefix(lower, "cf-proxy-")
}
// isWebsocketClientHeader returns true for headers needed by the client for WebSocket upgrade.
func isWebsocketClientHeader(name string) bool {
lower := strings.ToLower(name)
return lower == "sec-websocket-accept" ||
lower == "connection" ||
lower == "upgrade"
}