| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- 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
- }
|