package main import ( "fmt" "net/http" "strings" "flag" ) var( serverAddr string ) func main() { flag.StringVar(&serverAddr,"addr",":80","server listen addr") flag.Parse() http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { _, _ = w.Write([]byte("radio relay server")) }) http.HandleFunc("/play", handlePlay) _ = http.ListenAndServe(serverAddr, nil) } //提取http头中包含icy-的key-value对 func extractIcyHeaders(headers map[string][]string) map[string]string{ icyHeaders := make(map[string] string) for k, v := range headers{ k=strings.ToLower(k) if strings.HasPrefix(k,"icy-"){ if len(v)==0{ icyHeaders[k]="" }else{ icyHeaders[k]=v[0] } } } return icyHeaders } func sendRequest(url string, icyRequestHeaders map[string]string) *http.Response { if len(url)<5{ fmt.Println("url length too short!") return nil } client := &http.Client{} request, err:= http.NewRequest("GET", url, nil) if err != nil { fmt.Println(err.Error()) return nil } for k, v := range icyRequestHeaders { request.Header[k]=[]string{v} } response, err := client.Do(request) if err != nil { fmt.Println(err.Error()) return nil } return response } func receiveBody(response *http.Response) (exitChan chan struct{},dataChan chan []byte){ exitChan=make(chan struct{}) dataChan=make(chan []byte, 10) go func() { defer close(dataChan) defer response.Body.Close() for { select { case <-exitChan: fmt.Println("exit receive data!") return default:{ buf := make([]byte, 4096) n, err:= response.Body.Read(buf) if err != nil || n == 0{ fmt.Println("receive data error!") return }else{ dataChan <-buf[:n] } } } } }() return } func setResponseHeaders(w http.ResponseWriter,response *http.Response){ w.Header().Set("Content-Type","audio/mpeg") w.Header().Set("transfer-encoding","identity") icyResponseHeaders:=extractIcyHeaders(response.Header) for k, v := range icyResponseHeaders { w.Header()[k]=[]string{v} } } func sendBody(w http.ResponseWriter, dataChan <-chan []byte) { for { data,ok := <-dataChan if (!ok){ fmt.Println("receive data error!") break } n, err := w.Write(data) if err != nil || n == 0 { fmt.Println("send data error!") break } } } func handlePlay(w http.ResponseWriter, r *http.Request) { _ = r.ParseForm() url:=r.Form.Get("url") response:=sendRequest(url,extractIcyHeaders(r.Form)); if (response!=nil){ setResponseHeaders(w,response) exitChan,dataChan:=receiveBody(response); sendBody(w, dataChan) close(exitChan) }else{ w.WriteHeader(500) } }