Skip to content

Commit

Permalink
* Restructured Helper (module) and DomainExtensions
Browse files Browse the repository at this point in the history
* Transformers as a list of transformers
  • Loading branch information
SchlenkR committed Jul 27, 2023
1 parent 364b788 commit 08efd7b
Show file tree
Hide file tree
Showing 10 changed files with 106 additions and 102 deletions.
9 changes: 6 additions & 3 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,18 @@
- #112: Allow to add (multiple) headers (by @Samuel-Dufour - thank you)

v11.0.0
- Breaking change: #121: Turning off debug logs in FSI (breaking change in signature / namespace)
- #121 (Breaking change): Turning off debug logs in FSI (breaking change in signature / namespace)
- #124: Support Repeating Query Parameters (thanks @DaveJohnson8080)
- Breaking change: #106: Allow filename metadata with other "parts" (thanks @dawedawe)
- #106 (Breaking change): Allow filename metadata with other "parts" (thanks @dawedawe)
- Breaking change: ContentTypeForPart custom operations should come after part definition
- Breaking changes
- #104 (Breaking change): Automatic GZip response decompression
- Other breaking changes:
- Removed `ContentTypeWithEncoding` and used optional `charset` parameter in `ContentType` overloads.
- Renamed `byteArray` to `binary` in Dsl, DslCE and CSharp.
- Caution (!!): Renamed `stringPart` to `textPart` and changed argument order for `name` and `value` in Dsl and DslCE.
- Restructured types in Domain
- `Helper` is a module instead of a namespace, and some things were moved.
- All transformers in config are a list of transformers instead of a single item.
</PackageReleaseNotes>
</PropertyGroup>

Expand Down
6 changes: 3 additions & 3 deletions src/FsHttp/Domain.fs
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ type HttpClientHandlerTransformer =
type Config = {
timeout: System.TimeSpan option
printHint: PrintHint
httpMessageTransformer: (System.Net.Http.HttpRequestMessage -> System.Net.Http.HttpRequestMessage)
httpClientHandlerTransformer: HttpClientHandlerTransformer
httpClientTransformer: (System.Net.Http.HttpClient -> System.Net.Http.HttpClient)
httpMessageTransformers: list<System.Net.Http.HttpRequestMessage -> System.Net.Http.HttpRequestMessage>
httpClientHandlerTransformers: list<HttpClientHandlerTransformer>
httpClientTransformers: list<System.Net.Http.HttpClient -> System.Net.Http.HttpClient>
httpCompletionOption: System.Net.Http.HttpCompletionOption
proxy: Proxy option
certErrorStrategy: CertErrorStrategy
Expand Down
19 changes: 19 additions & 0 deletions src/FsHttp/DomainExtensions.fs
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
[<AutoOpen>]
module FsHttp.DomainExtensions

open System
open System.Net.Http.Headers
open FsHttp

type FsHttpUrl with
member this.ToUriString() =
let uri = UriBuilder(this.address)

let queryParamsString =
this.additionalQueryParams
|> Seq.map (fun (k, v) -> $"""{k}={Uri.EscapeDataString $"{v}"}""")
|> String.concat "&"

uri.Query <-
match uri.Query, queryParamsString with
| "", "" -> ""
| s, "" -> s
| "", q -> $"?{q}"
| s, q -> $"{s}&{q}"

uri.ToString()

type ContentType with
member this.ToMediaHeaderValue() =
let mhv = MediaTypeHeaderValue.Parse(this.value)
Expand Down
12 changes: 6 additions & 6 deletions src/FsHttp/Dsl.fs
Original file line number Diff line number Diff line change
Expand Up @@ -459,14 +459,14 @@ module Config =
httpClientFactory = Some clientFactory
}

let inline transformHttpClient transformer config = { config with httpClientTransformer = transformer }
let inline transformHttpClient transformer config =
{ config with httpClientTransformers = config.httpClientTransformers @ [transformer] }

let inline transformHttpRequestMessage transformer config = { config with httpMessageTransformer = transformer }
let inline transformHttpRequestMessage transformer config =
{ config with httpMessageTransformers = config.httpMessageTransformers @ [transformer] }

let inline transformHttpClientHandler transformer config = {
config with
httpClientHandlerTransformer = transformer
}
let inline transformHttpClientHandler transformer config =
{ config with httpClientHandlerTransformers = config.httpClientHandlerTransformers @ [transformer] }

