Skip to content

Commit

Permalink
Merge pull request #1741 from ruhullahshah/add_support_for_proxy_feature
Browse files Browse the repository at this point in the history
Add support for custom proxy credentials using the same policy as adopted by Paket
  • Loading branch information
matthid authored Jan 2, 2018
2 parents 47ffd2d + 3653b97 commit e50a358
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 4 deletions.
5 changes: 2 additions & 3 deletions src/app/FakeLib/DotNetCLIHelper.fs
Original file line number Diff line number Diff line change
Expand Up @@ -495,9 +495,8 @@ let InstallDotNetSDK sdkVersion =
let downloadSDK downloadPath archiveFileName =
let localPath = Path.Combine(DotnetSDKPath, archiveFileName) |> FullName
tracefn "Installing '%s' to '%s'" downloadPath localPath

let proxy = Net.WebRequest.DefaultWebProxy
proxy.Credentials <- Net.CredentialCache.DefaultCredentials

let proxy = Utils.getDefaultProxyForUrl downloadPath
use webclient = new Net.WebClient(Proxy = proxy)
webclient.DownloadFile(downloadPath, localPath)
localPath
Expand Down
3 changes: 2 additions & 1 deletion src/app/FakeLib/FakeLib.fsproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\packages\FSharp.Compiler.Tools\build\FSharp.Compiler.Tools.props" Condition="Exists('..\..\..\packages\FSharp.Compiler.Tools\build\FSharp.Compiler.Tools.props')" Label="Paket" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
Expand Down Expand Up @@ -41,6 +41,7 @@
</PropertyGroup>
<ItemGroup>
<None Include="paket.references" />
<Compile Include="Utils.fs" />
<Compile Include="..\..\..\paket-files\matthid\Yaaf.FSharp.Scripting\src\source\Yaaf.FSharp.Scripting\YaafFSharpScripting.fs">
<Paket>True</Paket>
<Link>paket-files/YaafFSharpScripting.fs</Link>
Expand Down
95 changes: 95 additions & 0 deletions src/app/FakeLib/Utils.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
module Fake.Utils

open System
open System.Net

//Using the same code as https://github.com/fsprojects/Paket for Memoization & Proxy handling
let inline internal memoizeByExt (getKey : 'a -> 'key) (f: 'a -> 'b) : ('a -> 'b) * ('key * 'b -> unit) =
let cache = System.Collections.Concurrent.ConcurrentDictionary<'key, 'b>()
(fun (x: 'a) ->
cache.GetOrAdd(getKey x, fun _ -> f x)),
(fun (key, c) ->
cache.TryAdd(key, c) |> ignore)

let inline internal memoizeBy (getKey : 'a -> 'key) (f: 'a -> 'b) : ('a -> 'b) =
memoizeByExt getKey f |> fst

let inline internal memoize (f: 'a -> 'b) : 'a -> 'b = memoizeBy id f

let envProxies () =
let getEnvValue (name:string) =
let v = Environment.GetEnvironmentVariable(name.ToUpperInvariant())
// under mono, env vars are case sensitive
if isNull v then Environment.GetEnvironmentVariable(name.ToLowerInvariant()) else v
let bypassList =
let noproxyString = getEnvValue "NO_PROXY"
let noproxy = if not (String.IsNullOrEmpty (noproxyString)) then System.Text.RegularExpressions.Regex.Escape(noproxyString).Replace(@"*", ".*") else noproxyString

if String.IsNullOrEmpty noproxy then [||] else
noproxy.Split([| ',' |], StringSplitOptions.RemoveEmptyEntries)
let getCredentials (uri:Uri) =
let userPass = uri.UserInfo.Split([| ':' |], 2)
if userPass.Length <> 2 || userPass.[0].Length = 0 then None else
let credentials = NetworkCredential(Uri.UnescapeDataString userPass.[0], Uri.UnescapeDataString userPass.[1])
Some credentials

let getProxy (scheme:string) =
let envVarName = sprintf "%s_PROXY" (scheme.ToUpperInvariant())
let envVarValue = getEnvValue envVarName
if isNull envVarValue then None else
match Uri.TryCreate(envVarValue, UriKind.Absolute) with
| true, envUri ->
#if NETSTANDARD1_6
Some
{ new IWebProxy with
member __.Credentials
with get () = (Option.toObj (getCredentials envUri)) :> ICredentials
and set value = ()
member __.GetProxy _ =
Uri (sprintf "http://%s:%d" envUri.Host envUri.Port)
member __.IsBypassed (host : Uri) =
Array.contains (string host) bypassList
}
#else
let proxy = WebProxy (Uri (sprintf "http://%s:%d" envUri.Host envUri.Port))
proxy.Credentials <- Option.toObj (getCredentials envUri)
proxy.BypassProxyOnLocal <- true
proxy.BypassList <- bypassList
Some proxy
#endif
| _ -> None

let addProxy (map:Map<string, WebProxy>) scheme =
match getProxy scheme with
| Some p -> Map.add scheme p map
| _ -> map

[ "http"; "https" ]
|> List.fold addProxy Map.empty

let calcEnvProxies = lazy (envProxies())

let getDefaultProxyForUrl =
memoize
(fun (url:string) ->
let uri = Uri url
let getDefault () =
#if NETSTANDARD1_6
let result = WebRequest.DefaultWebProxy
#else
let result = WebRequest.GetSystemWebProxy()
#endif
#if NETSTANDARD1_6
let proxy = result
#else
let address = result.GetProxy uri
if address = uri then null else
let proxy = WebProxy address
proxy.BypassProxyOnLocal <- true
#endif
proxy.Credentials <- CredentialCache.DefaultCredentials
proxy

match calcEnvProxies.Force().TryFind uri.Scheme with
| Some p -> if p.GetProxy uri <> uri then p else getDefault()
| None -> getDefault())

0 comments on commit e50a358

Please sign in to comment.