diff --git a/internal/integration/rssbridge/rssbridge.go b/internal/integration/rssbridge/rssbridge.go index 672d36b6..74cb6a0f 100644 --- a/internal/integration/rssbridge/rssbridge.go +++ b/internal/integration/rssbridge/rssbridge.go @@ -6,10 +6,15 @@ package rssbridge // import "miniflux.app/integration/rssbridge" import ( "encoding/json" "fmt" + "log/slog" "net/http" "net/url" + "strings" + "time" ) +const defaultClientTimeout = 30 * time.Second + type Bridge struct { URL string `json:"url"` BridgeMeta BridgeMeta `json:"bridgeMeta"` @@ -19,30 +24,61 @@ type BridgeMeta struct { Name string `json:"name"` } -func DetectBridges(rssbridgeURL, websiteURL string) (bridgeResponse []Bridge, err error) { - u, err := url.Parse(rssbridgeURL) +func DetectBridges(rssBridgeURL, websiteURL string) ([]*Bridge, error) { + endpointURL, err := url.Parse(rssBridgeURL) if err != nil { - return nil, err + return nil, fmt.Errorf("RSS-Bridge: unable to parse bridge URL: %w", err) } - values := u.Query() + + values := endpointURL.Query() values.Add("action", "findfeed") values.Add("format", "atom") values.Add("url", websiteURL) - u.RawQuery = values.Encode() + endpointURL.RawQuery = values.Encode() - response, err := http.Get(u.String()) + slog.Debug("Detecting RSS bridges", slog.String("url", endpointURL.String())) + + request, err := http.NewRequest(http.MethodGet, endpointURL.String(), nil) if err != nil { - return nil, fmt.Errorf("RSS-Bridge: unable to excute request: %w", err) + return nil, fmt.Errorf("RSS-Bridge: unable to create request: %w", err) + } + + httpClient := &http.Client{Timeout: defaultClientTimeout} + + response, err := httpClient.Do(request) + if err != nil { + return nil, fmt.Errorf("RSS-Bridge: unable to execute request: %w", err) } defer response.Body.Close() + if response.StatusCode == http.StatusNotFound { - return + return nil, nil } + if response.StatusCode > 400 { return nil, fmt.Errorf("RSS-Bridge: unexpected status code %d", response.StatusCode) } + + var bridgeResponse []*Bridge if err := json.NewDecoder(response.Body).Decode(&bridgeResponse); err != nil { return nil, fmt.Errorf("RSS-Bridge: unable to decode bridge response: %w", err) } - return + + for _, bridge := range bridgeResponse { + slog.Debug("Found RSS bridge", + slog.String("name", bridge.BridgeMeta.Name), + slog.String("url", bridge.URL), + ) + + if strings.HasPrefix(bridge.URL, "./") { + bridge.URL = rssBridgeURL + bridge.URL[2:] + + slog.Debug("Rewrited relative RSS bridge URL", + slog.String("name", bridge.BridgeMeta.Name), + slog.String("url", bridge.URL), + ) + } + } + + return bridgeResponse, nil }