let inline proxy url config = {
config with
Expand Down
2 changes: 1 addition & 1 deletion src/FsHttp/FsHttp.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
<ItemGroup>
<Compile Include="AssemblyInfo.fs" />
<Compile Include="Domain.fs" />
<Compile Include="DomainExtensions.fs" />
<Compile Include="Fsi.fs" />
<Compile Include="DomainExtensions.fs" />
<Compile Include="Helper.fs" />
<Compile Include="Autos.fs" />
<Compile Include="MimeTypes.fs" />
Expand Down
6 changes: 3 additions & 3 deletions src/FsHttp/GlobalConfig.fs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ let mutable private mutableDefaults = {
requestPrintMode = HeadersAndBody(defaultHeadersAndBodyPrintMode ())
responsePrintMode = HeadersAndBody(defaultHeadersAndBodyPrintMode ())
}
httpMessageTransformer = id
httpClientHandlerTransformer = id
httpClientTransformer = id
httpMessageTransformers = []
httpClientHandlerTransformers = []
httpClientTransformers = []
httpClientFactory = None
httpCompletionOption = System.Net.Http.HttpCompletionOption.ResponseHeadersRead
proxy = None
Expand Down
142 changes: 61 additions & 81 deletions src/FsHttp/Helper.fs
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
namespace FsHttp.Helper
module FsHttp.Helper

open System
open System.IO
open System.Text
open System.Net.Http.Headers
open System.Runtime.InteropServices
open FsHttp

[<RequireQualifiedAccess>]
module Encoding =
let base64 = Encoding.GetEncoding("ISO-8859-1")

[<AutoOpen>]
module StringBuilderExtensions =
type StringBuilder with
member sb.append(s: string) = sb.Append s |> ignore
member sb.appendLine(s: string) = sb.AppendLine s |> ignore
member sb.newLine() = sb.appendLine ""
type StringBuilder with
member sb.append(s: string) = sb.Append s |> ignore
member sb.appendLine(s: string) = sb.AppendLine s |> ignore
member sb.newLine() = sb.appendLine ""

member sb.appendSection(s: string) =
sb.appendLine s
member sb.appendSection(s: string) =
sb.appendLine s

String([ 0 .. s.Length ] |> List.map (fun _ -> '-') |> List.toArray)
|> sb.appendLine
String([ 0 .. s.Length ] |> List.map (fun _ -> '-') |> List.toArray)
|> sb.appendLine

[<RequireQualifiedAccess>]
module Map =
Expand Down Expand Up @@ -56,62 +56,62 @@ module Url =
let b = (norm url2).TrimStart(delTrim).TrimEnd(delTrim)
a + sdel + b

[<RequireQualifiedAccess>]
module Stream =
// TODO: Inefficient
type Utf8StringBufferingStream(baseStream: Stream, readBufferLimit: int option) =
inherit Stream()
let notSeekable () = failwith "Stream is not seekable."
let notWritable () = failwith "Stream is not writable."
let readBuffer = ResizeArray<byte>()
override _.Flush() = baseStream.Flush()

override _.Read(buffer, offset, count) =
let readCount = baseStream.Read(buffer, offset, count)

match readCount, readBufferLimit with
| 0, _ -> ()
| readCount, None -> readBuffer.AddRange(buffer[offset .. readCount - 1])
| readCount, Some limit ->
let remaining = limit - readBuffer.Count
let copyCount = min remaining readCount

if copyCount > 0 then
readBuffer.AddRange(buffer[offset .. copyCount - 1])

readCount

override _.Seek(_, _) = notSeekable ()
override _.SetLength(_) = notWritable ()
override _.Write(_, _, _) = notWritable ()
override _.CanRead = true
override _.CanSeek = false
override _.CanWrite = false
override _.Length = baseStream.Length

override _.Position
with get () = baseStream.Position
and set (_) = notSeekable ()

member _.GetUtf8String() =
// TODO: Inefficient
type Utf8StringBufferingStream(baseStream: Stream, readBufferLimit: int option) =
inherit Stream()
let notSeekable () = failwith "Stream is not seekable."
let notWritable () = failwith "Stream is not writable."
let readBuffer = ResizeArray<byte>()
override _.Flush() = baseStream.Flush()

override _.Read(buffer, offset, count) =
let readCount = baseStream.Read(buffer, offset, count)

match readCount, readBufferLimit with
| 0, _ -> ()
| readCount, None -> readBuffer.AddRange(buffer[offset .. readCount - 1])
| readCount, Some limit ->
let remaining = limit - readBuffer.Count
let copyCount = min remaining readCount

if copyCount > 0 then
readBuffer.AddRange(buffer[offset .. copyCount - 1])

readCount

override _.Seek(_, _) = notSeekable ()
override _.SetLength(_) = notWritable ()
override _.Write(_, _, _) = notWritable ()
override _.CanRead = true
override _.CanSeek = false
override _.CanWrite = false
override _.Length = baseStream.Length

override _.Position
with get () = baseStream.Position
and set (_) = notSeekable ()

member _.GetUtf8String() =
#if NETSTANDARD2_0 || NETSTANDARD2_1
let buffer = readBuffer |> Seq.toArray
let buffer = readBuffer |> Seq.toArray
#else
let buffer = CollectionsMarshal.AsSpan(readBuffer)
let buffer = CollectionsMarshal.AsSpan(readBuffer)
#endif
let s = Encoding.UTF8.GetString(buffer).AsSpan()
let s = Encoding.UTF8.GetString(buffer).AsSpan()

if s.Length = 0 then
s.ToString()
else
let s =
if s[s.Length - 1] |> Char.IsHighSurrogate then
s.Slice(0, s.Length - 1)
else
s
if s.Length = 0 then
s.ToString()
else
let s =
if s[s.Length - 1] |> Char.IsHighSurrogate then
s.Slice(0, s.Length - 1)
else
s

s.ToString()
s.ToString()

[<RequireQualifiedAccess>]
module Stream =
let readUtf8StringAsync maxUtf16CharCount (stream: Stream) =
let sr = new StreamReader(stream, Encoding.UTF8)
let sb = StringBuilder()
Expand Down Expand Up @@ -214,23 +214,3 @@ module Stream =
}

