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

resume song download on network error

parent a338cf49
No related branches found
No related tags found
No related merge requests found
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
"fmt" "fmt"
"io" "io"
"log" "log"
"net/http"
"net/url" "net/url"
"strings" "strings"
"sync" "sync"
...@@ -96,15 +97,55 @@ func (s *DJRandomSong) Open() (io.ReadCloser, error) { ...@@ -96,15 +97,55 @@ func (s *DJRandomSong) Open() (io.ReadCloser, error) {
return nil, errors.New("no audio file") return nil, errors.New("no audio file")
} }
resp, err := s.client.GetRaw("/dl/" + s.audiofile.MD5) 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 { if err != nil {
return nil, err return 0, err
} }
if resp.StatusCode != 200 { if r.resp.StatusCode > 300 {
resp.Body.Close() return 0, fmt.Errorf("HTTP error %d", r.resp.StatusCode)
return nil, fmt.Errorf("HTTP error %d", 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
}
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 { type DJRandomDatabase struct {
......
...@@ -116,6 +116,19 @@ func (h *HttpClient) GetRaw(url string) (*http.Response, error) { ...@@ -116,6 +116,19 @@ func (h *HttpClient) GetRaw(url string) (*http.Response, error) {
return h.bulkClient.Do(req) 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) { func (h *HttpClient) NewRequest(method, relUrl string, data io.Reader) (*http.Request, error) {
fullUrl := fmt.Sprintf("%s%s", h.baseUrl, relUrl) fullUrl := fmt.Sprintf("%s%s", h.baseUrl, relUrl)
return http.NewRequest(method, fullUrl, data) 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