Skip to content
Snippets Groups Projects
Commit 34826f9a authored by ale's avatar ale
Browse files

resume song download on network error

parent a338cf49
Branches
No related tags found
No related merge requests found
......@@ -7,6 +7,7 @@ import (
"fmt"
"io"
"log"
"net/http"
"net/url"
"strings"
"sync"
......@@ -96,15 +97,55 @@ func (s *DJRandomSong) Open() (io.ReadCloser, error) {
return nil, errors.New("no audio file")
}
resp, err := s.client.GetRaw("/dl/" + s.audiofile.MD5)
if err != nil {
return nil, err
return &songReader{
client: s.client,
url: "/dl/" + s.audiofile.MD5,
size: s.audiofile.Size,
}, nil
}
// A streaming HTTP reader that can resume the download on error.
type songReader struct {
client *util.HttpClient
url string
pos, size int64
resp *http.Response
}
func (r *songReader) Read(buf []byte) (int, error) {
var err error
for i := 0; i < 2; i++ {
if r.pos >= r.size {
return 0, io.EOF
}
if r.resp == nil {
r.resp, err = r.client.GetRawRange(r.url, r.pos, r.size)
if err != nil {
return 0, err
}
if r.resp.StatusCode > 300 {
return 0, fmt.Errorf("HTTP error %d", r.resp.StatusCode)
}
}
var n int
n, err = r.resp.Body.Read(buf)
if n > 0 {
r.pos += int64(n)
return n, err
}
log.Printf("HTTP read error: %v", err)
r.resp.Body.Close()
r.resp = nil
}
if resp.StatusCode != 200 {
resp.Body.Close()
return nil, fmt.Errorf("HTTP error %d", resp.StatusCode)
return 0, err
}
func (r *songReader) Close() error {
if r.resp != nil {
r.resp.Body.Close()
}
return resp.Body, nil
return nil
}
type DJRandomDatabase struct {
......
......@@ -116,6 +116,19 @@ func (h *HttpClient) GetRaw(url string) (*http.Response, error) {
return h.bulkClient.Do(req)
}
func (h *HttpClient) GetRawRange(url string, beg, end int64) (*http.Response, error) {
req, err := h.NewRequest("GET", url, nil)
if err != nil {
log.Printf("GetRaw(%s): NewRequest error: %s", url, err)
return nil, err
}
req.Header.Add("Range", fmt.Sprintf("bytes=%d-%d", beg, end-1))
SignHttpRequest(h.authKey, req)
return h.bulkClient.Do(req)
}
func (h *HttpClient) NewRequest(method, relUrl string, data io.Reader) (*http.Request, error) {
fullUrl := fmt.Sprintf("%s%s", h.baseUrl, relUrl)
return http.NewRequest(method, fullUrl, data)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment