Improve error handling for HTTP client
This commit is contained in:
parent
16c2dc4a8c
commit
dda9114692
5 changed files with 62 additions and 7 deletions
|
@ -7,21 +7,36 @@ package http
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/miniflux/miniflux/errors"
|
||||||
"github.com/miniflux/miniflux/logger"
|
"github.com/miniflux/miniflux/logger"
|
||||||
"github.com/miniflux/miniflux/timer"
|
"github.com/miniflux/miniflux/timer"
|
||||||
"github.com/miniflux/miniflux/version"
|
"github.com/miniflux/miniflux/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
const requestTimeout = 300
|
const (
|
||||||
const maxBodySize = 1024 * 1024 * 15
|
// 20 seconds max.
|
||||||
|
requestTimeout = 20
|
||||||
|
|
||||||
|
// 15MB max.
|
||||||
|
maxBodySize = 1024 * 1024 * 15
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errInvalidCertificate = "Invalid SSL certificate (original error: %q)"
|
||||||
|
errTemporaryNetworkOperation = "This website is temporarily unreachable (original error: %q)"
|
||||||
|
errPermanentNetworkOperation = "This website is permanently unreachable (original error: %q)"
|
||||||
|
errRequestTimeout = "Website unreachable, the request timed out after %d seconds"
|
||||||
|
)
|
||||||
|
|
||||||
// Client is a HTTP Client :)
|
// Client is a HTTP Client :)
|
||||||
type Client struct {
|
type Client struct {
|
||||||
|
@ -77,6 +92,26 @@ func (c *Client) executeRequest(request *http.Request) (*Response, error) {
|
||||||
client := c.buildClient()
|
client := c.buildClient()
|
||||||
resp, err := client.Do(request)
|
resp, err := client.Do(request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if uerr, ok := err.(*url.Error); ok {
|
||||||
|
switch uerr.Err.(type) {
|
||||||
|
case x509.CertificateInvalidError, x509.HostnameError:
|
||||||
|
err = errors.NewLocalizedError(errInvalidCertificate, uerr.Err)
|
||||||
|
case *net.OpError:
|
||||||
|
if uerr.Err.(*net.OpError).Temporary() {
|
||||||
|
err = errors.NewLocalizedError(errTemporaryNetworkOperation, uerr.Err)
|
||||||
|
} else {
|
||||||
|
err = errors.NewLocalizedError(errPermanentNetworkOperation, uerr.Err)
|
||||||
|
}
|
||||||
|
case net.Error:
|
||||||
|
nerr := uerr.Err.(net.Error)
|
||||||
|
if nerr.Timeout() {
|
||||||
|
err = errors.NewLocalizedError(errRequestTimeout, requestTimeout)
|
||||||
|
} else if nerr.Temporary() {
|
||||||
|
err = errors.NewLocalizedError(errTemporaryNetworkOperation, nerr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// Code generated by go generate; DO NOT EDIT.
|
// Code generated by go generate; DO NOT EDIT.
|
||||||
// 2018-02-08 08:24:29.272801 +0100 CET m=+0.026701596
|
// 2018-02-08 18:11:55.663532104 -0800 PST m=+0.009491930
|
||||||
|
|
||||||
package locale
|
package locale
|
||||||
|
|
||||||
|
@ -441,7 +441,11 @@ var translations = map[string]string{
|
||||||
"Miniflux API": "API de Miniflux",
|
"Miniflux API": "API de Miniflux",
|
||||||
"API Endpoint": "Point de terminaison de l'API",
|
"API Endpoint": "Point de terminaison de l'API",
|
||||||
"Your account password": "Le mot de passe de votre compte",
|
"Your account password": "Le mot de passe de votre compte",
|
||||||
"This web page is empty": "Cette page web est vide"
|
"This web page is empty": "Cette page web est vide",
|
||||||
|
"Invalid SSL certificate (original error: %q)": "Certificat SSL invalide (erreur originale : %q)",
|
||||||
|
"This website is temporarily unreachable (original error: %q)": "Ce site web est temporairement injoignable (erreur originale : %q)",
|
||||||
|
"This website is permanently unreachable (original error: %q)": "Ce site web n'est pas joignable de façon permanente (erreur originale : %q)",
|
||||||
|
"Website unreachable, the request timed out after %d seconds": "Site web injoignable, la requête à échouée après %d secondes"
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
|
@ -449,5 +453,5 @@ var translations = map[string]string{
|
||||||
var translationsChecksums = map[string]string{
|
var translationsChecksums = map[string]string{
|
||||||
"de_DE": "6528d76d5c78b45db4a137a092953155e81d47a64e91aa2411829e5d946e0e28",
|
"de_DE": "6528d76d5c78b45db4a137a092953155e81d47a64e91aa2411829e5d946e0e28",
|
||||||
"en_US": "6fe95384260941e8a5a3c695a655a932e0a8a6a572c1e45cb2b1ae8baa01b897",
|
"en_US": "6fe95384260941e8a5a3c695a655a932e0a8a6a572c1e45cb2b1ae8baa01b897",
|
||||||
"fr_FR": "e1f5604630f7dfffe81718f3647d6d3689ec3c4d9a2c78ed7641704e2b913b74",
|
"fr_FR": "ae61f82ac14bc2c6c6a3c2d38cf1ad8309ac2eef19b0726b2969ac155ccddc14",
|
||||||
}
|
}
|
||||||
|
|
|
@ -210,5 +210,9 @@
|
||||||
"Miniflux API": "API de Miniflux",
|
"Miniflux API": "API de Miniflux",
|
||||||
"API Endpoint": "Point de terminaison de l'API",
|
"API Endpoint": "Point de terminaison de l'API",
|
||||||
"Your account password": "Le mot de passe de votre compte",
|
"Your account password": "Le mot de passe de votre compte",
|
||||||
"This web page is empty": "Cette page web est vide"
|
"This web page is empty": "Cette page web est vide",
|
||||||
|
"Invalid SSL certificate (original error: %q)": "Certificat SSL invalide (erreur originale : %q)",
|
||||||
|
"This website is temporarily unreachable (original error: %q)": "Ce site web est temporairement injoignable (erreur originale : %q)",
|
||||||
|
"This website is permanently unreachable (original error: %q)": "Ce site web n'est pas joignable de façon permanente (erreur originale : %q)",
|
||||||
|
"Website unreachable, the request timed out after %d seconds": "Site web injoignable, la requête à échouée après %d secondes"
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,9 @@ func (h *Handler) CreateFeed(userID, categoryID int64, url string, crawler bool)
|
||||||
client := http.NewClient(url)
|
client := http.NewClient(url)
|
||||||
response, err := client.Get()
|
response, err := client.Get()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if _, ok := err.(errors.LocalizedError); ok {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return nil, errors.NewLocalizedError(errRequestFailed, err)
|
return nil, errors.NewLocalizedError(errRequestFailed, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +123,13 @@ func (h *Handler) RefreshFeed(userID, feedID int64) error {
|
||||||
client := http.NewClientWithCacheHeaders(originalFeed.FeedURL, originalFeed.EtagHeader, originalFeed.LastModifiedHeader)
|
client := http.NewClientWithCacheHeaders(originalFeed.FeedURL, originalFeed.EtagHeader, originalFeed.LastModifiedHeader)
|
||||||
response, err := client.Get()
|
response, err := client.Get()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
customErr := errors.NewLocalizedError(errRequestFailed, err)
|
var customErr errors.LocalizedError
|
||||||
|
if lerr, ok := err.(errors.LocalizedError); ok {
|
||||||
|
customErr = lerr
|
||||||
|
} else {
|
||||||
|
customErr = errors.NewLocalizedError(errRequestFailed, err)
|
||||||
|
}
|
||||||
|
|
||||||
originalFeed.ParsingErrorCount++
|
originalFeed.ParsingErrorCount++
|
||||||
originalFeed.ParsingErrorMsg = customErr.Error()
|
originalFeed.ParsingErrorMsg = customErr.Error()
|
||||||
h.store.UpdateFeed(originalFeed)
|
h.store.UpdateFeed(originalFeed)
|
||||||
|
|
|
@ -33,6 +33,9 @@ func FindSubscriptions(websiteURL string) (Subscriptions, error) {
|
||||||
client := http.NewClient(websiteURL)
|
client := http.NewClient(websiteURL)
|
||||||
response, err := client.Get()
|
response, err := client.Get()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if _, ok := err.(errors.LocalizedError); ok {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return nil, errors.NewLocalizedError(errConnectionFailure, err)
|
return nil, errors.NewLocalizedError(errConnectionFailure, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue