Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for headers.dhall configuration #2236

Merged
merged 25 commits into from
Sep 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
6a02fac
WIP support for ~/.config/dhall/headers.dhall
timbertson Jun 29, 2021
01438f1
load headers as dhall expressions, not JSON
timbertson Jul 24, 2021
b60c084
load headers from env in tests
timbertson Jul 25, 2021
8c859bb
user headers take precedent over inline headers
timbertson Jul 25, 2021
5c0711c
move UserHeaders out of HTTP manager
timbertson Aug 1, 2021
d8ff7ce
cleanup
timbertson Aug 1, 2021
9f33559
use caller's stack when importing headers
timbertson Aug 3, 2021
addfbaa
revert unnecessary change
timbertson Aug 3, 2021
54f2eda
Merge remote-tracking branch 'origin/master' into user-headers
timbertson Sep 15, 2021
e8ce0e8
PR feedback
timbertson Sep 16, 2021
65f3a12
Implement site headers loading as a plain dhall expression
timbertson Sep 18, 2021
b233d23
refer to site / user headers as originHeaders consistently
timbertson Sep 18, 2021
1799fd1
revert unnecessary diffs
timbertson Sep 18, 2021
9e51f6b
minor
timbertson Sep 18, 2021
85afb69
Load origin headers with an empty stack
timbertson Sep 19, 2021
dd85fba
revert the addition of OriginHeaders ImportMode
timbertson Sep 19, 2021
88f6fbd
reset dhall-lang submodule
timbertson Sep 19, 2021
c77f5a7
loadOriginHeaders: use parent stack instead of special-casing reentra…
timbertson Sep 21, 2021
02a65a3
fix compilation failure when building without http
timbertson Sep 24, 2021
a78e942
revert unnecessary diffs
timbertson Sep 24, 2021
14201cd
Merge remote-tracking branch 'origin/master' into user-headers
timbertson Sep 24, 2021
dd515d9
raise haddock coverage in Import module
timbertson Sep 24, 2021
0d9ffa2
fix haddock warning
timbertson Sep 25, 2021
84b4c6d
Merge remote-tracking branch 'origin/master' into user-headers
timbertson Sep 25, 2021
770cbab
fix compilation error when HTTP is disabled
timbertson Sep 25, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions dhall/dhall.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,7 @@ Library
Other-Modules:
Dhall.Eval
Dhall.Import.Types
Dhall.Import.Headers
Dhall.Marshal.Internal
Dhall.Normalize
Dhall.Parser.Combinators
Expand Down
49 changes: 42 additions & 7 deletions dhall/ghc-src/Dhall/Import/HTTP.hs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}

module Dhall.Import.HTTP
( fetchFromHttpUrl
, originHeadersFileExpr
) where

