    {-# LANGUAGE CPP               #-}
    {-# LANGUAGE OverloadedStrings #-}
    {-# LANGUAGE RecordWildCards   #-}

    module Dhall.Import.HTTP
        ( fetchFromHttpUrl
        ) where

    import Control.Exception (Exception)
    import Control.Monad.IO.Class (MonadIO(..))
    import Control.Monad.Trans.State.Strict (StateT)
    import Data.ByteString (ByteString)
    import Data.CaseInsensitive (CI)
    import Data.Dynamic (toDyn)
    import Data.Semigroup ((<>))

    import Dhall.Core
        ( Import(..)
        , ImportHashed(..)
        , ImportType(..)
        , Scheme(..)
        , URL(..)
        )
    import Dhall.URL (renderURL)

    import qualified Control.Monad.Trans.State.Strict as State
    import qualified Data.Text                        as Text
    import qualified Data.Text.Encoding
    import qualified Dhall.Util

    import Dhall.Import.Types

    import qualified Control.Exception
    import qualified Data.List.NonEmpty               as NonEmpty
    import qualified Data.Text.Lazy
    import qualified Data.Text.Lazy.Encoding

    #if MIN_VERSION_http_client(0,5,0)
    import Network.HTTP.Client
        (HttpException(..), HttpExceptionContent(..), Manager)
    #else
    import Network.HTTP.Client (HttpException(..), Manager)
    #endif

    import qualified Network.HTTP.Client                     as HTTP
    import qualified Network.HTTP.Client.TLS                 as HTTP
    import qualified Network.HTTP.Types

    mkPrettyHttpException :: String -> HttpException -> PrettyHttpException
    mkPrettyHttpException :: String -> HttpException -> PrettyHttpException
    mkPrettyHttpException url :: String
    url ex :: HttpException
    ex =
        String -> Dynamic -> PrettyHttpException
    PrettyHttpException (String -> HttpException -> String
    renderPrettyHttpException String
    url HttpException
    ex) (HttpException -> Dynamic
    forall a. Typeable a => a -> Dynamic
    toDyn HttpException
    ex)

    renderPrettyHttpException :: String -> HttpException -> String
    #if MIN_VERSION_http_client(0,5,0)
    renderPrettyHttpException :: String -> HttpException -> String
    renderPrettyHttpException _ (InvalidUrlException _ r :: String
    r) =
          "\n"
      String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "\ESC[1;31mError\ESC[0m: Invalid URL\n"
      String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "\n"
      String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "URL: " String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> String -> String
    forall a. Show a => a -> String
    show String
    r String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> "\n"
    renderPrettyHttpException url :: String
    url (HttpExceptionRequest _ e :: HttpExceptionContent
    e) =
      case HttpExceptionContent
    e of
        ConnectionFailure _ ->
              "\n"
          String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "\ESC[1;31mError\ESC[0m: Remote host not found\n"
          String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "\n"
          String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "URL: " String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> String
    url String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> "\n"
        InvalidDestinationHost host :: ByteString
    host ->
              "\n"
          String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "\ESC[1;31mError\ESC[0m: Invalid remote host name:\n"
          String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "\n"
          String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "Host: " String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> ByteString -> String
    forall a. Show a => a -> String
    show ByteString
    host String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> "\n"
        ResponseTimeout ->
              "\n"
          String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "\ESC[1;31mError\ESC[0m: The remote host took too long to respond\n"
          String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "\n"
          String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "URL: " String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> String
    url String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> "\n"
        StatusCodeException response :: Response ()
    response body :: ByteString
    body -> String
    prefix String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> String
    suffix
          where
            prefix :: String
    prefix
                | Int
    statusCode Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == 401 =
                        "\n"
                    String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "\ESC[1;31mError\ESC[0m: Access unauthorized\n"
                | Int
    statusCode Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == 403 =
                        "\n"
                    String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "\ESC[1;31mError\ESC[0m: Access forbidden\n"
                | Int
    statusCode Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == 404 =
                        "\n"
                    String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "\ESC[1;31mError\ESC[0m: Remote file not found\n"
                | Int
    statusCode Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == 500 =
                        "\n"
                    String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "\ESC[1;31mError\ESC[0m: Server-side failure\n"
                | Int
    statusCode Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == 502 =
                        "\n"
                    String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "\ESC[1;31mError\ESC[0m: Upstream failure\n"
                | Int
    statusCode Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == 503 =
                        "\n"
                    String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "\ESC[1;31mError\ESC[0m: Server temporarily unavailable\n"
                | Int
    statusCode Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == 504 =
                        "\n"
                    String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "\ESC[1;31mError\ESC[0m: Upstream timeout\n"
                | Bool
    otherwise =
                        "\n"
                    String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "\ESC[1;31mError\ESC[0m: HTTP request failure\n"

            suffix :: String
    suffix =
                    "\n"
                String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "HTTP status code: " String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> Int -> String
    forall a. Show a => a -> String
    show Int
    statusCode String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> "\n"
                String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "\n"
                String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "URL: " String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> String
    url String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> "\n"
                String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  String
    message

            statusCode :: Int
    statusCode =
                Status -> Int
    Network.HTTP.Types.statusCode
                    (Response () -> Status
    forall body. Response body -> Status
    HTTP.responseStatus Response ()
    response)

            message :: String
    message =
                case ByteString -> Either UnicodeException Text
    Data.Text.Encoding.decodeUtf8' ByteString
    body of
                    Left _ ->
                            "\n"
                        String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "Message (non-UTF8 bytes):\n"
                        String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "\n"
                        String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  String
    truncatedBodyString String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> "\n"
                      where
                        bodyString :: String
    bodyString = ByteString -> String
    forall a. Show a => a -> String
    show ByteString
    body

                        dots :: String
    dots = "…"

                        truncatedLength :: Int
    truncatedLength = 80 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - String -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length String
    dots

                        truncatedBodyString :: String
    truncatedBodyString
                            | Int
    truncatedLength Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < String -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length String
    bodyString =
                                Int -> String -> String
    forall a. Int -> [a] -> [a]
    take Int
    truncatedLength String
    bodyString String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> String
    dots
                            | Bool
    otherwise =
                                String
    bodyString
                    Right "" ->
                        ""
                    Right bodyText :: Text
    bodyText ->
                            "\n"
                        String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "Message:\n"
                        String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "\n"
                        String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  Text -> String
    Text.unpack Text
    prefixedText
                      where
                        prefixedLines :: [Text]
    prefixedLines =
                            (Text -> Text -> Text) -> [Text] -> [Text] -> [Text]
    forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
    zipWith Text -> Text -> Text
    forall a. (Semigroup a, IsString a) => a -> a -> a
    combine [Text]
    prefixes (Text -> [Text]
    Text.lines Text
    bodyText)
                          where
                            prefixes :: [Text]
    prefixes =
                                (Int -> Text) -> [Int] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map (String -> Text
    Text.pack (String -> Text) -> (Int -> String) -> Int -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> String
    forall a. Show a => a -> String
    show) [(1 ::Int)..7] [Text] -> [Text] -> [Text]
    forall a. [a] -> [a] -> [a]
    ++ [ "…" ]

                            combine :: a -> a -> a
    combine n :: a
    n line :: a
    line = a
    n a -> a -> a
    forall a. Semigroup a => a -> a -> a
    <> "│ " a -> a -> a
    forall a. Semigroup a => a -> a -> a
    <> a
    line

                        prefixedText :: Text
    prefixedText = [Text] -> Text
    Text.unlines [Text]
    prefixedLines

        e' :: HttpExceptionContent
    e' -> "\n" String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> HttpExceptionContent -> String
    forall a. Show a => a -> String
    show HttpExceptionContent
    e' String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> "\n"
    #else
    renderPrettyHttpException url e = case e of
        FailedConnectionException2 _ _ _ e' ->
                "\n"
            <>  "\ESC[1;31mError\ESC[0m: Wrong host:\n"
            <>  "\n"
            <>  "Host: " <> show e' <> "\n"
        InvalidDestinationHost host ->
                "\n"
            <>  "\ESC[1;31mError\ESC[0m: Invalid host name:\n"
            <>  "\n"
            <>  "Host: " <> show host <> "\n"
        ResponseTimeout ->
                "\ESC[1;31mError\ESC[0m: The host took too long to respond\n"
            <>  "\n"
            <>  "URL: " <> url <> "\n"
        e' ->   "\n"
            <>  show e' <> "\n"
    #endif

    newManager :: StateT Status IO Manager
    newManager :: StateT Status IO Manager
    newManager = do
        let settings :: ManagerSettings
    settings = ManagerSettings
    HTTP.tlsManagerSettings
    #if MIN_VERSION_http_client(0,5,0)
              { managerResponseTimeout :: ResponseTimeout
    HTTP.managerResponseTimeout = Int -> ResponseTimeout
    HTTP.responseTimeoutMicro (30 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * 1000 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * 1000) }  -- 30 seconds
    #else
              { HTTP.managerResponseTimeout = Just (30 * 1000 * 1000) }  -- 30 seconds
    #endif

        Status { _manager :: Status -> Maybe Manager
    _manager = Maybe Manager
    oldManager, ..} <- StateT Status IO Status
    forall (m :: * -> *) s. Monad m => StateT s m s
    State.get

        case Maybe Manager
    oldManager of
            Nothing -> do
                Manager
    manager <- IO Manager -> StateT Status IO Manager
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (ManagerSettings -> IO Manager
    HTTP.newManager ManagerSettings
    settings)

                Status -> StateT Status IO ()
    forall (m :: * -> *) s. Monad m => s -> StateT s m ()
    State.put (Status :: NonEmpty Chained
    -> [Depends]
    -> Map Chained ImportSemantics
    -> Maybe Manager
    -> (URL -> StateT Status IO Text)
    -> Substitutions Src Void
    -> Maybe (ReifiedNormalizer Void)
    -> Context (Expr Src Void)
    -> SemanticCacheMode
    -> Status
    Status { _manager :: Maybe Manager
    _manager = Manager -> Maybe Manager
    forall a. a -> Maybe a
    Just Manager
    manager , ..})

                Manager -> StateT Status IO Manager
    forall (m :: * -> *) a. Monad m => a -> m a
    return Manager
    manager

            Just manager :: Manager
    manager -> do
                Manager -> StateT Status IO Manager
    forall (m :: * -> *) a. Monad m => a -> m a
    return Manager
    manager

    data NotCORSCompliant = NotCORSCompliant
        { NotCORSCompliant -> [ByteString]
    expectedOrigins :: [ByteString]
        , NotCORSCompliant -> ByteString
    actualOrigin    :: ByteString
        }

    instance Exception NotCORSCompliant

    instance Show NotCORSCompliant where
        show :: NotCORSCompliant -> String
    show (NotCORSCompliant {..}) =
                String
    forall string. IsString string => string
    Dhall.Util._ERROR String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> ": Not CORS compliant\n"
            String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "\n"
            String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "Dhall supports transitive imports, meaning that an imported expression can\n"
            String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "import other expressions.  However, a remote import (the \"parent\" import)\n"
            String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "cannot import another remote import (the \"child\" import) unless the child\n"
            String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "import grants permission to do using CORS.  The child import must respond with\n"
            String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "an `Access-Control-Allow-Origin` response header that matches the parent\n"
            String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "import, otherwise Dhall rejects the import.\n"
            String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "\n" String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> String
    prologue
          where
            prologue :: String
    prologue =
                case [ByteString]
    expectedOrigins of
                    [ expectedOrigin :: ByteString
    expectedOrigin ] ->
                            "The following parent import:\n"
                        String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "\n"
                        String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "↳ " String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> ByteString -> String
    forall a. Show a => a -> String
    show ByteString
    actualOrigin String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> "\n"
                        String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "\n"
                        String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "... did not match the expected origin:\n"
                        String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "\n"
                        String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "↳ " String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> ByteString -> String
    forall a. Show a => a -> String
    show ByteString
    expectedOrigin String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> "\n"
                        String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "\n"
                        String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "... so import resolution failed.\n"
                    [] ->
                            "The child response did not include any `Access-Control-Allow-Origin` header,\n"
                        String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "so import resolution failed.\n"
                    _:_:_ ->
                            "The child response included more than one `Access-Control-Allow-Origin` header,\n"
                        String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "when only one such header should have been present, so import resolution\n"
                        String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "failed.\n"
                        String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "\n"
                        String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <>  "This may indicate that the server for the child import is misconfigured.\n"

    corsCompliant
        :: MonadIO io
        => ImportType -> URL -> [(CI ByteString, ByteString)] -> io ()
    corsCompliant :: ImportType -> URL -> [(CI ByteString, ByteString)] -> io ()
    corsCompliant (Remote parentURL :: URL
    parentURL) childURL :: URL
    childURL responseHeaders :: [(CI ByteString, ByteString)]
    responseHeaders = IO () -> io ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> io ()) -> IO () -> io ()
    forall a b. (a -> b) -> a -> b
    $ do
        let toOrigin :: URL -> ByteString
    toOrigin (URL {..}) =
                Text -> ByteString
    Data.Text.Encoding.encodeUtf8 (Text
    prefix Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> "://" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    authority)
              where
                prefix :: Text
    prefix =
                    case Scheme
    scheme of
                        HTTP  -> "http"
                        HTTPS -> "https"

        let actualOrigin :: ByteString
    actualOrigin = URL -> ByteString
    toOrigin URL
    parentURL

        let childOrigin :: ByteString
    childOrigin = URL -> ByteString
    toOrigin URL
    childURL

        let predicate :: (a, b) -> Bool
    predicate (header :: a
    header, _) = a
    header a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    == "Access-Control-Allow-Origin"

        let originHeaders :: [(CI ByteString, ByteString)]
    originHeaders = ((CI ByteString, ByteString) -> Bool)
    -> [(CI ByteString, ByteString)] -> [(CI ByteString, ByteString)]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (CI ByteString, ByteString) -> Bool
    forall a b. (Eq a, IsString a) => (a, b) -> Bool
    predicate [(CI ByteString, ByteString)]
    responseHeaders

        let expectedOrigins :: [ByteString]
    expectedOrigins = ((CI ByteString, ByteString) -> ByteString)
    -> [(CI ByteString, ByteString)] -> [ByteString]
    forall a b. (a -> b) -> [a] -> [b]
    map (CI ByteString, ByteString) -> ByteString
    forall a b. (a, b) -> b
    snd [(CI ByteString, ByteString)]
    originHeaders

        case [ByteString]
    expectedOrigins of
            [expectedOrigin :: ByteString
    expectedOrigin]
                | ByteString
    expectedOrigin ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == "*" ->
                    () -> IO ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
                | ByteString
    expectedOrigin ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteString
    actualOrigin ->
                    () -> IO ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
            _   | ByteString
    actualOrigin ByteString -> ByteString -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteString
    childOrigin ->
                    () -> IO ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
                | Bool
    otherwise ->
                    NotCORSCompliant -> IO ()
    forall e a. Exception e => e -> IO a
    Control.Exception.throwIO (NotCORSCompliant :: [ByteString] -> ByteString -> NotCORSCompliant
    NotCORSCompliant {..})
    corsCompliant _ _ _ = () -> io ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()

    type HTTPHeader = Network.HTTP.Types.Header

    fetchFromHttpUrl :: URL -> Maybe [HTTPHeader] -> StateT Status IO Text.Text
    fetchFromHttpUrl :: URL -> Maybe [(CI ByteString, ByteString)] -> StateT Status IO Text
    fetchFromHttpUrl childURL :: URL
    childURL mheaders :: Maybe [(CI ByteString, ByteString)]
    mheaders = do
        Manager
    manager <- StateT Status IO Manager
    newManager

        let childURLString :: String
    childURLString = Text -> String
    Text.unpack (URL -> Text
    renderURL URL
    childURL)

        Request
    request <- IO Request -> StateT Status IO Request
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (String -> IO Request
    forall (m :: * -> *). MonadThrow m => String -> m Request
    HTTP.parseUrlThrow String
    childURLString)

        let requestWithHeaders :: Request
    requestWithHeaders =
                case Maybe [(CI ByteString, ByteString)]
    mheaders of
                  Nothing      -> Request
    request
                  Just headers :: [(CI ByteString, ByteString)]
    headers -> Request
    request { requestHeaders :: [(CI ByteString, ByteString)]
    HTTP.requestHeaders = [(CI ByteString, ByteString)]
    headers }

        let io :: IO (Response ByteString)
    io = Request -> Manager -> IO (Response ByteString)
    HTTP.httpLbs Request
    requestWithHeaders Manager
    manager

        let handler :: HttpException -> IO a
    handler e :: HttpException
    e = do
                let HttpException
    _ = HttpException
    e :: HttpException
                PrettyHttpException -> IO a
    forall e a. Exception e => e -> IO a
    Control.Exception.throwIO (String -> HttpException -> PrettyHttpException
    mkPrettyHttpException String
    childURLString HttpException
    e)

        Response ByteString
    response <- IO (Response ByteString) -> StateT Status IO (Response ByteString)
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO ((HttpException -> IO (Response ByteString))
    -> IO (Response ByteString) -> IO (Response ByteString)
    forall e a. Exception e => (e -> IO a) -> IO a -> IO a
    Control.Exception.handle HttpException -> IO (Response ByteString)
    forall a. HttpException -> IO a
    handler IO (Response ByteString)
    io)

        Status {..} <- StateT Status IO Status
    forall (m :: * -> *) s. Monad m => StateT s m s
    State.get

        let Chained parentImport :: Import
    parentImport = NonEmpty Chained -> Chained
    forall a. NonEmpty a -> a
    NonEmpty.head NonEmpty Chained
    _stack

        let parentImportType :: ImportType
    parentImportType = ImportHashed -> ImportType
    importType (Import -> ImportHashed
    importHashed Import
    parentImport)

        ImportType
    -> URL -> [(CI ByteString, ByteString)] -> StateT Status IO ()
    forall (io :: * -> *).
    MonadIO io =>
    ImportType -> URL -> [(CI ByteString, ByteString)] -> io ()
    corsCompliant ImportType
    parentImportType URL
    childURL (Response ByteString -> [(CI ByteString, ByteString)]
    forall body. Response body -> [(CI ByteString, ByteString)]
    HTTP.responseHeaders Response ByteString
    response)

        let bytes :: ByteString
    bytes = Response ByteString -> ByteString
    forall body. Response body -> body
    HTTP.responseBody Response ByteString
    response

        case ByteString -> Either UnicodeException Text
    Data.Text.Lazy.Encoding.decodeUtf8' ByteString
    bytes of
            Left  err :: UnicodeException
    err  -> IO Text -> StateT Status IO Text
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (UnicodeException -> IO Text
    forall e a. Exception e => e -> IO a
    Control.Exception.throwIO UnicodeException
    err)
            Right text :: Text
    text -> Text -> StateT Status IO Text
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Text -> Text
    Data.Text.Lazy.toStrict Text
    text)