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
matthid authored Jan 2, 2018

Unverified

This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
2 parents 47ffd2d + 3653b97 commit e50a358
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
@@ -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
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')" />
@@ -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>
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.