Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add default proxy credentials when connecting to GitHub #2507

Merged
merged 2 commits into from
May 4, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 26 additions & 25 deletions src/app/Fake.Api.GitHub/GitHub.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@
open Octokit
open Octokit.Internal
open System
open System.Threading
open System.Net
open System.Net.Http
open System.Reflection
open System.IO

/// Contains tasks to interact with [GitHub](https://github.com/) releases
Expand Down Expand Up @@ -52,24 +51,22 @@ module GitHub =
/// If left unspecified, and the tag does not already exist, the default branch is used instead.
TargetCommitish : string }

// wrapper re-implementation of HttpClientAdapter which works around
// known Octokit bug in which user-supplied timeouts are not passed to HttpClient object
// https://github.com/octokit/octokit.net/issues/963
type private HttpClientWithTimeout(timeout : TimeSpan) as this =
inherit HttpClientAdapter(fun () -> HttpMessageHandlerFactory.CreateDefault())
let setter = lazy(
match typeof<HttpClientAdapter>.GetTypeInfo().GetField("_http", BindingFlags.NonPublic ||| BindingFlags.Instance) with
| null -> ()
| f ->
match f.GetValue(this) with
| :? HttpClient as http -> http.Timeout <- timeout
| _ -> ())

interface IHttpClient with
member __.Send(request : IRequest, ct : CancellationToken) =
setter.Force()
match request with :? Request as r -> r.Timeout <- timeout | _ -> ()
base.Send(request, ct)
let private timeout = TimeSpan.FromMinutes 20.

let private createHttpClient =
let handlerFactory () =
let handler = HttpMessageHandlerFactory.CreateDefault()
#if NETSTANDARD2_0
// Ensure the default credentials are used with any system-configured proxy
// https://github.com/dotnet/runtime/issues/25745#issuecomment-378322214
match handler with
| :? HttpClientHandler as h ->
h.DefaultProxyCredentials <- CredentialCache.DefaultCredentials
| _ -> ()
#endif
handler

fun () -> new HttpClientAdapter(Func<_> handlerFactory)

/// A version of 'reraise' that can work inside computation expressions
let private captureAndReraise ex =
Expand Down Expand Up @@ -105,42 +102,46 @@ module GitHub =
/// Creates a GitHub API v3 client using the specified credentials
let createClient (user:string) (password:string) =
async {
let httpClient = new HttpClientWithTimeout(TimeSpan.FromMinutes 20.)
let httpClient = createHttpClient()
let connection = Connection(ProductHeaderValue("FAKE"), httpClient)
let github = GitHubClient(connection)
github.Credentials <- Credentials(user, password)
github.SetRequestTimeout timeout
return github
}

/// Creates a GitHub API v3 client using the specified token
let createClientWithToken (token:string) =
async {
let httpClient = new HttpClientWithTimeout(TimeSpan.FromMinutes 20.)
let httpClient = createHttpClient()
let connection = Connection(ProductHeaderValue("FAKE"), httpClient)
let github = GitHubClient(connection)
github.Credentials <- Credentials(token)
github.SetRequestTimeout timeout
return github
}

/// Creates a GitHub API v3 client to GitHub Enterprise server at the specified url using the specified credentials
let createGHEClient url (user:string) (password:string) =
async {
let credentials = Credentials(user, password)
let httpClient = new HttpClientWithTimeout(TimeSpan.FromMinutes 20.)
let httpClient = createHttpClient()
let connection = Connection(ProductHeaderValue("FAKE"), Uri(url), InMemoryCredentialStore(credentials), httpClient, SimpleJsonSerializer())
let github = GitHubClient(connection)
github.Credentials <- credentials
github.SetRequestTimeout timeout
return github
}

/// Creates a GitHub API v3 client to GitHub Enterprise server at the specified url using the specified token
let createGHEClientWithToken url (token:string) =
async {
let credentials = Credentials(token)
let httpClient = new HttpClientWithTimeout(TimeSpan.FromMinutes 20.)
let httpClient = createHttpClient()
let connection = Connection(ProductHeaderValue("FAKE"), Uri(url), InMemoryCredentialStore(credentials), httpClient, SimpleJsonSerializer())
let github = GitHubClient(connection)
github.Credentials <- credentials
github.SetRequestTimeout timeout
return github
}

Expand Down Expand Up @@ -209,7 +210,7 @@ module GitHub =
| None -> ()

let archiveContents = File.OpenRead(fi.FullName)
let assetUpload = ReleaseAssetUpload(fi.Name,"application/octet-stream",archiveContents,Nullable<TimeSpan>())
let assetUpload = ReleaseAssetUpload(fi.Name,"application/octet-stream",archiveContents,Nullable timeout)

let! asset = Async.AwaitTask <| release'.Client.Repository.Release.UploadAsset(release'.Release, assetUpload)
printfn "Uploaded %s" asset.Name
Expand Down