packages feed

link-canonical-0.1.0.0: src/Link/Canonical/Types.hs

module Link.Canonical.Types
  ( -- * Result types
    NormResult (..),
    NormTrace (..),

    -- * Configuration types
    NormConfig (..),
    RedirectConfig (..),
    TrackingConfig (..),
    TrailingSlash (..),

    -- * Observability
    NormHooks (..),
  )
where

import Link.Canonical.Prelude

-- | Result of URL normalization
data NormResult = NormResult
  { -- | The canonical form of the URL
    canonical :: URI,
    -- | The original input URL
    original :: URI,
    -- | Number of redirects followed
    redirectsCount :: Int,
    -- | Full redirect chain for debugging
    redirectChain :: [URI],
    -- | Name of the domain rule applied, if any
    ruleApplied :: Maybe Text,
    -- | Tracking parameters that were removed
    paramsStripped :: [Text]
  }
  deriving stock (Generic, Eq, Show)

-- | Detailed trace of normalization for debugging
data NormTrace = NormTrace
  { -- | Original input
    input :: URI,
    -- | After redirect resolution
    afterRedirects :: URI,
    -- | After generic normalization
    afterGeneric :: URI,
    -- | After domain-specific rules
    afterDomain :: URI,
    -- | Final canonical URL
    final :: URI,
    -- | All URLs in redirect chain
    redirectChain :: [URI],
    -- | Domain rule that was applied
    ruleApplied :: Maybe Text,
    -- | Total processing time
    duration :: NominalDiffTime
  }
  deriving stock (Generic, Eq, Show)

-- | Main configuration for URL normalization
data NormConfig = NormConfig
  { -- | Redirect resolution settings
    redirects :: RedirectConfig,
    -- | Tracking parameter settings
    tracking :: TrackingConfig,
    -- | Whether to remove URL fragments (default: True)
    stripFragment :: Bool,
    -- | Whether to sort query parameters (default: True)
    sortParams :: Bool,
    -- | Trailing slash policy (default: Strip)
    trailingSlash :: TrailingSlash
  }
  deriving stock (Generic)

-- | Policy for handling trailing slashes in paths
data TrailingSlash
  = -- | Keep trailing slashes as-is
    Keep
  | -- | Remove trailing slashes
    Strip
  | -- | Add trailing slashes
    Add
  deriving stock (Generic, Eq, Show)

-- | Configuration for redirect resolution
data RedirectConfig = RedirectConfig
  { -- | Maximum number of redirects to follow (default: 10)
    maxRedirects :: Int,
    -- | Timeout per request in seconds (default: 10)
    timeout :: NominalDiffTime,
    -- | Allow HTTPS to HTTP downgrades (default: False)
    allowDowngrade :: Bool,
    -- | Block redirects to private IPs for SSRF protection (default: True)
    blockPrivateIPs :: Bool,
    -- | User-Agent header value
    userAgent :: Text
  }
  deriving stock (Generic)

-- | Configuration for tracking parameter removal
data TrackingConfig = TrackingConfig
  { -- | Patterns to match tracking parameters (supports * suffix wildcards)
    denyPatterns :: [Text],
    -- | Parameters to never strip, even if they match deny patterns
    allowlist :: Set Text
  }
  deriving stock (Generic)

-- | Hooks for observability during normalization
data NormHooks m = NormHooks
  { -- | Called for each redirect: (from, to)
    onRedirectStep :: URI -> URI -> m (),
    -- | Called when a domain rule is applied: (ruleName, before, after)
    onRuleApplied :: Text -> URI -> URI -> m (),
    -- | Called when normalization completes
    onNormComplete :: NormTrace -> m ()
  }
  deriving stock (Generic)