-
Notifications
You must be signed in to change notification settings - Fork 125
Add HTTPClientRequest
#509
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
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,127 @@ | ||||||||||||||||||||||||||||
//===----------------------------------------------------------------------===// | ||||||||||||||||||||||||||||
// | ||||||||||||||||||||||||||||
// This source file is part of the AsyncHTTPClient open source project | ||||||||||||||||||||||||||||
// | ||||||||||||||||||||||||||||
// Copyright (c) 2021 Apple Inc. and the AsyncHTTPClient project authors | ||||||||||||||||||||||||||||
// Licensed under Apache License v2.0 | ||||||||||||||||||||||||||||
// | ||||||||||||||||||||||||||||
// See LICENSE.txt for license information | ||||||||||||||||||||||||||||
// See CONTRIBUTORS.txt for the list of AsyncHTTPClient project authors | ||||||||||||||||||||||||||||
// | ||||||||||||||||||||||||||||
// SPDX-License-Identifier: Apache-2.0 | ||||||||||||||||||||||||||||
// | ||||||||||||||||||||||||||||
//===----------------------------------------------------------------------===// | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
#if compiler(>=5.5) && canImport(_Concurrency) | ||||||||||||||||||||||||||||
import NIOCore | ||||||||||||||||||||||||||||
import NIOHTTP1 | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
@available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *) | ||||||||||||||||||||||||||||
struct HTTPClientRequest { | ||||||||||||||||||||||||||||
var url: String | ||||||||||||||||||||||||||||
var method: HTTPMethod | ||||||||||||||||||||||||||||
var headers: HTTPHeaders | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
var body: Body? | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
init(url: String) { | ||||||||||||||||||||||||||||
self.url = url | ||||||||||||||||||||||||||||
self.method = .GET | ||||||||||||||||||||||||||||
self.headers = .init() | ||||||||||||||||||||||||||||
self.body = .none | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
@available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *) | ||||||||||||||||||||||||||||
extension HTTPClientRequest { | ||||||||||||||||||||||||||||
struct Body { | ||||||||||||||||||||||||||||
internal enum Mode { | ||||||||||||||||||||||||||||
case asyncSequence(length: Int?, (ByteBufferAllocator) async throws -> ByteBuffer?) | ||||||||||||||||||||||||||||
case sequence(length: Int?, (ByteBufferAllocator) -> ByteBuffer) | ||||||||||||||||||||||||||||
case byteBuffer(ByteBuffer) | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
var mode: Mode | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
private init(_ mode: Mode) { | ||||||||||||||||||||||||||||
self.mode = mode | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
@available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *) | ||||||||||||||||||||||||||||
extension HTTPClientRequest.Body { | ||||||||||||||||||||||||||||
static func byteBuffer(_ byteBuffer: ByteBuffer) -> Self { | ||||||||||||||||||||||||||||
self.init(.byteBuffer(byteBuffer)) | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
static func bytes<Bytes>( | ||||||||||||||||||||||||||||
length: Int? = nil, | ||||||||||||||||||||||||||||
_ bytes: Bytes | ||||||||||||||||||||||||||||
) -> Self where Bytes: Sequence, Bytes.Element == UInt8 { | ||||||||||||||||||||||||||||
self.init(.sequence(length: length) { allocator in | ||||||||||||||||||||||||||||
if let buffer = bytes.withContiguousStorageIfAvailable({ allocator.buffer(bytes: $0) }) { | ||||||||||||||||||||||||||||
// fastpath | ||||||||||||||||||||||||||||
return buffer | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
// potentially really slow path | ||||||||||||||||||||||||||||
return allocator.buffer(bytes: bytes) | ||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
static func bytes<Bytes>( | ||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we make this method |
||||||||||||||||||||||||||||
_ bytes: Bytes | ||||||||||||||||||||||||||||
) -> Self where Bytes: RandomAccessCollection, Bytes.Element == UInt8 { | ||||||||||||||||||||||||||||
self.init(.sequence(length: bytes.count) { allocator in | ||||||||||||||||||||||||||||
if let buffer = bytes.withContiguousStorageIfAvailable({ allocator.buffer(bytes: $0) }) { | ||||||||||||||||||||||||||||
// fastpath | ||||||||||||||||||||||||||||
return buffer | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
// potentially really slow path | ||||||||||||||||||||||||||||
return allocator.buffer(bytes: bytes) | ||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
/// This method should never be used and was always deprecated. | ||||||||||||||||||||||||||||
/// The whole purpose of this overload is to prevent users from providing a redundant length if `Bytes` conforms to | ||||||||||||||||||||||||||||
/// `RandomAccessCollection` because it already provide a property `count` to get the length in O(**1**). | ||||||||||||||||||||||||||||
/// - Note: `length` is ignored in favour of `bytes.count` | ||||||||||||||||||||||||||||
@available(*, deprecated, message: "no need to manually specify `length` because we automatically use `bytes.count` as the `length`") | ||||||||||||||||||||||||||||
static func bytes<Bytes>( | ||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we make this method |
||||||||||||||||||||||||||||
length: Int, | ||||||||||||||||||||||||||||
_ collection: Bytes | ||||||||||||||||||||||||||||
) -> Self where Bytes: RandomAccessCollection, Bytes.Element == UInt8 { | ||||||||||||||||||||||||||||
return .bytes(collection) | ||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we're going to offer this overload, can we at least |
||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is an interesting idea... It pushes people into using the right thing. However I wonder if it is a good idea to introduce new API, that we deprecate from the get go. @Lukasa wdyt? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd be more inclined to consider marking the method There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have tried async-http-client/Sources/AsyncHTTPClient/AsyncAwait/HTTPClientRequest.swift Lines 58 to 70 in 8e4b2b4
Even adding @_disfavoredOverload to the Sequence overload doesn't help.
I think what we could also do is marking the method as deprecated and just adding a fatalError with a useful message. Then user will get a compiler warning and a runtime error. WDYT? |
||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
static func stream<SequenceOfBytes>( | ||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we make this method |
||||||||||||||||||||||||||||
length: Int? = nil, | ||||||||||||||||||||||||||||
_ sequenceOfBytes: SequenceOfBytes | ||||||||||||||||||||||||||||
) -> Self where SequenceOfBytes: AsyncSequence, SequenceOfBytes.Element == ByteBuffer { | ||||||||||||||||||||||||||||
var iterator = sequenceOfBytes.makeAsyncIterator() | ||||||||||||||||||||||||||||
let body = self.init(.asyncSequence(length: length) { _ -> ByteBuffer? in | ||||||||||||||||||||||||||||
try await iterator.next() | ||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||
return body | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
static func stream<Bytes>( | ||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we make this method |
||||||||||||||||||||||||||||
length: Int? = nil, | ||||||||||||||||||||||||||||
_ bytes: Bytes | ||||||||||||||||||||||||||||
) -> Self where Bytes: AsyncSequence, Bytes.Element == UInt8 { | ||||||||||||||||||||||||||||
var iterator = bytes.makeAsyncIterator() | ||||||||||||||||||||||||||||
let body = self.init(.asyncSequence(length: nil) { allocator -> ByteBuffer? in | ||||||||||||||||||||||||||||
var buffer = allocator.buffer(capacity: 1024) // TODO: Magic number | ||||||||||||||||||||||||||||
while buffer.writableBytes > 0, let byte = try await iterator.next() { | ||||||||||||||||||||||||||||
buffer.writeInteger(byte) | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
if buffer.readableBytes > 0 { | ||||||||||||||||||||||||||||
return buffer | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
return nil | ||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||
return body | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make this method
@inlinable
?