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 support for plain control types #1487

Merged
merged 9 commits into from
Jul 24, 2023
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
3 changes: 3 additions & 0 deletions .github/workflows/pull-requests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
branches:
- main


jobs:
build-windows:

Expand All @@ -20,6 +21,8 @@ jobs:
- name: Restore packages
run: dotnet paket restore
- name: Build and test (Release)
env:
FAKE_DETAILED_ERRORS: true
Copy link
Collaborator

Choose a reason for hiding this comment

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

nice, agreed

run: dotnet fake build -t All
- name: Build (Debug)
run: dotnet build -c Debug -v n
Expand Down
2 changes: 2 additions & 0 deletions build.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ Target.create "Help" (fun _ ->
printfn ""
printfn " Other targets:"
printfn " * CleanInternetCaches"
printfn " * Format"
printfn " * CheckFormat"
printfn "")

let sourceFiles =
Expand Down
62 changes: 51 additions & 11 deletions src/FSharp.Data.Http/Http.fs
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,13 @@ module HttpStatusCodes =

type MultipartItem = MultipartItem of formField: string * filename: string * content: Stream

type MultipartFileItem =
| MultipartFileItem of formField: string * filename: string option * contentType: string option * content: Stream

type MultipartFormDataItem =
| FileValue of MultipartFileItem
| FormValue of string * string

/// The body to send in an HTTP request
type HttpRequestBody =

Expand All @@ -649,6 +656,9 @@ type HttpRequestBody =
/// A sequence of formParamName * fileName * fileContent groups
| Multipart of boundary: string * parts: seq<MultipartItem>

/// A sequence of formParamName * fileName * fileContent groups
| MultipartFormData of boundary: string * parts: seq<MultipartFormDataItem>

/// The response body returned by an HTTP request
type HttpResponseBody =
| Text of string
Expand Down Expand Up @@ -1521,7 +1531,7 @@ module internal HttpHelpers =
/// c) write newline
/// d) write section data
/// 3) write trailing boundary
let writeMultipart (boundary: string) (parts: seq<MultipartItem>) (e: Encoding) =
let writeMultipartFileItem (boundary: string) (parts: seq<MultipartFileItem>) (e: Encoding) =
let newlineStream () =
new MemoryStream(e.GetBytes "\r\n") :> Stream

Expand All @@ -1545,18 +1555,23 @@ module internal HttpHelpers =

let segments =
parts
|> Seq.map (fun (MultipartItem (formField, fileName, contentStream)) ->
let fileExt = Path.GetExtension fileName
let contentType = defaultArg (MimeTypes.tryFind fileExt) "application/octet-stream"
|> Seq.map (fun (MultipartFileItem (formField, fileName, contentType, contentStream)) ->
let printHeader (header, value) = sprintf "%s: %s" header value

let headerpart =
[ prefixedBoundary
HttpRequestHeaders.ContentDisposition("form-data", Some formField, Some fileName)
|> printHeader
HttpRequestHeaders.ContentType contentType
|> printHeader ]
|> String.concat "\r\n"
let headers =
match contentType with
| Some (contentType) ->
[ prefixedBoundary
HttpRequestHeaders.ContentDisposition("form-data", Some formField, fileName)
|> printHeader
HttpRequestHeaders.ContentType contentType
|> printHeader ]
| None ->
[ prefixedBoundary
HttpRequestHeaders.ContentDisposition("form-data", Some formField, fileName)
|> printHeader ]

let headerpart = headers |> String.concat "\r\n"

let headerStream =
let bytes = e.GetBytes headerpart
Expand All @@ -1583,6 +1598,16 @@ module internal HttpHelpers =
let wholePayloadLength = wholePayload |> trySumLength
new CombinedStream(wholePayloadLength, wholePayload) :> Stream

let writeMultipart (boundary: string) (parts: seq<MultipartItem>) (e: Encoding) =
let fileParts =
parts
|> Seq.map (fun (MultipartItem (formField, fileName, stream)) ->
let fileExt = Path.GetExtension fileName
let contentType = defaultArg (MimeTypes.tryFind fileExt) "application/octet-stream"
MultipartFileItem(formField, Some fileName, Some contentType, stream))

writeMultipartFileItem boundary fileParts e

let asyncCopy (source: Stream) (dest: Stream) =
async {
do!
Expand Down Expand Up @@ -2080,6 +2105,21 @@ type Http private () =

HttpContentTypes.FormValues, (fun e -> new MemoryStream(bytes e) :> _)
| Multipart (boundary, parts) -> HttpContentTypes.Multipart(boundary), writeMultipart boundary parts
| MultipartFormData (boundary, parts) ->
let fileParts =
parts
|> Seq.map (fun p ->
match p with
| FormValue (formField, value) ->
MultipartFileItem(
formField,
None,
None,
new MemoryStream(Encoding.UTF8.GetBytes(value))
)
| FileValue (item) -> item)

HttpContentTypes.Multipart(boundary), writeMultipartFileItem boundary fileParts

// Set default content type if it is not specified by the user
let encoding =
Expand Down
Loading