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

How to set body data to a HTTPRequest? #15

Open
li-bei opened this issue Jul 19, 2023 · 5 comments
Open

How to set body data to a HTTPRequest? #15

li-bei opened this issue Jul 19, 2023 · 5 comments
Labels
kind/enhancement Improvements to existing feature.

Comments

@li-bei
Copy link

li-bei commented Jul 19, 2023

That seems not supported yet?

@guoye-zhang guoye-zhang added the kind/enhancement Improvements to existing feature. label Jul 23, 2023
@guoye-zhang
Copy link
Collaborator

It is not currently supported. We need to find good mechanisms for sending data, stream, file, and potentially multipart body, and it will likely be a part of the future server and client HTTP APIs rather than on the currency types themselves.

https://github.com/atrick/swift-evolution/blob/bufferview-roadmap/visions/view-types.md
https://forums.swift.org/t/requirements-for-a-high-level-http-server-type/65337

@fumoboy007
Copy link

In the meantime, I think we could add URLSession convenience methods that take in a body parameter.

Currently, in order to send a POST request, the developer needs to manually convert the HTTPRequest to a URLRequest so that they can set the body. Then, they would need to manually convert the URLResponse to an HTTPResponse because there is no URLSession convenience method that accepts a URLRequest.

I was thinking the following two convenience methods could be added:

extension URLSession {
  func data(
    for request: HTTPRequest,
    body: Data,
    delegate: URLSessionTaskDelegate? = nil
  ) async throws -> (Data, HTTPResponse) {
    
  }

  func data(
    for request: HTTPRequest,
    bodyStream: InputStream,
    delegate: URLSessionTaskDelegate? = nil
  ) async throws -> (Data, HTTPResponse) {
    
  }
}

@guoye-zhang
Copy link
Collaborator

We currently have these 2:

public func upload(for request: HTTPRequest, fromFile fileURL: URL, delegate: URLSessionTaskDelegate? = nil) async throws -> (Data, HTTPResponse)
public func upload(for request: HTTPRequest, from bodyData: Data, delegate: URLSessionTaskDelegate? = nil) async throws -> (Data, HTTPResponse)

InputStream should be provided in needNewBodyStream delegate method since URLSession would ask for a new stream from the beginning in situations such as redirection or authentication. It's discouraged to provide a single stream upfront. You can convert HTTPRequest to URLRequest then call uploadTaskWithStreamedRequest. A convenience was not provided because InputStream doesn't work very well with Swift concurrency.

@fumoboy007
Copy link

Ah, I didn’t realize that URLSessionUploadTask can do short-lived requests; I thought it was only for long-lived requests. Thanks!

URLSessionDataTask also supports a request body via URLRequest.httpBody. Do you know what the difference is between using URLSessionDataTask vs. URLSessionUploadTask for short-lived requests with bodies? (If so, please also answer this StackOverflow question. 😆)

@guoye-zhang
Copy link
Collaborator

Upload task is a subclass of data task, so there is little difference between the 2 of them. It's recommended to use upload task instead of httpBody/httpBodyStream properties on the URLRequest. Upload/download tasks also have the benefit of working with background sessions (but you'll have to use the delegate instead of the convenience or async methods).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/enhancement Improvements to existing feature.
Projects
None yet
Development

No branches or pull requests

3 participants