Skip to content

Commit 51f236e

Browse files
committed
Added initial implementation of HTTPLoading with combine
1 parent 95ca57b commit 51f236e

6 files changed

Lines changed: 109 additions & 2 deletions

File tree

HTTPFramework.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
/* Begin PBXBuildFile section */
1010
61C6A80E0C9A5F5C2756D592 /* libPods-HTTPFramework.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BF286CA8C5E32ACBCFFAF266 /* libPods-HTTPFramework.a */; };
11+
AD1FAF2E25504AFD0007D814 /* HTTPLoadingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD1FAF2D25504AFD0007D814 /* HTTPLoadingTests.swift */; };
1112
AD7F1A582545A7FD00FD12B0 /* HTTPFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AD7F1A4E2545A7FC00FD12B0 /* HTTPFramework.framework */; };
1213
AD7F1A5F2545A7FD00FD12B0 /* HTTPFramework.h in Headers */ = {isa = PBXBuildFile; fileRef = AD7F1A512545A7FC00FD12B0 /* HTTPFramework.h */; settings = {ATTRIBUTES = (Public, ); }; };
1314
AD7F1A6B2545A84700FD12B0 /* HTTPMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD7F1A6A2545A84700FD12B0 /* HTTPMethod.swift */; };
@@ -24,6 +25,7 @@
2425
ADFF72242550237D00E78549 /* HTTPResultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADFF72232550237D00E78549 /* HTTPResultTests.swift */; };
2526
ADFF7228255024A900E78549 /* HTTPErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADFF7227255024A900E78549 /* HTTPErrorTests.swift */; };
2627
ADFF722E255025B700E78549 /* HTTPBodyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADFF722D255025B700E78549 /* HTTPBodyTests.swift */; };
28+
ADFF7232255036C500E78549 /* HTTPLoading.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADFF7231255036C500E78549 /* HTTPLoading.swift */; };
2729
/* End PBXBuildFile section */
2830

2931
/* Begin PBXContainerItemProxy section */
@@ -39,6 +41,7 @@
3941
/* Begin PBXFileReference section */
4042
364B0DD793995C1448F3231E /* Pods-HTTPFramework.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HTTPFramework.release.xcconfig"; path = "Target Support Files/Pods-HTTPFramework/Pods-HTTPFramework.release.xcconfig"; sourceTree = "<group>"; };
4143
4CC0531749716F549FCFA617 /* Pods-HTTPFramework.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HTTPFramework.debug.xcconfig"; path = "Target Support Files/Pods-HTTPFramework/Pods-HTTPFramework.debug.xcconfig"; sourceTree = "<group>"; };
44+
AD1FAF2D25504AFD0007D814 /* HTTPLoadingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPLoadingTests.swift; sourceTree = "<group>"; };
4245
AD7F1A4E2545A7FC00FD12B0 /* HTTPFramework.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = HTTPFramework.framework; sourceTree = BUILT_PRODUCTS_DIR; };
4346
AD7F1A512545A7FC00FD12B0 /* HTTPFramework.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTTPFramework.h; sourceTree = "<group>"; };
4447
AD7F1A522545A7FC00FD12B0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -58,6 +61,7 @@
5861
ADFF72232550237D00E78549 /* HTTPResultTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPResultTests.swift; sourceTree = "<group>"; };
5962
ADFF7227255024A900E78549 /* HTTPErrorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPErrorTests.swift; sourceTree = "<group>"; };
6063
ADFF722D255025B700E78549 /* HTTPBodyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPBodyTests.swift; sourceTree = "<group>"; };
64+
ADFF7231255036C500E78549 /* HTTPLoading.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPLoading.swift; sourceTree = "<group>"; };
6165
BF286CA8C5E32ACBCFFAF266 /* libPods-HTTPFramework.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-HTTPFramework.a"; sourceTree = BUILT_PRODUCTS_DIR; };
6266
/* End PBXFileReference section */
6367

