subfmproxy/main.go

79 lines
2.1 KiB
Go

package main
import (
"bytes"
"io"
"log"
"net/http"
"net/http/httputil"
"net/url"
"os"
"os/exec"
"strings"
)
type Proxy struct {
proxyTarget *url.URL
}
func NewProxy(target string) *Proxy {
proxy := &Proxy{}
urlTarget, err := url.Parse(target)
if err != nil {
log.Fatal("Target not a valid URL!", target)
}
proxy.proxyTarget = urlTarget
return proxy
}
// serves as a reverse proxy to http://www.subsonic.org/pages/api.jsp
func (pr Proxy) ServeHTTP(w http.ResponseWriter, req *http.Request) {
log.Println("req ", req.RequestURI, req.Method)
proxy := httputil.NewSingleHostReverseProxy(pr.proxyTarget)
// format: 2023/02/03 14:17:16 req /rest/stream.view?u=jefklak&t=8c90da505334799b3184e9fb0539814d&s=LEcB8n9&v=1.13.0&c=substreamer&f=json&id=59d5e314f94f72d30df1a20c537e158c&maxBitRate=320&format=mp3&estimateContentLength=false GET
// returns a binary ID3 file ready to be streamed to the FM receiver system.
// Warning, this does NOT work with Navidrome's native system that also has a /rest/stream endpoint (without the .view)
// TODO wat met "pauzeren"?
// zie https://blog.yossarian.net/2022/11/07/Modernizing-my-1980s-sound-system#fnref:model
if strings.Contains(req.RequestURI, "/rest/stream.view") {
proxy.ModifyResponse = func(resp *http.Response) error {
body, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
err = resp.Body.Close()
if err != nil {
return err
}
go func() {
mp3 := strings.ReplaceAll(req.RequestURI, "/", "_") + ".mp3"
os.WriteFile(mp3, body, 0666)
// on Mac: "sudo ln -s /usr/bin/open /usr/local/bin/play"
go exec.Command("play", mp3).Run()
}()
// pass on the original body into a new body 'cause the original one has been read out already.
resp.Body = io.NopCloser(bytes.NewReader(body))
return nil
}
}
// allow for SSL redirection if needed
req.URL.Host = pr.proxyTarget.Host
req.URL.Scheme = pr.proxyTarget.Scheme
req.Header.Set("X-Forwarded-Host", req.Header.Get("Host"))
req.Host = pr.proxyTarget.Host
proxy.ServeHTTP(w, req)
}
func main() {
proxy := NewProxy("http://cd.xavier/")
http.ListenAndServe(":8080", proxy)
}