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 Fake.Net.Http documentation & API update #1759

Merged
merged 3 commits into from
Jan 27, 2018
Merged
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions FAKE.sln
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "markdown", "markdown", "{B9
help\markdown\legacy-core-targets.md = help\markdown\legacy-core-targets.md
help\markdown\legacy-gettingstarted.md = help\markdown\legacy-gettingstarted.md
help\markdown\legacy-index.md = help\markdown\legacy-index.md
help\markdown\net-http.md = help\markdown\net-http.md
help\markdown\testing-sonarqube.md = help\markdown\testing-sonarqube.md
help\markdown\todo-androidpublisher.md = help\markdown\todo-androidpublisher.md
help\markdown\todo-azurecloudservices.md = help\markdown\todo-azurecloudservices.md
Expand Down
67 changes: 67 additions & 0 deletions help/markdown/net-http.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Downloading Files Over HTTP

The `Fake.Net.Http` module provides a functionality to download files over HTTP.

[API-Reference](apidocs/fake-net-http.html)

## Including the Fake.Net.Http dependency

In order to open the `Fake.Net.Http` module from a build script you have to add a `Fake.Net.Http` dependency into your
`paket.dependencies` file:

group NetcoreBuild
source https://api.nuget.org/v3/index.json

nuget Fake.Net.Http prerelease

.... other dependencies, like
nuget Fake.Core.Target prerelease

Please see more details on referencing FAKE 5 modules [here](fake-fake5-modules.html).

## Downloading a Single File

To download a single file over HTTP use `downloadFile` from the Http module:

open Fake.Net
open Fake.Core

Target.Create "DownloadFile" (fun _ ->
let absoluteFilePath = Http.downloadFile "/tmp/5.zip" @"http://ipv4.download.thinkbroadband.com/5MB.zip"
printfn "File path: %s" absoluteFilePath
)

A console output should be:

