@@ -14,120 +14,117 @@ import NIOHTTP1
1414
1515/// Adapter that implements HTTPClient protocol using AsyncHTTPClient
1616public class AsyncHTTPClientAdapter : HTTPClient {
17- /// The underlying AsyncHTTPClient instance
18- private let client : AsyncHTTPClient . HTTPClient
19-
20- /// Initializes a new AsyncHTTPClientAdapter with the provided AsyncHTTPClient
21- /// - Parameter client: The AsyncHTTPClient instance to use
22- public init ( client: AsyncHTTPClient . HTTPClient ) {
23- self . client = client
24- }
25-
26- /// Creates a new AsyncHTTPClientAdapter with a default configuration
27- /// - Returns: A new AsyncHTTPClientAdapter instance
28- public static func createDefault( ) -> AsyncHTTPClientAdapter {
29- let httpClient = AsyncHTTPClient . HTTPClient (
30- eventLoopGroupProvider: . singleton,
31- configuration: AsyncHTTPClient . HTTPClient. Configuration (
32- certificateVerification: . fullVerification,
33- timeout: . init(
34- connect: . seconds( 30 ) ,
35- read: . seconds( 30 )
36- ) ,
37- backgroundActivityLogger: nil )
38- )
39- return AsyncHTTPClientAdapter ( client: httpClient)
40- }
41-
42- /// Fetches data for a given HTTP request
43- /// - Parameter request: The HTTP request to perform
44- /// - Returns: A tuple containing the data and HTTP response
45- public func data( for request: HTTPRequest ) async throws -> ( Data , HTTPResponse ) {
46- let asyncHTTPClientRequest = try createAsyncHTTPClientRequest ( from: request)
47-
48- let response = try await client. execute ( asyncHTTPClientRequest, deadline: . now( ) + . seconds( 60 ) )
49- let body = try await response. body. collect ( upTo: 100 * 1024 * 1024 ) // 100 MB max
50-
51- let data = Data ( buffer: body)
52- let httpResponse = HTTPResponse (
53- statusCode: Int ( response. status. code) ,
54- headers: convertHeaders ( response. headers)
55- )
56-
57- return ( data, httpResponse)
58- }
59-
60- /// Fetches a byte stream for a given HTTP request
61- /// - Parameter request: The HTTP request to perform
62- /// - Returns: A tuple containing the byte stream and HTTP response
63- public func bytes( for request: HTTPRequest ) async throws -> ( HTTPByteStream , HTTPResponse ) {
64- let asyncHTTPClientRequest = try createAsyncHTTPClientRequest ( from: request)
65-
66- let response = try await client. execute ( asyncHTTPClientRequest, deadline: . now( ) + . seconds( 60 ) )
67- let httpResponse = HTTPResponse (
68- statusCode: Int ( response. status. code) ,
69- headers: convertHeaders ( response. headers)
70- )
71-
72- let stream = AsyncThrowingStream < String , Error > { continuation in
73- Task {
74- do {
75- for try await byteBuffer in response. body {
76- if let string = byteBuffer. getString ( at: 0 , length: byteBuffer. readableBytes) {
77- let lines = string. split ( separator: " \n " , omittingEmptySubsequences: false )
78- for line in lines {
79- continuation. yield ( String ( line) )
80- }
81- }
82- }
83- continuation. finish ( )
84- } catch {
85- continuation. finish ( throwing: error)
86- }
17+ /// Initializes a new AsyncHTTPClientAdapter with the provided AsyncHTTPClient
18+ /// - Parameter client: The AsyncHTTPClient instance to use
19+ public init ( client: AsyncHTTPClient . HTTPClient ) {
20+ self . client = client
21+ }
22+
23+ deinit {
24+ shutdown ( )
25+ }
26+
27+ /// Creates a new AsyncHTTPClientAdapter with a default configuration
28+ /// - Returns: A new AsyncHTTPClientAdapter instance
29+ public static func createDefault( ) -> AsyncHTTPClientAdapter {
30+ let httpClient = AsyncHTTPClient . HTTPClient (
31+ eventLoopGroupProvider: . singleton,
32+ configuration: AsyncHTTPClient . HTTPClient. Configuration (
33+ certificateVerification: . fullVerification,
34+ timeout: . init(
35+ connect: . seconds( 30 ) ,
36+ read: . seconds( 30 ) ) ,
37+ backgroundActivityLogger: nil ) )
38+ return AsyncHTTPClientAdapter ( client: httpClient)
39+ }
40+
41+ /// Fetches data for a given HTTP request
42+ /// - Parameter request: The HTTP request to perform
43+ /// - Returns: A tuple containing the data and HTTP response
44+ public func data( for request: HTTPRequest ) async throws -> ( Data , HTTPResponse ) {
45+ let asyncHTTPClientRequest = try createAsyncHTTPClientRequest ( from: request)
46+
47+ let response = try await client. execute ( asyncHTTPClientRequest, deadline: . now( ) + . seconds( 60 ) )
48+ let body = try await response. body. collect ( upTo: 100 * 1024 * 1024 ) // 100 MB max
49+
50+ let data = Data ( buffer: body)
51+ let httpResponse = HTTPResponse (
52+ statusCode: Int ( response. status. code) ,
53+ headers: convertHeaders ( response. headers) )
54+
55+ return ( data, httpResponse)
56+ }
57+
58+ /// Fetches a byte stream for a given HTTP request
59+ /// - Parameter request: The HTTP request to perform
60+ /// - Returns: A tuple containing the byte stream and HTTP response
61+ public func bytes( for request: HTTPRequest ) async throws -> ( HTTPByteStream , HTTPResponse ) {
62+ let asyncHTTPClientRequest = try createAsyncHTTPClientRequest ( from: request)
63+
64+ let response = try await client. execute ( asyncHTTPClientRequest, deadline: . now( ) + . seconds( 60 ) )
65+ let httpResponse = HTTPResponse (
66+ statusCode: Int ( response. status. code) ,
67+ headers: convertHeaders ( response. headers) )
68+
69+ let stream = AsyncThrowingStream < String , Error > { continuation in
70+ Task {
71+ do {
72+ for try await byteBuffer in response. body {
73+ if let string = byteBuffer. getString ( at: 0 , length: byteBuffer. readableBytes) {
74+ let lines = string. split ( separator: " \n " , omittingEmptySubsequences: false )
75+ for line in lines {
76+ continuation. yield ( String ( line) )
77+ }
8778 }
79+ }
80+ continuation. finish ( )
81+ } catch {
82+ continuation. finish ( throwing: error)
8883 }
89-
90- return ( . lines( stream) , httpResponse)
84+ }
9185 }
92-
93- /// Converts our HTTPRequest to AsyncHTTPClient's Request
94- /// - Parameter request: Our HTTPRequest
95- /// - Returns: AsyncHTTPClient Request
96- private func createAsyncHTTPClientRequest( from request: HTTPRequest ) throws -> HTTPClientRequest {
97- var asyncHTTPClientRequest = HTTPClientRequest ( url: request. url. absoluteString)
98- asyncHTTPClientRequest. method = NIOHTTP1 . HTTPMethod ( rawValue: request. method. rawValue)
99-
100- // Add headers
101- for (key, value) in request. headers {
102- asyncHTTPClientRequest. headers. add ( name: key, value: value)
103- }
104-
105- // Add body if present
106- if let body = request. body {
107- asyncHTTPClientRequest. body = . bytes( body)
108- }
109-
110- return asyncHTTPClientRequest
111- }
112-
113- /// Converts NIOHTTP1 headers to a dictionary
114- /// - Parameter headers: NIOHTTP1 HTTPHeaders
115- /// - Returns: Dictionary of header name-value pairs
116- private func convertHeaders( _ headers: HTTPHeaders ) -> [ String : String ] {
117- var result = [ String: String] ( )
118- for header in headers {
119- result [ header. name] = header. value
120- }
121- return result
86+
87+ return ( . lines( stream) , httpResponse)
88+ }
89+
90+ /// Properly shutdown the HTTP client
91+ public func shutdown( ) {
92+ try ? client. shutdown ( ) . wait ( )
93+ }
94+
95+ /// The underlying AsyncHTTPClient instance
96+ private let client : AsyncHTTPClient . HTTPClient
97+
98+ /// Converts our HTTPRequest to AsyncHTTPClient's Request
99+ /// - Parameter request: Our HTTPRequest
100+ /// - Returns: AsyncHTTPClient Request
101+ private func createAsyncHTTPClientRequest( from request: HTTPRequest ) throws -> HTTPClientRequest {
102+ var asyncHTTPClientRequest = HTTPClientRequest ( url: request. url. absoluteString)
103+ asyncHTTPClientRequest. method = NIOHTTP1 . HTTPMethod ( rawValue: request. method. rawValue)
104+
105+ // Add headers
106+ for (key, value) in request. headers {
107+ asyncHTTPClientRequest. headers. add ( name: key, value: value)
122108 }
123-
124- /// Properly shutdown the HTTP client
125- public func shutdown ( ) {
126- try ? client . shutdown ( ) . wait ( )
109+
110+ // Add body if present
111+ if let body = request . body {
112+ asyncHTTPClientRequest . body = . bytes ( body )
127113 }
128-
129- deinit {
130- shutdown ( )
114+
115+ return asyncHTTPClientRequest
116+ }
117+
118+ /// Converts NIOHTTP1 headers to a dictionary
119+ /// - Parameter headers: NIOHTTP1 HTTPHeaders
120+ /// - Returns: Dictionary of header name-value pairs
121+ private func convertHeaders( _ headers: HTTPHeaders ) -> [ String : String ] {
122+ var result = [ String: String] ( )
123+ for header in headers {
124+ result [ header. name] = header. value
131125 }
126+ return result
127+ }
128+
132129}
133130#endif
0 commit comments