let saveFileTAsync fileName source = saveFileAsync fileName source |> Async.StartAsTask

[<AutoOpen>]
module FsHttpUrlExtensions =
type FsHttpUrl with
member this.ToUriString() =
let uri = UriBuilder(this.address)

let queryParamsString =
this.additionalQueryParams
|> Seq.map (fun (k, v) -> $"""{k}={Uri.EscapeDataString $"{v}"}""")
|> String.concat "&"

uri.Query <-
match uri.Query, queryParamsString with
| "", "" -> ""
| s, "" -> s
| "", q -> $"?{q}"
| s, q -> $"{s}&{q}"

uri.ToString()
8 changes: 5 additions & 3 deletions src/FsHttp/Request.fs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,9 @@ let private getHttpClient config =
| Default -> false
| AlwaysAccept -> true

let handler = config.httpClientHandlerTransformer (getSslHandler ignoreSslIssues)
let handler =
let initHandler = getSslHandler ignoreSslIssues
config.httpClientHandlerTransformers |> List.fold (fun c n -> n c) initHandler

match config.proxy with
| Some proxy ->
Expand All @@ -176,7 +178,7 @@ let toAsync (context: IToRequest) =
async {
let request, requestMessage = toRequestAndMessage context
do Fsi.logfn $"Sending request {request.header.method} {request.header.url.ToUriString()} ..."
use finalRequestMessage = request.config.httpMessageTransformer requestMessage
use finalRequestMessage = request.config.httpMessageTransformers |> List.fold (fun c n -> n c) requestMessage
let! ctok = Async.CancellationToken
let client = getHttpClient request.config

Expand All @@ -186,7 +188,7 @@ let toAsync (context: IToRequest) =
let cookies = cookies |> List.map string |> String.concat "; "
do finalRequestMessage.Headers.Add("Cookie", cookies)

let finalClient = request.config.httpClientTransformer client
let finalClient = request.config.httpClientTransformers |> List.fold (fun c n -> n c) client

let! response =
finalClient.SendAsync(finalRequestMessage, request.config.httpCompletionOption, ctok)
Expand Down
2 changes: 1 addition & 1 deletion src/FsHttp/Response.fs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ let toStream response = (toStreamTAsync response).Result
let parseAsync parserName parse response =
async {
use! contentStream = toStreamAsync response
use bufferingStream = new Stream.Utf8StringBufferingStream(contentStream, None)
use bufferingStream = new Utf8StringBufferingStream(contentStream, None)

try
let! ct = Async.CancellationToken
Expand Down
2 changes: 1 addition & 1 deletion src/Tests/Helper.fs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ let private testUtf8StringBufferingStream limit =
let text = "abcdefghijklmnop"

let bs =
new Stream.Utf8StringBufferingStream(new MemoryStream(Encoding.UTF8.GetBytes(text)), limit)
new Utf8StringBufferingStream(new MemoryStream(Encoding.UTF8.GetBytes(text)), limit)

let sr = new StreamReader(bs)
do sr.ReadToEnd() |> ignore
Expand Down

0 comments on commit 08efd7b

Please sign in to comment.