diff --git a/backend/app/notify/telegram.go b/backend/app/notify/telegram.go index 61a9d159..5e13e738 100644 --- a/backend/app/notify/telegram.go +++ b/backend/app/notify/telegram.go @@ -42,7 +42,10 @@ func NewTelegram(token string, channelID string, timeout time.Duration, api stri } log.Printf("[DEBUG] create new telegram notifier for cham %s, timeout=%s, api=%s", channelID, res.timeout, res.timeout) - err := repeater.NewDefault(5, time.Millisecond*250).Do(func() error { + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + err := repeater.NewDefault(5, time.Millisecond*250).Do(ctx, func() error { client := http.Client{Timeout: telegramTimeOut} resp, err := client.Get(fmt.Sprintf("%s%s/getMe", res.apiPrefix, token)) if err != nil { diff --git a/backend/app/rest/proxy/image.go b/backend/app/rest/proxy/image.go index 17160658..5ad0b805 100644 --- a/backend/app/rest/proxy/image.go +++ b/backend/app/rest/proxy/image.go @@ -1,6 +1,7 @@ package proxy import ( + "context" "encoding/base64" "io" "net/http" @@ -22,6 +23,7 @@ type Image struct { RemarkURL string RoutePath string Enabled bool + Timeout time.Duration } // Convert all img src links without https to proxied links @@ -51,11 +53,23 @@ func (p Image) Routes() chi.Router { return } + timeout := 60 * time.Second // default + if p.Timeout > 0 { + timeout = p.Timeout + } + + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + client := http.Client{Timeout: 30 * time.Second} var resp *http.Response - err = repeater.NewDefault(5, time.Second).Do(func() error { + err = repeater.NewDefault(5, time.Second).Do(ctx, func() error { var e error - resp, e = client.Get(string(src)) + req, e := http.NewRequest("GET", string(src), nil) + if e != nil { + return errors.Wrapf(e, "failed to make request for %s", r.URL.Query().Get("src")) + } + resp, e = client.Do(req.WithContext(ctx)) return e }) if err != nil { diff --git a/backend/app/rest/proxy/image_test.go b/backend/app/rest/proxy/image_test.go index b7b90098..dc8eae0c 100644 --- a/backend/app/rest/proxy/image_test.go +++ b/backend/app/rest/proxy/image_test.go @@ -3,9 +3,12 @@ package proxy import ( "encoding/base64" "fmt" + "io/ioutil" "net/http" "net/http/httptest" + "strings" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -87,6 +90,25 @@ func TestImage_Routes(t *testing.T) { assert.Equal(t, 400, resp.StatusCode) } +func TestImage_RoutesTimedOut(t *testing.T) { + img := Image{Enabled: true, RemarkURL: "https://demo.remark42.com", RoutePath: "/api/v1/proxy", Timeout: 50 * time.Millisecond} + router := img.Routes() + + httpSrv := imgHTTPServer(t) + defer httpSrv.Close() + ts := httptest.NewServer(router) + defer ts.Close() + + encodedImgURL := base64.URLEncoding.EncodeToString([]byte(httpSrv.URL + "/image/img-slow.png")) + resp, err := http.Get(ts.URL + "/?src=" + encodedImgURL) + require.Nil(t, err) + assert.Equal(t, 400, resp.StatusCode) + b, err := ioutil.ReadAll(resp.Body) + require.Nil(t, err) + t.Log(string(b)) + assert.True(t, strings.Contains(string(b), "deadline exceeded")) +} + func TestPicture_Convert(t *testing.T) { img := Image{Enabled: true, RoutePath: "/img"} r := img.Convert(` xyz `) @@ -113,6 +135,11 @@ func imgHTTPServer(t *testing.T) *httptest.Server { w.Write([]byte(fmt.Sprintf("%123s", "X"))) return } + if r.URL.Path == "/image/img-slow.png" { + time.Sleep(500 * time.Millisecond) + w.WriteHeader(500) + return + } t.Log("http img request - not found", r.URL) w.WriteHeader(404) }))