Skip to content
This repository

Partial Fix for #543 #1015

Merged
merged 2 commits into from over 1 year ago

2 participants

Arun Tejasvi Chaganty Duncan Coutts
Arun Tejasvi Chaganty

I was looking to fix a usability issue; cabal would fail when given an empty http_proxy env variable. I replaced the proxy string extraction code with fetchProxy from HTTP (>=4000.0.8) and perform a check to see if the http_proxy string is empty - and if so, treat it as NoProxy. This should of course be the default behaviour of fetchProxy.

Duncan Coutts dcoutts merged commit 4e43553 into from
Duncan Coutts
Owner

Looks great, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
123 cabal-install/Distribution/Client/HttpUtils.hs
@@ -13,31 +13,18 @@ module Distribution.Client.HttpUtils (
13 13 import Network.HTTP
14 14 ( Request (..), Response (..), RequestMethod (..)
15 15 , Header(..), HeaderName(..) )
  16 +import Network.HTTP.Proxy ( Proxy(..), fetchProxy)
16 17 import Network.URI
17 18 ( URI (..), URIAuth (..), parseAbsoluteURI )
18   -import Network.Stream
19   - ( Result, ConnError(..) )
20 19 import Network.Browser
21   - ( Proxy (..), Authority (..), BrowserAction, browse
  20 + ( Authority (..), BrowserAction, browse
22 21 , setOutHandler, setErrHandler, setProxy, setAuthorityGen, request)
  22 +import Network.Stream
  23 + ( Result, ConnError(..) )
23 24 import Control.Monad
24 25 ( mplus, join, liftM, liftM2 )
25 26 import qualified Data.ByteString.Lazy.Char8 as ByteString
26 27 import Data.ByteString.Lazy (ByteString)
27   -#ifdef WIN32
28   -import System.Win32.Types
29   - ( DWORD, HKEY )
30   -import System.Win32.Registry
31   - ( hKEY_CURRENT_USER, regOpenKey, regCloseKey
32   - , regQueryValue, regQueryValueEx )
33   -import Control.Exception
34   - ( bracket )
35   -import Distribution.Compat.Exception
36   - ( handleIO )
37   -import Foreign
38   - ( toBool, Storable(peek, sizeOf), castPtr, alloca )
39   -#endif
40   -import System.Environment (getEnvironment)
41 28
42 29 import qualified Paths_cabal_install (version)
43 30 import Distribution.Verbosity (Verbosity)
@@ -46,102 +33,26 @@ import Distribution.Simple.Utils
46 33 , copyFileVerbose, writeFileAtomic )
47 34 import Distribution.Text
48 35 ( display )
  36 +import Data.Char ( isSpace )
49 37 import qualified System.FilePath.Posix as FilePath.Posix
50 38 ( splitDirectories )
51 39
52   --- FIXME: all this proxy stuff is far too complicated, especially parsing
53   --- the proxy strings. Network.Browser should have a way to pick up the
54   --- proxy settings hiding all this system-dependent stuff below.
55   -
56   --- try to read the system proxy settings on windows or unix
57   -proxyString, envProxyString, registryProxyString :: IO (Maybe String)
58   -#ifdef WIN32
59   --- read proxy settings from the windows registry
60   -registryProxyString = handleIO (\_ -> return Nothing) $
61   - bracket (regOpenKey hive path) regCloseKey $ \hkey -> do
62   - enable <- fmap toBool $ regQueryValueDWORD hkey "ProxyEnable"
63   - if enable
64   - then fmap Just $ regQueryValue hkey (Just "ProxyServer")
65   - else return Nothing
66   - where
67   - -- some sources say proxy settings should be at
68   - -- HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows
69   - -- \CurrentVersion\Internet Settings\ProxyServer
70   - -- but if the user sets them with IE connection panel they seem to
71   - -- end up in the following place:
72   - hive = hKEY_CURRENT_USER
73   - path = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
74   -
75   - regQueryValueDWORD :: HKEY -> String -> IO DWORD
76   - regQueryValueDWORD hkey name = alloca $ \ptr -> do
77   - regQueryValueEx hkey name (castPtr ptr) (sizeOf (undefined :: DWORD))
78   - peek ptr
79   -#else
80   -registryProxyString = return Nothing
81   -#endif
82   -
83   --- read proxy settings by looking for an env var
84   -envProxyString = do
85   - env <- getEnvironment
86   - return (lookup "http_proxy" env `mplus` lookup "HTTP_PROXY" env)
87   -
88   -proxyString = liftM2 mplus envProxyString registryProxyString
89   -
  40 +-- Trime
  41 +trim :: String -> String
  42 +trim = f . f
  43 + where f = reverse . dropWhile isSpace
90 44
91 45 -- |Get the local proxy settings
  46 +--TODO: print info message when we're using a proxy based on verbosity
92 47 proxy :: Verbosity -> IO Proxy
93 48 proxy verbosity = do
94   - mstr <- proxyString
95   - case mstr of
96   - Nothing -> return NoProxy
97   - Just str -> case parseHttpProxy str of
98   - Nothing -> do
99   - warn verbosity $ "invalid http proxy uri: " ++ show str
100   - warn verbosity $ "proxy uri must be http with a hostname"
101   - warn verbosity $ "ignoring http proxy, trying a direct connection"
102   - return NoProxy
103   - Just p -> return p
104   ---TODO: print info message when we're using a proxy
105   -
106   --- | We need to be able to parse non-URIs like @\"wwwcache.example.com:80\"@
107   --- which lack the @\"http://\"@ URI scheme. The problem is that
108   --- @\"wwwcache.example.com:80\"@ is in fact a valid URI but with scheme
109   --- @\"wwwcache.example.com:\"@, no authority part and a path of @\"80\"@.
110   ---
111   --- So our strategy is to try parsing as normal uri first and if it lacks the
112   --- 'uriAuthority' then we try parsing again with a @\"http://\"@ prefix.
113   ---
114   -parseHttpProxy :: String -> Maybe Proxy
115   -parseHttpProxy str = join
116   - . fmap uri2proxy
117   - $ parseHttpURI str
118   - `mplus` parseHttpURI ("http://" ++ str)
119   - where
120   - parseHttpURI str' = case parseAbsoluteURI str' of
121   - Just uri@URI { uriAuthority = Just _ }
122   - -> Just (fixUserInfo uri)
123   - _ -> Nothing
124   -
125   -fixUserInfo :: URI -> URI
126   -fixUserInfo uri = uri{ uriAuthority = f `fmap` uriAuthority uri }
127   - where
128   - f a@URIAuth{ uriUserInfo = s } =
129   - a{ uriUserInfo = case reverse s of
130   - '@':s' -> reverse s'
131   - _ -> s
132   - }
133   -uri2proxy :: URI -> Maybe Proxy
134   -uri2proxy uri@URI{ uriScheme = "http:"
135   - , uriAuthority = Just (URIAuth auth' host port)
136   - } = Just (Proxy (host ++ port) auth)
137   - where auth = if null auth'
138   - then Nothing
139   - else Just (AuthBasic "" usr pwd uri)
140   - (usr,pwd') = break (==':') auth'
141   - pwd = case pwd' of
142   - ':':cs -> cs
143   - _ -> pwd'
144   -uri2proxy _ = Nothing
  49 + p <- fetchProxy True
  50 + -- Handle empty proxy strings
  51 + return $ case p of
  52 + Proxy uri auth ->
  53 + let uri' = trim uri in
  54 + if uri' == "" then NoProxy else Proxy uri' auth
  55 + _ -> p
145 56
146 57 mkRequest :: URI -> Request ByteString
147 58 mkRequest uri = Request{ rqURI = uri
2  cabal-install/cabal-install.cabal
@@ -112,7 +112,7 @@ Executable cabal
112 112 Cabal >= 1.17.0 && < 1.18,
113 113 filepath >= 1.0 && < 1.4,
114 114 network >= 1 && < 3,
115   - HTTP >= 4000.0.2 && < 4001,
  115 + HTTP >= 4000.0.8 && < 4001,
116 116 zlib >= 0.4 && < 0.6,
117 117 time >= 1.1 && < 1.5,
118 118 mtl >= 2.0 && < 3

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.