You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
79 lines
2.1 KiB
79 lines
2.1 KiB
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)
|
|
}
|