Downloading [http://ipv4.download.thinkbroadband.com/5MB.zip] ...
Download succeeded
File path: /tmp/5.zip

## Downloading Multiple Files

To download multiple files in parallel use `downloadFiles` from the Http module:

open Fake.Net
open Fake.Core

Target.Create "DownloadFiles" (fun _ ->
let files: Http.DownloadParameters list = [
{Path = "/tmp/5.zip"; Uri = "http://ipv4.download.thinkbroadband.com/5MB.zip"};
{Path = "/tmp/10.zip"; Uri = "http://ipv4.download.thinkbroadband.com/10MB.zip"}]
let filePaths = Http.downloadFiles files
printfn "File paths: %A" filePaths
)

A console output should be:

Downloading [http://ipv4.download.thinkbroadband.com/5MB.zip] ...
Downloading [http://ipv4.download.thinkbroadband.com/10MB.zip] ...
Download succeeded
File paths: ["/tmp/5.zip"; "/tmp/10.zip"]

## More Details

* `downloadFile` and `downloadFiles` throw an Exception and fail a FAKE Target if any error occurs (invalid URI, invalid local file
path/permissions, etc.)

* file with the same name will be overwritten if exists in the target location
8 changes: 7 additions & 1 deletion help/templates/template.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,12 @@
<li><a href="@(prefix)apidocs/fake-dotnet-paket.html">Paket</a></li>
</ul>
</li>
<li>
<a href="@(prefix)apidocs/index.html#Fake.Net">Net</a>
<ul>
<li><a href="@(prefix)net-http.html">Http</a></li>
</ul>
</li>
<li>
<a href="@(prefix)apidocs/index.html#Fake.Tools.Git">Tools</a>
<ul>
Expand Down Expand Up @@ -297,4 +303,4 @@
<script src="@(prefix)assets/js/main.js"></script>

</body>
</html>
</html>
4 changes: 2 additions & 2 deletions src/app/Fake.Net.Http/AssemblyInfo.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ open System.Reflection
[<assembly: AssemblyTitleAttribute("FAKE - F# Make HTTP Client")>]
[<assembly: AssemblyProductAttribute("FAKE - F# Make")>]
[<assembly: AssemblyVersionAttribute("5.0.0")>]
[<assembly: AssemblyInformationalVersionAttribute("5.0.0-beta010")>]
[<assembly: AssemblyInformationalVersionAttribute("5.0.0")>]
[<assembly: AssemblyFileVersionAttribute("5.0.0")>]
do ()

module internal AssemblyVersionInformation =
let [<Literal>] AssemblyTitle = "FAKE - F# Make HTTP Client"
let [<Literal>] AssemblyProduct = "FAKE - F# Make"
let [<Literal>] AssemblyVersion = "5.0.0"
let [<Literal>] AssemblyInformationalVersion = "5.0.0-beta010"
let [<Literal>] AssemblyInformationalVersion = "5.0.0"
let [<Literal>] AssemblyFileVersion = "5.0.0"
8 changes: 7 additions & 1 deletion src/app/Fake.Net.Http/Async.fs
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
namespace Fake.Net.Async

/// [omit]
module Async =
/// [omit]
let result = async.Return

/// [omit]
let map f value = async {
let! v = value
return f v
}

/// [omit]
let bind f xAsync = async {
let! x = xAsync
return! f x
}

/// [omit]
let apply fAsync xAsync = async {
// start the two asyncs in parallel
let! fChild = Async.StartChild fAsync
Expand All @@ -23,4 +29,4 @@ module Async =

// apply the function to the results
return f x
}
}
31 changes: 18 additions & 13 deletions src/app/Fake.Net.Http/HttpLoader.fs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ module Http =

/// Input parameter type
type DownloadParameters = {
/// The URI from which to download data
Uri: string
/// The name of the local file that is to receive the data
Path: string
}

Expand Down Expand Up @@ -60,14 +62,15 @@ module Http =
let urlResult = createUri input.Uri
createDownloadInfoRecord <!> filePathResult <*> urlResult

/// Unwraps the Result type and throws an exception if download process failed
/// [omit]
let private printDownloadResults result =
let private processResults result =
match result with
| Ok result ->
Trace.log <| sprintf "Downloaded : [%A]" result
Trace.log "Download succeeded"
result
| Error errs ->
Trace.traceError <| sprintf "Failed: %A" errs
result
failwith <| sprintf "Download failed : [%A]" errs

/// [omit]
let private saveStreamToFileAsync (filePath: FilePath) (stream: Stream) : Async<Result<FilePath, Err list>> =
Expand Down Expand Up @@ -95,7 +98,7 @@ module Http =
return! saveStreamToFileAsync info.LocalFilePath stream
with
| ex ->
let err = sprintf "[%s] %s" info.Uri.Host ex.Message
let err = sprintf "[%s] %s" info.Uri.OriginalString ex.Message
return Error [err ]
}

Expand All @@ -109,24 +112,26 @@ module Http =
Async.result (Error errs)

/// Download file by the given file path and Uri
/// string -> string -> Result<FilePath,string list>
/// string -> string -> string
/// ## Parameters
/// - `localFilePath` - A local file path to download file
/// - `uri` - A Uri to download from
///
/// ## Returns
/// - `Result` type. Success branch contains a downloaded file path. Failure branch contains a list of errors
let downloadFile (localFilePath: string) (uri: string) : Result<string, string list> =
/// - `string` type. Contains a downloaded file path
let downloadFile (localFilePath: string) (uri: string) : string =
downloadFileAsync { Uri=uri; Path=localFilePath }
|> Async.RunSynchronously
|> printDownloadResults
|> processResults

/// Download list of Uri's in parallel
/// DownloadParameters -> Result<FilePath, Err list>
/// DownloadParameters -> string list
/// ## Parameters
/// - `input` - List of Http.DownloadParameters. Each Http.DownloadParameters record type contains Uri and file path
///
/// ## Returns
/// - `Result` type. Success branch contains a list of downloaded file paths. Failure branch contains a list of errors
let downloadFiles (input: DownloadParameters list) : Result<string list, string list> =
/// - `string list` type. Contains a list of downloaded file paths
let downloadFiles (input: DownloadParameters list) : string list =
input
// DownloadParameters -> "Async<Result<FilePath, Err list>> list"
|> List.map downloadFileAsync
Expand All @@ -135,4 +140,4 @@ module Http =
// "Async<Result<FilePath, Err list> list>" -> "Async<Result<FilePath list, Err list>>"
|> Async.map List.sequenceResultA
|> Async.RunSynchronously
|> printDownloadResults
|> processResults
5 changes: 5 additions & 0 deletions src/app/Fake.Net.Http/List.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
open Fake.Net.Async
open Fake.Net.Result

/// [omit]
// List extensions for traversing Result and Async types
// Functions from fsharpforfunandprofit.com, please see details here:
// https://fsharpforfunandprofit.com/posts/elevated-world-5/
module List =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should mark that internal?


/// [omit]
/// Map a Async producing function over a list to get a new Async
/// using applicative style
/// ('a -> Async<'b>) -> 'a list -> Async<'b list>
Expand All @@ -27,10 +29,12 @@ module List =

List.foldBack folder list initState

/// [omit]
/// Transform a "list<Async>" into a "Async<list>"
/// and collect the results using apply.
let sequenceAsyncA x = traverseAsyncA id x

/// [omit]
/// Map a Result producing function over a list to get a new Result
/// using applicative style
/// ('a -> Result<'b>) -> 'a list -> Result<'b list>
Expand All @@ -50,6 +54,7 @@ module List =

List.foldBack folder list initState

/// [omit]
/// Transform a "list<Result>" into a "Result<list>"
/// and collect the results using apply.
let sequenceResultA x = traverseResultA id x
Expand Down
3 changes: 3 additions & 0 deletions src/app/Fake.Net.Http/Result.fs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
namespace Fake.Net.Result

/// [omit]
module Result =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

internal?


/// [omit]
type ResultBuilder() =
member __.Bind(m, f) =
match m with
Expand All @@ -11,6 +13,7 @@ module Result =
member __.Return(x) =
Ok x

/// [omit]
let apply fResult xResult =
match fResult,xResult with
| Ok f, Ok x ->
Expand Down
12 changes: 12 additions & 0 deletions src/app/FakeLib/FakeLib.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,18 @@
<Compile Include="..\Fake.DotNet.Xamarin\Xamarin.fs">
<Link>Fake.DotNet.Xamarin/Xamarin.fs</Link>
</Compile>
<Compile Include="..\Fake.Net.Http\Async.fs">
<Link>Fake.Net.Http/Async.fs</Link>
</Compile>
<Compile Include="..\Fake.Net.Http\Result.fs">
<Link>Fake.Net.Http/Result.fs</Link>
</Compile>
<Compile Include="..\Fake.Net.Http\List.fs">
<Link>Fake.Net.Http/List.fs</Link>
</Compile>
<Compile Include="..\Fake.Net.Http\HttpLoader.fs">
<Link>Fake.Net.Http/HttpLoader.fs</Link>
</Compile>
<Compile Include="UserInputHelper.fs" />
<Compile Include="CSharpHelper.fs" />
<Compile Include="EnvironmentHelper.fs" />
Expand Down