Skip to content

Commit dd01d0a

Browse files
authored
Merge pull request #3682 from igrep/user-agent
Specify User-Agent on every HTTP request (#3628)
2 parents 57c974b + 9642b8e commit dd01d0a

File tree

12 files changed

+85
-15
lines changed

12 files changed

+85
-15
lines changed

ChangeLog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ Other enhancements:
1313
* A new sub command `ls` has been introduced to stack to view
1414
local and remote snapshots present in the system. Use `stack ls
1515
snapshots --help` to get more details about it.
16+
* Specify User-Agent HTTP request header on every HTTP request.
17+
See [#3628](https://github.com/commercialhaskell/stack/issues/3628) for details.
1618

1719
* In addition to supporting `.tar.gz` and `.zip` files as remote archives,
1820
plain `.tar` files are now accepted too. This will additionally help with

package.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ library:
143143
- Data.Store.VersionTagged
144144
- Network.HTTP.Download
145145
- Network.HTTP.Download.Verified
146+
- Network.HTTP.StackClient
146147
- Options.Applicative.Args
147148
- Options.Applicative.Builder.Extra
148149
- Options.Applicative.Complicated

src/Hackage/Security/Client/Repository/HttpLib/HttpClient.hs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import qualified Data.ByteString as BS
2222
import qualified Data.ByteString.Char8 as BS.C8
2323
import qualified Network.HTTP.Client as HttpClient
2424
import qualified Network.HTTP.Client.Internal as HttpClient
25+
import qualified Network.HTTP.StackClient as StackClient
2526
import qualified Network.HTTP.Types as HttpClient
2627

2728
import Hackage.Security.Client hiding (Header)
@@ -69,7 +70,7 @@ get manager reqHeaders uri callback = wrapCustomEx $ do
6970
-- the URI contains URL auth. Not sure if this is a concern.
7071
request' <- HttpClient.setUri HttpClient.defaultRequest uri
7172
let request = setRequestHeaders reqHeaders request'
72-
checkHttpException $ HttpClient.withResponse request manager $ \response -> do
73+
checkHttpException $ StackClient.withResponseByManager request manager $ \response -> do
7374
let br = wrapCustomEx $ HttpClient.responseBody response
7475
callback (getResponseHeaders response) br
7576

@@ -82,7 +83,7 @@ getRange manager reqHeaders uri (from, to) callback = wrapCustomEx $ do
8283
request' <- HttpClient.setUri HttpClient.defaultRequest uri
8384
let request = setRange from to
8485
$ setRequestHeaders reqHeaders request'
85-
checkHttpException $ HttpClient.withResponse request manager $ \response -> do
86+
checkHttpException $ StackClient.withResponseByManager request manager $ \response -> do
8687
let br = wrapCustomEx $ HttpClient.responseBody response
8788
case () of
8889
() | HttpClient.responseStatus response == HttpClient.partialContent206 ->

src/Network/HTTP/Download.hs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,12 @@ module Network.HTTP.Download
1515
, download
1616
, redownload
1717
, httpJSON
18+
, httpLbs
19+
, httpLBS
1820
, parseRequest
1921
, parseUrlThrow
2022
, setGithubHeaders
23+
, withResponse
2124
) where
2225

2326
import Stack.Prelude
@@ -30,7 +33,8 @@ import Data.Text.Encoding (decodeUtf8With)
3033
import Network.HTTP.Client (Request, Response, path, checkResponse, parseUrlThrow, parseRequest)
3134
import Network.HTTP.Client.Conduit (requestHeaders)
3235
import Network.HTTP.Download.Verified
33-
import Network.HTTP.Simple (httpJSON, withResponse, getResponseBody, getResponseHeaders, getResponseStatusCode,
36+
import Network.HTTP.StackClient (httpJSON, httpLbs, httpLBS, withResponse)
37+
import Network.HTTP.Simple (getResponseBody, getResponseHeaders, getResponseStatusCode,
3438
setRequestHeader)
3539
import Path.IO (doesFileExist)
3640
import System.Directory (createDirectoryIfMissing,
@@ -112,5 +116,4 @@ instance Exception DownloadException
112116

113117
-- | Set the user-agent request header
114118
setGithubHeaders :: Request -> Request
115-
setGithubHeaders = setRequestHeader "User-Agent" ["The Haskell Stack"]
116-
. setRequestHeader "Accept" ["application/vnd.github.v3+json"]
119+
setGithubHeaders = setRequestHeader "Accept" ["application/vnd.github.v3+json"]

src/Network/HTTP/Download/Verified.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ import Data.Text.Encoding (decodeUtf8With)
4242
import Data.Text.Encoding.Error (lenientDecode)
4343
import GHC.IO.Exception (IOException(..),IOErrorType(..))
4444
import Network.HTTP.Client (getUri, path)
45-
import Network.HTTP.Simple (Request, HttpException, httpSink, getResponseHeaders)
45+
import Network.HTTP.StackClient (httpSink)
46+
import Network.HTTP.Simple (Request, HttpException, getResponseHeaders)
4647
import Network.HTTP.Types.Header (hContentLength, hContentMD5)
4748
import Path
4849
import Stack.Types.Runner

src/Network/HTTP/StackClient.hs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
{-# LANGUAGE OverloadedStrings #-}
2+
3+
-- |
4+
-- Wrapper functions of 'Network.HTTP.Simple' and 'Network.HTTP.Client' to
5+
-- add the 'User-Agent' HTTP request header to each request.
6+
7+
module Network.HTTP.StackClient
8+
( httpJSON
9+
, httpLbs
10+
, httpLBS
11+
, httpNoBody
12+
, httpSink
13+
, setUserAgent
14+
, withResponse
15+
, withResponseByManager
16+
) where
17+
18+
import Control.Monad.Catch (MonadMask)
19+
import Data.Aeson (FromJSON)
20+
import qualified Data.ByteString as Strict
21+
import Data.ByteString.Lazy (ByteString)
22+
import Data.Conduit (ConduitM, Sink)
23+
import qualified Network.HTTP.Client
24+
import Network.HTTP.Client (BodyReader, Manager, Request, Response)
25+
import Network.HTTP.Simple (setRequestHeader)
26+
import qualified Network.HTTP.Simple
27+
import UnliftIO (MonadIO)
28+
29+
30+
setUserAgent :: Request -> Request
31+
setUserAgent = setRequestHeader "User-Agent" ["The Haskell Stack"]
32+
33+
34+
httpJSON :: (MonadIO m, FromJSON a) => Request -> m (Response a)
35+
httpJSON = Network.HTTP.Simple.httpJSON . setUserAgent
36+
37+
38+
httpLbs :: MonadIO m => Request -> m (Response ByteString)
39+
httpLbs = Network.HTTP.Simple.httpLbs . setUserAgent
40+
41+
42+
httpLBS :: MonadIO m => Request -> m (Response ByteString)
43+
httpLBS = httpLbs
44+
45+
46+
httpNoBody :: MonadIO m => Request -> m (Response ())
47+
httpNoBody = Network.HTTP.Simple.httpNoBody . setUserAgent
48+
49+
50+
httpSink :: (MonadIO m, MonadMask m) => Request -> (Response () -> Sink Strict.ByteString m a) -> m a
51+
httpSink = Network.HTTP.Simple.httpSink . setUserAgent
52+
53+
54+
withResponse
55+
:: (MonadIO m, MonadMask m, MonadIO n)
56+
=> Request -> (Response (ConduitM i Strict.ByteString n ()) -> m a) -> m a
57+
withResponse = Network.HTTP.Simple.withResponse . setUserAgent
58+
59+
60+
withResponseByManager :: Request -> Manager -> (Response BodyReader -> IO a) -> IO a
61+
withResponseByManager = Network.HTTP.Client.withResponse . setUserAgent

src/Stack/Config.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ import Distribution.Version (simplifyVersionRange, mkVersion')
6363
import GHC.Conc (getNumProcessors)
6464
import Lens.Micro (lens)
6565
import Network.HTTP.Client (parseUrlThrow)
66-
import Network.HTTP.Simple (httpJSON, getResponseBody)
66+
import Network.HTTP.StackClient (httpJSON)
67+
import Network.HTTP.Simple (getResponseBody)
6768
import Options.Applicative (Parser, strOption, long, help)
6869
import Path
6970
import Path.Extra (toFilePathNoTrailingSep)

src/Stack/Ls.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ import qualified Data.Text as T
2121
import qualified Data.Text.IO as T
2222
import Data.Typeable (Typeable)
2323
import qualified Data.Vector as V
24+
import Network.HTTP.StackClient (httpJSON)
2425
import Network.HTTP.Simple
25-
(addRequestHeader, getResponseBody, httpJSON, parseRequest,
26+
(addRequestHeader, getResponseBody, parseRequest,
2627
setRequestManager)
2728
import Network.HTTP.Types.Header (hAccept)
2829
import qualified Options.Applicative as OA

src/Stack/New.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import Data.Time.Calendar
3939
import Data.Time.Clock
4040
import qualified Data.Yaml as Yaml
4141
import Network.HTTP.Download
42-
import Network.HTTP.Simple
42+
import Network.HTTP.Simple (Request, HttpException, getResponseStatusCode, getResponseBody)
4343
import Path
4444
import Path.IO
4545
import Stack.Constants

src/Stack/Setup.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ import qualified Distribution.System as Cabal
6363
import Distribution.Text (simpleParse)
6464
import Distribution.Version (mkVersion')
6565
import Lens.Micro (set)
66-
import Network.HTTP.Simple (getResponseBody, httpLBS, withResponse, getResponseStatusCode)
66+
import Network.HTTP.Simple (getResponseBody, getResponseStatusCode)
6767
import Network.HTTP.Download
6868
import Path
6969
import Path.CheckInstall (warnInstallSearchPathIssues)

0 commit comments

Comments
 (0)