-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathHTTPRequest.swift
More file actions
82 lines (71 loc) · 2.8 KB
/
HTTPRequest.swift
File metadata and controls
82 lines (71 loc) · 2.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
//
// HTTPRequest.swift
// QuickHatchHTTP
//
// Created by Daniel Koster on 10/13/25.
//
import Foundation
import Combine
public protocol DataTask: NSObjectProtocol {
func resume()
func suspend()
func cancel()
}
public protocol HTTPRequest {
var headers: [String: String] { get }
var body: Data? { get }
var url: String { get }
var method: HTTPMethod { get }
}
public protocol HTTPRequestActionable {
func response() async throws -> HTTPResponse
var responsePublisher: any Publisher<HTTPResponse, Error> { get }
}
public protocol HTTPRequestDecodedActionable<ResponseType> {
associatedtype ResponseType: Codable
func responseDecoded() async throws -> Response<ResponseType>
var responseDecodedPublisher: any Publisher<ResponseType, Error> { get }
}
public struct QHHTTPRequest<T: Codable>: HTTPRequest, URLRequestProtocol, HTTPRequestActionable, HTTPRequestDecodedActionable {
public typealias ResponseType = T
public let headers: [String : String]
public let body: Data?
public let url: String
public let method: HTTPMethod
private let requestFactory: NetworkRequestFactory
private let jsonDecoder: JSONDecoder
public init(headers: [String : String] = [:],
body: Data? = nil,
url: String,
method: HTTPMethod,
requestFactory: NetworkRequestFactory = URLSessionRequestFactory(urlSession: URLSession.shared),
jsonDecoder: JSONDecoder = JSONDecoder()) {
self.headers = headers
self.body = body
self.url = url
self.method = method
self.requestFactory = requestFactory
self.jsonDecoder = jsonDecoder
}
public func response() async throws -> any HTTPResponse {
let urlRequest = try asURLRequest()
return try await requestFactory.data(request: urlRequest)
}
public func responseDecoded() async throws -> Response<T> {
let urlRequest = try asURLRequest()
return try await requestFactory.response(request: urlRequest, jsonDecoder: jsonDecoder)
}
public var responseDecodedPublisher: any Publisher<T, Error> {
guard let urlRequest = try? asURLRequest() else { return Fail(error: RequestError.malformedRequest) }
return requestFactory.response(urlRequest: urlRequest,
jsonDecoder: jsonDecoder)
.map { $0.data }
}
public var responsePublisher: any Publisher<any HTTPResponse, Error> {
guard let urlRequest = try? asURLRequest() else { return Fail(error: RequestError.malformedRequest) }
return requestFactory.dataPublisher(request: urlRequest)
}
public func asURLRequest() throws -> URLRequest {
return try URLRequest(url: url, method: method, headers: headers)
}
}