import Control.Exception (Exception)
Expand All @@ -12,21 +14,31 @@ import Data.ByteString (ByteString)
import Data.CaseInsensitive (CI)
import Data.Dynamic (toDyn)
import Data.List.NonEmpty (NonEmpty (..))
import Data.Text.Encoding (decodeUtf8)
import Dhall.Core
( Import (..)
( Expr (..)
, Directory (..)
, File (..)
, FilePrefix (..)
, Import (..)
, ImportHashed (..)
, ImportMode (..)
, ImportType (..)
, Scheme (..)
, URL (..)
)
import Dhall.Import.Types
import Dhall.Parser (Src)
import Dhall.URL (renderURL)
import System.Directory (getXdgDirectory, XdgDirectory(XdgConfig))
import System.FilePath (splitDirectories)


import Network.HTTP.Client (HttpException (..), HttpExceptionContent (..))

import qualified Control.Exception
import qualified Control.Monad.Trans.State.Strict as State
import qualified Data.HashMap.Strict as HashMap
import qualified Data.Text as Text
import qualified Data.Text.Encoding
import qualified Data.Text.Lazy
Expand Down Expand Up @@ -238,20 +250,35 @@ corsCompliant (Remote parentURL) childURL responseHeaders = liftIO $ do
Control.Exception.throwIO (NotCORSCompliant {..})
corsCompliant _ _ _ = return ()

type HTTPHeader = Network.HTTP.Types.Header
addHeaders :: OriginHeaders -> Maybe [HTTPHeader] -> HTTP.Request -> HTTP.Request
addHeaders originHeaders urlHeaders request =
request { HTTP.requestHeaders = (filterHeaders urlHeaders) <> perOriginHeaders }
where
origin = decodeUtf8 (HTTP.host request) <> ":" <> Text.pack (show (HTTP.port request))

perOriginHeaders = HashMap.lookupDefault [] origin originHeaders

filterHeaders = foldMap (filter (not . overridden))

overridden :: HTTPHeader -> Bool
overridden (key, _value) = any (matchesKey key) perOriginHeaders

matchesKey :: CI ByteString -> HTTPHeader -> Bool
matchesKey key (candidate, _value) = key == candidate

fetchFromHttpUrl :: URL -> Maybe [HTTPHeader] -> StateT Status IO Text.Text
fetchFromHttpUrl childURL mheaders = do
Status { _loadOriginHeaders } <- State.get

originHeaders <- _loadOriginHeaders
Copy link
Collaborator

@Gabriella439 Gabriella439 Sep 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made one mistake when I previously suggested using the ambient StateT for _loadOriginHeaders. We do still want _loadOriginHeaders to use StateT, but we want the _stack to be temporarily reset to contain just one import, which is the path to origin headers. This is because of this line from the standard:

(ε, headersPath) × Γ₀ ⊢ userHeadersExpr ⇒ userHeaders ⊢ Γ₁ ; Resolve userHeadersExpr with an empty import context

The key bit is the (ε, headersPath) part, which says that when resolving the userHeadersExpr you want the stack to contain only the headers path and nothing else.

However, we don't have to reset the stack here within the fetchFromHttpUrl function. Instead, I think the best place to do that would be inside of the _loadOriginHeaders function. I'll comment below with some more notes about how to do that.


manager <- newManager

let childURLString = Text.unpack (renderURL childURL)

request <- liftIO (HTTP.parseUrlThrow childURLString)
baseRequest <- liftIO (HTTP.parseUrlThrow childURLString)

let requestWithHeaders =
case mheaders of
Nothing -> request
Just headers -> request { HTTP.requestHeaders = headers }
let requestWithHeaders = addHeaders originHeaders mheaders baseRequest

let io = HTTP.httpLbs requestWithHeaders manager

Expand All @@ -278,3 +305,11 @@ fetchFromHttpUrl childURL mheaders = do
case Data.Text.Lazy.Encoding.decodeUtf8' bytes of
Left err -> liftIO (Control.Exception.throwIO err)
Right text -> return (Data.Text.Lazy.toStrict text)

originHeadersFileExpr :: IO (Expr Src Import)
originHeadersFileExpr = do
directoryStr <- getXdgDirectory XdgConfig "dhall"
let components = map Text.pack (splitDirectories directoryStr)
let directory = Directory (reverse components)
let file = (File directory "headers.dhall")
return (Embed (Import (ImportHashed Nothing (Local Absolute file)) Code))
9 changes: 7 additions & 2 deletions dhall/ghcjs-src/Dhall/Import/HTTP.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@

module Dhall.Import.HTTP
( fetchFromHttpUrl
, originHeadersFileExpr
) where

import Control.Monad.IO.Class (MonadIO (..))
import Control.Monad.Trans.State.Strict (StateT)
import Data.ByteString (ByteString)
import Data.CaseInsensitive (CI)
import Dhall.Core (URL (..))
import Dhall.Import.Types (Status)
import Dhall.Core (URL (..), Expr (..))
import Dhall.Import.Types (Import, Status)
import Dhall.Parser (Src)
import Dhall.URL (renderURL)

import qualified Data.Text as Text
Expand All @@ -35,3 +37,6 @@ fetchFromHttpUrl childURL Nothing = do
return body
fetchFromHttpUrl _ _ =
fail "Dhall does not yet support custom headers when built using GHCJS"

originHeadersFileExpr :: IO (Expr Src Import)
originHeadersFileExpr = return Missing
Loading