Validate the federation tester URI placeholder, escape the domain, set a client timeout, cap the response body, and ship CA certificates in the scratch image so HTTPS calls succeed. Sort hosts, connection reports, and errors when rendering so output is deterministic, and deduplicate TLS problems. Drop the deprecated aggregate Rule() and add tests for collection and rules.
62 lines
1.7 KiB
Go
62 lines
1.7 KiB
Go
package checker
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
"time"
|
|
|
|
sdk "git.happydns.org/checker-sdk-go/checker"
|
|
)
|
|
|
|
const (
|
|
defaultTesterURI = "https://federationtester.matrix.org/api/report?server_name=%s"
|
|
collectHTTPTimeout = 30 * time.Second
|
|
maxResponseBodySize = 5 << 20 // 5 MiB
|
|
)
|
|
|
|
var collectHTTPClient = &http.Client{Timeout: collectHTTPTimeout}
|
|
|
|
func (p *matrixProvider) Collect(ctx context.Context, opts sdk.CheckerOptions) (any, error) {
|
|
domain, _ := opts["serviceDomain"].(string)
|
|
if domain == "" {
|
|
return nil, fmt.Errorf("serviceDomain is required")
|
|
}
|
|
domain = strings.TrimSuffix(domain, ".")
|
|
|
|
testerURI, _ := opts["federationTesterServer"].(string)
|
|
if testerURI == "" {
|
|
testerURI = defaultTesterURI
|
|
}
|
|
if !strings.Contains(testerURI, "%s") {
|
|
return nil, fmt.Errorf("federationTesterServer must contain a %%s placeholder for the domain")
|
|
}
|
|
|
|
reqURL := fmt.Sprintf(testerURI, url.QueryEscape(domain))
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqURL, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("unable to build the request: %w", err)
|
|
}
|
|
|
|
resp, err := collectHTTPClient.Do(req)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("unable to perform the test: %w", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode >= 300 {
|
|
return nil, fmt.Errorf("federation tester returned status %d; check https://federationtester.matrix.org/#%s", resp.StatusCode, domain)
|
|
}
|
|
|
|
var data MatrixFederationData
|
|
if err := json.NewDecoder(io.LimitReader(resp.Body, maxResponseBodySize)).Decode(&data); err != nil {
|
|
return nil, fmt.Errorf("failed to decode federation tester response: %w", err)
|
|
}
|
|
|
|
return &data, nil
|
|
}
|