Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Networking.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
E5CE42B923344DCA00295277 /* Networking.h in Headers */ = {isa = PBXBuildFile; fileRef = E5CE42AB23344DC900295277 /* Networking.h */; settings = {ATTRIBUTES = (Public, ); }; };
E5CE42EE23344F5800295277 /* NetworkingService.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5CE42ED23344F5800295277 /* NetworkingService.swift */; };
E5CE42F123344F6200295277 /* URLSessionDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5CE42EF23344F6200295277 /* URLSessionDispatcher.swift */; };
E5CE42F223344F6200295277 /* URLRequestDispatching.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5CE42F023344F6200295277 /* URLRequestDispatching.swift */; };
E5CE42F223344F6200295277 /* URLRequestDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5CE42F023344F6200295277 /* URLRequestDispatcher.swift */; };
E5CE42F523344F8500295277 /* URLRequestProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5CE42F323344F8500295277 /* URLRequestProtocol.swift */; };
E5CE42F623344F8500295277 /* URLRequestAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5CE42F423344F8500295277 /* URLRequestAdapter.swift */; };
E5CE42F823344FBE00295277 /* SimpleURLRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5CE42F723344FBE00295277 /* SimpleURLRequest.swift */; };
Expand Down Expand Up @@ -63,7 +63,7 @@
E5CE42B823344DCA00295277 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
E5CE42ED23344F5800295277 /* NetworkingService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkingService.swift; sourceTree = "<group>"; };
E5CE42EF23344F6200295277 /* URLSessionDispatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLSessionDispatcher.swift; sourceTree = "<group>"; };
E5CE42F023344F6200295277 /* URLRequestDispatching.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLRequestDispatching.swift; sourceTree = "<group>"; };
E5CE42F023344F6200295277 /* URLRequestDispatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLRequestDispatcher.swift; sourceTree = "<group>"; };
E5CE42F323344F8500295277 /* URLRequestProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLRequestProtocol.swift; sourceTree = "<group>"; };
E5CE42F423344F8500295277 /* URLRequestAdapter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLRequestAdapter.swift; sourceTree = "<group>"; };
E5CE42F723344FBE00295277 /* SimpleURLRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SimpleURLRequest.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -227,7 +227,7 @@
E5CE42C923344E0D00295277 /* Dispatcher */ = {
isa = PBXGroup;
children = (
E5CE42F023344F6200295277 /* URLRequestDispatching.swift */,
E5CE42F023344F6200295277 /* URLRequestDispatcher.swift */,
E5CE42EF23344F6200295277 /* URLSessionDispatcher.swift */,
);
path = Dispatcher;
Expand Down Expand Up @@ -456,7 +456,7 @@
E5CE4309233450A400295277 /* NSErrorExtension.swift in Sources */,
E5CE43062334503500295277 /* NetworkingError.swift in Sources */,
E5CE430223344FCA00295277 /* URLRequestBuilder.swift in Sources */,
E5CE42F223344F6200295277 /* URLRequestDispatching.swift in Sources */,
E5CE42F223344F6200295277 /* URLRequestDispatcher.swift in Sources */,
E5CE430F2334517300295277 /* CodableSerializing.swift in Sources */,
E5CE42EE23344F5800295277 /* NetworkingService.swift in Sources */,
E5CE4311233456CF00295277 /* CodableRequesting.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
//
// URLRequestDispatching.swift
// URLRequestDispatcher.swift
// Networking
//
// Created by Eduardo Sanches Bocato on 27/09/19.
// Copyright © 2019 Bocato. All rights reserved.
//

/// This guy is responsible for executing the requests by calling whoever we want to use as a client to deal with networking.
public protocol URLRequestDispatching {
public protocol URLRequestDispatcher {

/// Defines an adapter to modify requests when needed
var adapter: URLRequestAdapter? { get set }

/// Executes the request and provides a completion with the response.
///
Expand All @@ -28,7 +31,7 @@ public protocol URLRequestDispatching {
@discardableResult
func execute(request: URLRequestProtocol, completion: @escaping (_ response: Result<Data?, URLRequestError>) -> Void) -> URLRequestToken?
}
extension URLRequestDispatching {
extension URLRequestDispatcher {

@discardableResult
public func execute(request: URLRequestProtocol, completion: @escaping (_ response: Result<Data?, URLRequestError>) -> Void) -> URLRequestToken? {
Expand Down
33 changes: 16 additions & 17 deletions Networking/Sources/Dispatcher/URLSessionDispatcher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,6 @@
// Copyright © 2019 Bocato. All rights reserved.
//

//
// URLSessionDispatcher.swift
// Networking
//
// Created by Eduardo Sanches Bocato on 27/09/19.
// Copyright © 2019 Bocato. All rights reserved.
//

import Foundation

private struct DataTaskResponse {
Expand All @@ -22,12 +14,16 @@ private struct DataTaskResponse {
let httpResponse: HTTPURLResponse
}

public final class URLSessionDispatcher: URLRequestDispatching {
public final class URLSessionDispatcher: URLRequestDispatcher {

// MARK: - Private Properties

// MARK: - Properties
private let session: URLSessionProtocol
private let requestBuilderType: URLRequestBuilder.Type

private var session: URLSessionProtocol
private var requestBuilderType: URLRequestBuilder.Type
// MARK: - Public Properties

public var adapter: URLRequestAdapter?

// MARK: - Initialization

Expand All @@ -36,10 +32,10 @@ public final class URLSessionDispatcher: URLRequestDispatching {
/// - Parameter session: An URLSession.
public required init(
session: URLSessionProtocol = URLSession.shared,
requestBuilderType: URLRequestBuilder.Type = DefaultURLRequestBuilder.self
requestBuilderType: URLRequestBuilder.Type? = nil
) {
self.session = session
self.requestBuilderType = requestBuilderType
self.requestBuilderType = requestBuilderType ?? DefaultURLRequestBuilder.self
}

// MARK: - Public
Expand All @@ -53,11 +49,14 @@ public final class URLSessionDispatcher: URLRequestDispatching {

var urlRequestToken: URLRequestToken?

let requestBuilder = requestBuilderType.init(request: request)
if let adapter = adapter {
requestBuilder.add(adapter: adapter)
}

do {

let urlRequest = try requestBuilderType
.init(request: request)
.build() as NSURLRequest
let urlRequest = try requestBuilder.build() as NSURLRequest

dispatch(request: urlRequest, urlRequestToken: &urlRequestToken) { result in
queue.async { completion(result) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ import Foundation
/// Defines an API service.
public protocol NetworkingService {
/// The dispatcher to take care of the network requests.
var dispatcher: URLRequestDispatching { get }
var dispatcher: URLRequestDispatcher { get }
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public protocol URLRequestProtocol {
/// Defines the list of headers we want to pass along with each request.
var headers: [String: String]? { get }

/// Defines the adapters for the request
var adapters: [URLRequestAdapter]? { get }
// /// Defines the adapters for the request
// var adapters: [URLRequestAdapter]? { get set }

}
11 changes: 5 additions & 6 deletions Networking/Sources/URLRequests/Tools/URLRequestBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public protocol URLRequestBuilder {
func build() throws -> URLRequest
}

public final class DefaultURLRequestBuilder: URLRequestBuilder {
final class DefaultURLRequestBuilder: URLRequestBuilder {

// MARK: - Properties

Expand All @@ -75,7 +75,7 @@ public final class DefaultURLRequestBuilder: URLRequestBuilder {
private var method: HTTPMethod = .get
private var headers: [String: String]?
private var parameters: URLRequestParameters?
private var adapters: [URLRequestAdapter] = []
private var adapter: URLRequestAdapter?

// MARK: - Initialization

Expand All @@ -87,7 +87,6 @@ public final class DefaultURLRequestBuilder: URLRequestBuilder {
self.method = request.method
self.headers = request.headers
self.parameters = request.parameters
self.adapters = request.adapters ?? []
}

/// Initializes the request.
Expand Down Expand Up @@ -149,7 +148,7 @@ public final class DefaultURLRequestBuilder: URLRequestBuilder {
/// - Returns: Itself, for sugar syntax purposes.
@discardableResult
public func add(adapter: URLRequestAdapter) -> Self {
adapters.append(adapter)
self.adapter = adapter
return self
}

Expand All @@ -174,8 +173,8 @@ public final class DefaultURLRequestBuilder: URLRequestBuilder {
urlRequest.addValue($0.value, forHTTPHeaderField: $0.key)
}

try adapters.forEach {
urlRequest = try $0.adapt(urlRequest)
if let adapter = adapter {
urlRequest = try adapter.adapt(urlRequest)
}

return urlRequest
Expand Down
33 changes: 33 additions & 0 deletions NetworkingTests/Tests/Dispatcher/URLSessionDispatcherTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,39 @@ final class URLSessionDispatcherTests: XCTestCase {
}
}

func test_whenAdapterAndSucceed_adaptShouldBeCalled() {
// Given
guard let url = URL(string: "http://www.someurl.com/") else {
XCTFail("Could not create URL.")
return
}
let urlResponse = HTTPURLResponse(
url: url,
statusCode: 200,
httpVersion: nil,
headerFields: nil
)
let urlSessionStub = URLSessionStub(
data: nil,
urlResponse: urlResponse
)
let sut = URLSessionDispatcher(session: urlSessionStub)
let request: SimpleURLRequest = .init(url: url)

let adapterSpy = URLRequestAdapterSpy()
sut.adapter = adapterSpy

// When
let executeRequestExpectation = expectation(description: "executeRequestExpectation")
sut.execute(request: request) { _ in
executeRequestExpectation.fulfill()
}
wait(for: [executeRequestExpectation], timeout: 1.0)

// Then
XCTAssertTrue(adapterSpy.adaptCalled, "adapt method should have been called.")
}

}

// MARK: - Testing Helpers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ final class CodableRequestingTests: XCTestCase {
return
}
let resultToReturn: Result<Data?, URLRequestError> = .success(validDataToReturn)
let urlRequestDispatchingStub = URLRequestDispatchingStub(
let urlRequestDispatcherStub = URLRequestDispatcherStub(
resultToReturn: resultToReturn
)
guard let url = URL(string: "http://www.someurl.com/") else {
Expand All @@ -29,7 +29,7 @@ final class CodableRequestingTests: XCTestCase {
}
let request: SimpleURLRequest = .init(url: url)
let expectedCodableResult = SomeResponse(value: "something")
let sut = CodableRequestingService(dispatcher: urlRequestDispatchingStub)
let sut = CodableRequestingService(dispatcher: urlRequestDispatcherStub)

// When
let requestCodableExpectation = expectation(description: "serializeCodableExpectation")
Expand All @@ -53,18 +53,20 @@ final class CodableRequestingTests: XCTestCase {
// MARK: - Testing Helpers
private class CodableRequestingService: CodableRequesting {

var dispatcher: URLRequestDispatching
var dispatcher: URLRequestDispatcher

init(dispatcher: URLRequestDispatching) {
init(dispatcher: URLRequestDispatcher) {
self.dispatcher = dispatcher
}

}

final class URLRequestDispatchingStub: URLRequestDispatching {
final class URLRequestDispatcherStub: URLRequestDispatcher {

private let resultToReturn: Result<Data?, URLRequestError>

var adapter: URLRequestAdapter?

init(resultToReturn: Result<Data?, URLRequestError>) {
self.resultToReturn = resultToReturn
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ final class DefaultURLRequestBuilderTests: XCTestCase {

// MARK: - Testing Helpers

private final class URLRequestAdapterSpy: URLRequestAdapter {
final class URLRequestAdapterSpy: URLRequestAdapter {
private(set) var adaptCalled = false
func adapt(_ urlRequest: URLRequest) throws -> URLRequest {
adaptCalled = true
Expand Down
56 changes: 14 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Networking layer abstraction

Add this to Cartfile:

`git "https://github.com/bocato/Networking.git" ~> 1.0`
`git "https://github.com/bocato/Networking.git" ~> 1.1`

Then:

Expand Down Expand Up @@ -45,7 +45,7 @@ enum PokemonsRequest: Request {

var parameters: RequestParameters? {
switch self {
case let .list(limit):
case .list(let limit):
guard let limit = limit else { return nil }
return .url(["limit": limit])
}
Expand All @@ -64,11 +64,11 @@ final class PokemonsDataService: NetworkingService {

// MARK: - Properties

var dispatcher: URLRequestDispatching
var dispatcher: URLRequestDispatcher

// MARK: - Initialization

init(dispatcher: URLRequestDispatching) {
init(dispatcher: URLRequestDispatcher) {
self.dispatcher = dispatcher
}

Expand Down Expand Up @@ -160,45 +160,17 @@ final class AccessTokenAdapter: URLRequestAdapter {
}
```

The request will be like this:

```swift
enum PokemonsRequest: Request {

case list(limit: Int?, accessToken: String)

var path: String {
switch self {
case .list:
return "pokemon"
}
}

var method: HTTPMethod {
switch self {
case .list:
return .get
}
}

var headers: [String : String]? {
return nil
let dispatcher = URLSessionDispatcher()
dispatcher.adapter = AccessTokenAdapter(accessToken: "1234")

let request: PokemonsRequest = .list
dispatcher.execute(request: request) { (result) in
switch result {
case let .failure(error):
// Do something
case .success(data):
// Do something
}

var parameters: RequestParameters? {
switch self {
case let .list(limit):
guard let limit = limit else { return nil }
return .url(["limit": limit])
}
}

var adapters: [URLRequestAdapters]? {
switch self {
case let .list(_, accessToken):
return [AccessTokenAdapter(accessToken: accessToken)]
}
}

}
```