@@ -121,6 +125,7 @@
121125
AD7F1A7A2545ABD600FD12B0 /* HTTPResult.swift */,
122126
AD7F1A7E2545AC2400FD12B0 /* HTTPError.swift */,
123127
ADFF720D2550027E00E78549 /* HTTPBody.swift */,
128+
ADFF7231255036C500E78549 /* HTTPLoading.swift */,
124129
);
125130
path = HTTPFramework;
126131
sourceTree = "<group>";
@@ -136,6 +141,7 @@
136141
ADFF72232550237D00E78549 /* HTTPResultTests.swift */,
137142
ADFF7227255024A900E78549 /* HTTPErrorTests.swift */,
138143
ADFF722D255025B700E78549 /* HTTPBodyTests.swift */,
144+
AD1FAF2D25504AFD0007D814 /* HTTPLoadingTests.swift */,
139145
);
140146
path = HTTPFrameworkTests;
141147
sourceTree = "<group>";
@@ -304,6 +310,7 @@
304310
files = (
305311
AD7F1A732545A9F400FD12B0 /* HTTPResponse.swift in Sources */,
306312
AD7F1A7B2545ABD600FD12B0 /* HTTPResult.swift in Sources */,
313+
ADFF7232255036C500E78549 /* HTTPLoading.swift in Sources */,
307314
AD7F1A6B2545A84700FD12B0 /* HTTPMethod.swift in Sources */,
308315
AD7F1A6F2545A88400FD12B0 /* HTTPRequest.swift in Sources */,
309316
AD7F1A7F2545AC2400FD12B0 /* HTTPError.swift in Sources */,
@@ -318,6 +325,7 @@
318325
files = (
319326
ADFF721E25501F9100E78549 /* HTTPResponseTests.swift in Sources */,
320327
ADFF722E255025B700E78549 /* HTTPBodyTests.swift in Sources */,
328+
AD1FAF2E25504AFD0007D814 /* HTTPLoadingTests.swift in Sources */,
321329
ADFF72122550180E00E78549 /* HTTPMethodTests.swift in Sources */,
322330
ADFF721A25501A0900E78549 /* HTTPRequestTests.swift in Sources */,
323331
ADFF72162550197A00E78549 /* HTTPStatusTests.swift in Sources */,

HTTPFramework/HTTPError.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ public struct HTTPError: Error {
1818
public let underlyingError: Error?
1919

2020
public enum Code {
21-
// A.S.: Add more
21+
case badUrl
22+
case canceled
2223
case unkown
2324
}
2425
}

HTTPFramework/HTTPLoading.swift

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//
2+
// HTTPLoading.swift
3+
// HTTPFramework
4+
//
5+
// Created by Антон Савинов on 02.11.2020.
6+
//
7+
8+
import Foundation
9+
import Combine
10+
11+
public protocol HTTPLoading {
12+
func load(request: HTTPRequest) -> AnyPublisher<HTTPResponse, HTTPError>
13+
}
14+
15+
extension URLSession: HTTPLoading {
16+
public func load(request: HTTPRequest) -> AnyPublisher<HTTPResponse, HTTPError> {
17+
guard let url = request.url else {
18+
fatalError("Can't fetch url from HTTPRequest")
19+
}
20+
21+
var urlRequest = URLRequest(url: url)
22+
urlRequest.httpMethod = request.method.rawValue
23+
24+
for (header, value) in request.headers {
25+
urlRequest.addValue(value, forHTTPHeaderField: header)
26+
}
27+
28+
if request.body.isEmpty == false {
29+
for (header, value) in request.body.additionalHeaders {
30+
urlRequest.addValue(value, forHTTPHeaderField: header)
31+
}
32+
do {
33+
urlRequest.httpBody = try request.body.encodeData()
34+
} catch {
35+
fatalError("Can't encode data from request body")
36+
}
37+
}
38+
let publisher = dataTaskPublisher(for: urlRequest)
39+
return publisher.map { (data, urlResponse) -> HTTPResponse in
40+
if let httpUrlResponse = urlResponse as? HTTPURLResponse {
41+
return HTTPResponse(response: httpUrlResponse, request: request, body: data)
42+
} else {
43+
return HTTPResponse(response: HTTPURLResponse(), request: request, body: data)
44+
}
45+
}.mapError { (failure) -> HTTPError in
46+
let code: HTTPError.Code
47+
switch failure.code {
48+
case .cancelled:
49+
code = .canceled
50+
case .badURL:
51+
code = .badUrl
52+
default:
53+
code = .unkown
54+
}
55+
return HTTPError(code: code, request: request, response: nil, underlyingError: failure)
56+
}.eraseToAnyPublisher()
57+
}
58+
}

HTTPFramework/HTTPRequest.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,8 @@ public extension HTTPRequest {
4141
urlComponents.path = newValue
4242
}
4343
}
44+
45+
var url: URL? {
46+
urlComponents.url
47+
}
4448
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//
2+
// HTTPLoadingTests.swift
3+
// HTTPFrameworkTests
4+
//
5+
// Created by Антон Савинов on 02.11.2020.
6+
//
7+
8+
import XCTest
9+
import Combine
10+
@testable import HTTPFramework
11+
12+
class HTTPLoadingTests: XCTestCase {
13+
func testMethod() throws {
14+
let loader: HTTPLoading = URLSession.shared
15+
16+
var request = HTTPRequest()
17+
request.host = "swapi.dev"
18+
request.path = "/api/people"
19+
20+
21+
_ = loader.load(request: request)
22+
.receive(on: DispatchQueue.main)
23+
.sink { (result) in
24+
switch result {
25+
case .finished:
26+
print("finished")
27+
case .failure(let error):
28+
print(error)
29+
}
30+
} receiveValue: { (response) in
31+
XCTAssertNotNil(response)
32+
}
33+
34+
wait(for: [XCTestExpectation()], timeout: 60)
35+
}
36+
}

HTTPFrameworkTests/HTTPResultTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ import XCTest
99
@testable import HTTPFramework
1010

1111
class HTTPResultTests: XCTestCase {
12-
12+
1313
}

0 commit comments

Comments
 (0)