Support setting endpoints from environment variables#1013
Conversation
|
Nice to see I'm not the only person who could use this. :) I think this is a good idea, but I don't think user code should have to be modified to support it. It should be default behavior as it is with other SDKs. One way to do that would be to make The only question I would have is whether there should be a grace period where a user should opt in by setting some var like The reason for a grace period is that suddenly supporting the vars is a change in behavior and could break some installations. Something like:
On the other hand, maybe a grace period isn't necessary. |
|
Here's my patch that enables the endpoints by default: diff --git a/lib/amazonka/src/Amazonka/Env.hs b/lib/amazonka/src/Amazonka/Env.hs
index 516d8fb0727..bf0f4b72044 100644
--- a/lib/amazonka/src/Amazonka/Env.hs
+++ b/lib/amazonka/src/Amazonka/Env.hs
@@ -43,12 +43,15 @@ module Amazonka.Env
where
import Amazonka.Core.Lens.Internal (Lens)
+import Amazonka.Data.Text (toText)
import Amazonka.Env.Hooks (Hooks, addLoggingHooks, noHooks)
import Amazonka.Logger (Logger)
import Amazonka.Prelude
import Amazonka.Types hiding (timeout)
+import qualified Amazonka.Endpoint as Endpoint
import qualified Amazonka.Types as Service (Service (..))
import qualified Data.Function as Function
+import qualified Data.List as List
import qualified Data.Text as Text
import qualified Network.HTTP.Client as Client
import qualified Network.HTTP.Conduit as Client.Conduit
@@ -160,17 +163,47 @@ newEnvNoAuth =
newEnvNoAuthFromManager :: MonadIO m => Client.Manager -> m EnvNoAuth
newEnvNoAuthFromManager manager = do
mRegion <- lookupRegion
+ endpointOverrides <- customEndpoints
pure
Env
{ region = fromMaybe NorthVirginia mRegion,
logger = \_ _ -> pure (),
hooks = addLoggingHooks noHooks,
retryCheck = retryConnectionFailure 3,
- overrides = id,
+ overrides = endpointOverrides,
manager,
auth = Proxy
}
+-- | Retrieve custom endpoints from environment variables:
+--
+-- * @AWS_ENDPOINT_URL@
+-- * @AWS_ENDPOINT_URL_<SERVICE>@
+--
+-- The latter takes precedence over the former.
+customEndpoints :: (MonadIO m) => m (Service -> Service)
+customEndpoints = do
+ environment <- liftIO Environment.getEnvironment
+ let globalUrl = lookup "AWS_ENDPOINT_URL" environment >>= Client.parseUrlThrow
+ let serviceUrls = mapMaybe (\(k, v) -> (,v) <$> removePrefix "AWS_ENDPOINT_URL_" k) environment
+ let override s =
+ case lookup (Text.unpack . Text.toLower . toText $ Service.abbrev s) serviceUrls of
+ Just x -> setEndpointMaybe (Client.parseUrlThrow x) s
+ Nothing -> setEndpointMaybe globalUrl s
+ pure override
+ where
+ removePrefix :: String -> String -> Maybe String
+ removePrefix prefix s =
+ if prefix `List.isPrefixOf` s
+ then Just $ drop (length prefix) s
+ else Nothing
+
+ setEndpointMaybe :: Maybe Client.Request -> Service -> Service
+ setEndpointMaybe mreq s =
+ case mreq of
+ Just req -> Endpoint.setEndpoint (Client.secure req) (Client.host req) (Client.port req) s
+ Nothing -> s
+
-- | Get "the" 'Auth' from an 'Env'', if we can.
authMaybe :: Foldable withAuth => Env' withAuth -> Maybe Auth
authMaybe = foldr (const . Just) Nothing . auth |
Partially solves #980.
The added
customEndpointsloads environment variablesAWS_ENDPOINT_URLandAWS_ENDPOINT_URL_<SERVICE>if any to provide a function to override default endpoints.Intended to be used as follows: