Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
fe83bd5b71
|
|||
|
456a0ce108
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -87,6 +87,7 @@ node_modules/**
|
||||
!.gitignore
|
||||
!version
|
||||
!out.jsonl
|
||||
!Dockerfile*
|
||||
# ...even if they are in subdirectories
|
||||
!*/
|
||||
/blocklist.json
|
||||
|
||||
48
main.go
48
main.go
@@ -41,6 +41,9 @@ var orlyFavicon []byte
|
||||
// faviconData holds the favicon data to serve
|
||||
var faviconData []byte
|
||||
|
||||
// faviconContentType holds the content type for the favicon
|
||||
var faviconContentType string
|
||||
|
||||
func main() {
|
||||
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
|
||||
defer cancel()
|
||||
@@ -60,7 +63,7 @@ type C struct {
|
||||
WTo time.Duration `env:"REVERSE_WTO" usage:"maximum duration before timing out write of the response" default:"5m"`
|
||||
Idle time.Duration `env:"REVERSE_IDLE" usage:"how long idle connection is kept before closing (set rto, wto to 0 to use this)"`
|
||||
Certs []string `env:"REVERSE_CERTS" usage:"certificates and the domain they match: eg: mleku.dev:/path/to/cert - this will indicate to load two, one with extension .key and one with .crt, each expected to be PEM encoded TLS private and public keys, respectively"`
|
||||
Favicon string `env:"REVERSE_FAVICON" usage:"path to custom favicon file to serve as favicon.ico (overrides default orly.png)"`
|
||||
Favicon string `env:"REVERSE_FAVICON" usage:"path to custom favicon file to serve as favicon.ico (overrides default favicon.ico)"`
|
||||
}
|
||||
|
||||
// GetEnv checks if the first command line argument is "env" and returns
|
||||
@@ -475,6 +478,14 @@ func setProxy(mapping map[string]string) (http.Handler, error) {
|
||||
rp := newSingleHostReverseProxy(u)
|
||||
rp.ErrorLog = log2.New(io.Discard, "", 0)
|
||||
rp.BufferPool = bufPool{}
|
||||
rp.ModifyResponse = func(resp *http.Response) error {
|
||||
// Add CORS headers to all proxied responses
|
||||
resp.Header.Set("Access-Control-Allow-Origin", "*")
|
||||
resp.Header.Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
|
||||
resp.Header.Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization, Upgrade, Connection, Sec-WebSocket-Key, Sec-WebSocket-Version, Sec-WebSocket-Protocol, Sec-WebSocket-Extensions")
|
||||
resp.Header.Set("Access-Control-Max-Age", "86400")
|
||||
return nil
|
||||
}
|
||||
mux.Handle(hn+"/", rp)
|
||||
addFaviconHandler(hn, mux)
|
||||
continue
|
||||
@@ -497,6 +508,14 @@ func setProxy(mapping map[string]string) (http.Handler, error) {
|
||||
return net.DialTimeout(network, ba, 5*time.Second)
|
||||
},
|
||||
},
|
||||
ModifyResponse: func(resp *http.Response) error {
|
||||
// Add CORS headers to all proxied responses
|
||||
resp.Header.Set("Access-Control-Allow-Origin", "*")
|
||||
resp.Header.Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
|
||||
resp.Header.Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization, Upgrade, Connection, Sec-WebSocket-Key, Sec-WebSocket-Version, Sec-WebSocket-Protocol, Sec-WebSocket-Extensions")
|
||||
resp.Header.Set("Access-Control-Max-Age", "86400")
|
||||
return nil
|
||||
},
|
||||
ErrorLog: log2.New(os.Stderr, "reverse", 0),
|
||||
BufferPool: bufPool{},
|
||||
}
|
||||
@@ -855,8 +874,9 @@ func NostrDNS(hn, ba string, mux *http.ServeMux) (err error) {
|
||||
// loadFavicon loads the favicon data from the configured file or uses the default
|
||||
func loadFavicon(faviconPath string) error {
|
||||
if faviconPath == "" {
|
||||
// Use default orly.png
|
||||
faviconData = orlyFavicon
|
||||
// Use default embedded favicon.ico
|
||||
faviconData = defaultFavicon
|
||||
faviconContentType = "image/x-icon"
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -870,18 +890,36 @@ func loadFavicon(faviconPath string) error {
|
||||
}
|
||||
|
||||
faviconData = data
|
||||
|
||||
// Determine content type based on file extension
|
||||
ext := strings.ToLower(filepath.Ext(faviconPath))
|
||||
switch ext {
|
||||
case ".ico":
|
||||
faviconContentType = "image/x-icon"
|
||||
case ".png":
|
||||
faviconContentType = "image/png"
|
||||
case ".gif":
|
||||
faviconContentType = "image/gif"
|
||||
case ".jpg", ".jpeg":
|
||||
faviconContentType = "image/jpeg"
|
||||
case ".svg":
|
||||
faviconContentType = "image/svg+xml"
|
||||
default:
|
||||
faviconContentType = "image/x-icon" // default fallback
|
||||
}
|
||||
|
||||
log.I.Ln("loaded custom favicon from", faviconPath)
|
||||
return nil
|
||||
}
|
||||
|
||||
// addFaviconHandler adds a favicon handler for the given hostname that serves
|
||||
// the configured favicon as favicon.ico
|
||||
// the configured favicon (default favicon.ico or custom file) as favicon.ico
|
||||
func addFaviconHandler(hostname string, mux *http.ServeMux) {
|
||||
mux.HandleFunc(
|
||||
hostname+"/favicon.ico",
|
||||
func(w http.ResponseWriter, r *http.Request) {
|
||||
log.I.Ln("serving favicon for", hostname)
|
||||
w.Header().Set("Content-Type", "image/png")
|
||||
w.Header().Set("Content-Type", faviconContentType)
|
||||
w.Header().Set("Content-Length", fmt.Sprint(len(faviconData)))
|
||||
w.Header().Set("Cache-Control", "public, max-age=31536000") // 1 year cache
|
||||
if _, err := w.Write(faviconData); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user