Files
Sanaei f727d04f65
CI / go-test (push) Canceled after 0s
CI / postgres-durable-first (push) Canceled after 0s
CI / codegen (push) Canceled after 0s
CI / govulncheck (push) Canceled after 0s
CI / race (push) Canceled after 0s
CI / fuzz-smoke (push) Canceled after 0s
CI / golangci (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CodeQL Advanced / Analyze (go) (push) Canceled after 0s
CodeQL Advanced / Analyze (actions) (push) Canceled after 0s
CodeQL Advanced / Analyze (javascript-typescript) (push) Canceled after 0s
Docs CI / build (push) Canceled after 0s
Docs Deploy (GitHub Pages) / build (push) Canceled after 0s
Release 3X-UI / build (386) (push) Canceled after 0s
Release 3X-UI / build (amd64) (push) Canceled after 0s
Release 3X-UI / build (arm64) (push) Canceled after 0s
Release 3X-UI / build (armv5) (push) Canceled after 0s
Release 3X-UI / build (armv6) (push) Canceled after 0s
Release 3X-UI / build (armv7) (push) Canceled after 0s
Release 3X-UI / build (s390x) (push) Canceled after 0s
Release 3X-UI / Build for Windows (amd64) (push) Canceled after 0s
Deploy Smoke Tests / noninteractive-install (ubuntu-24.04-arm) (push) Canceled after 0s
Deploy Smoke Tests / noninteractive-install (ubuntu-latest) (push) Canceled after 0s
Deploy Smoke Tests / release-tag-install (ubuntu-24.04-arm) (push) Canceled after 0s
Deploy Smoke Tests / release-tag-install (ubuntu-latest) (push) Canceled after 0s
Docs Deploy (GitHub Pages) / deploy (push) Canceled after 0s
Release 3X-UI / Publish rolling dev release (push) Canceled after 0s
v3.7.0
2026-08-24 15:07:15 +02:00

101 lines
2.5 KiB
Go

package pia
import (
"bytes"
"context"
"crypto/x509"
"encoding/json"
"errors"
"fmt"
"io"
"mime"
"net"
"net/http"
"strings"
)
func readLimitedBody(body io.Reader, limit int64) ([]byte, error) {
raw, err := io.ReadAll(io.LimitReader(body, limit+1))
if err != nil {
return nil, err
}
if int64(len(raw)) > limit {
return nil, fmt.Errorf("response exceeds %d bytes", limit)
}
return raw, nil
}
func expectedContentType(header string, accepted ...string) bool {
mediaType, _, err := mime.ParseMediaType(header)
if err != nil {
return false
}
for _, candidate := range accepted {
if strings.EqualFold(mediaType, candidate) {
return true
}
}
return false
}
func noRedirect(_ *http.Request, _ []*http.Request) error {
return errors.New("redirects are disabled for this request")
}
func decodeSingleJSON(raw []byte, target any) error {
decoder := json.NewDecoder(bytes.NewReader(raw))
decoder.UseNumber()
if err := decoder.Decode(target); err != nil {
return err
}
var extra any
if err := decoder.Decode(&extra); !errors.Is(err, io.EOF) {
if err == nil {
return errors.New("multiple JSON values are not allowed")
}
return err
}
return nil
}
func classifyNetworkError(ctx context.Context, fallback, message string, err error) error {
cause := redactNetErr(err)
if errors.Is(ctx.Err(), context.Canceled) || errors.Is(err, context.Canceled) {
return WrapError(CodeCancelled, "The operation was cancelled.", cause)
}
if errors.Is(ctx.Err(), context.DeadlineExceeded) || errors.Is(err, context.DeadlineExceeded) {
return WrapError(CodeTimeout, "The network request timed out.", cause)
}
var netErr net.Error
if errors.As(err, &netErr) && netErr.Timeout() {
return WrapError(CodeTimeout, "The network request timed out.", cause)
}
var unknownAuthority x509.UnknownAuthorityError
var hostnameError x509.HostnameError
var invalidCertificate x509.CertificateInvalidError
if errors.As(err, &unknownAuthority) || errors.As(err, &hostnameError) || errors.As(err, &invalidCertificate) {
return WrapError(CodeTLSValidation, "PIA's server identity could not be verified.", cause)
}
return WrapError(fallback, message, cause)
}
type redactedCause struct{ kind string }
func (e redactedCause) Error() string { return e.kind }
func redactNetErr(err error) error {
if err == nil {
return nil
}
return redactedCause{kind: "network error"}
}
func containsSecret(s string, secrets ...string) bool {
for _, secret := range secrets {
if secret != "" && strings.Contains(s, secret) {
return true
}
}
return false
}