Skip to content

Instantly share code, notes, and snippets.

@mecid
Last active June 19, 2023 16:35
Show Gist options
  • Save mecid/bfb7201b6436b68ba9a29a933ad91e05 to your computer and use it in GitHub Desktop.
Save mecid/bfb7201b6436b68ba9a29a933ad91e05 to your computer and use it in GitHub Desktop.
Networking layer in Swift
import Foundation
import Combine
enum HTTPMethod: String {
case put = "PUT"
case post = "POST"
case get = "GET"
case delete = "DELETE"
case head = "HEAD"
}
protocol Request {
var scheme: String { get }
var method: HTTPMethod { get }
var path: String { get }
var host: String { get }
var queryItems: [URLQueryItem] { get }
var headers: [String: String] { get }
var body: Data? { get }
}
extension Request {
var scheme: String { return "https" }
var method: HTTPMethod { return .get }
var headers: [String: String] { return [:] }
var body: Data? { return nil }
}
extension Request {
func build() -> URLRequest {
var components = URLComponents()
components.scheme = scheme
components.host = host
components.path = path
components.queryItems = queryItems
guard let url = components.url else {
preconditionFailure("Invalid url components")
}
var request = URLRequest(url: url)
request.allHTTPHeaderFields = headers
request.httpMethod = method.rawValue
request.httpBody = body
return request
}
}
protocol RequestModifier {
func modifyRequest(_ request: URLRequest) -> URLRequest
}
struct DataLoader {
var session: URLSession
var modifiers: [RequestModifier]
func load(_ request: Request) -> AnyPublisher<Data, Error> {
let modifiedRequest = modifiers.reduce(request.build()) { $1.modifyRequest($0) }
return session
.dataTaskPublisher(for: modifiedRequest)
.map(\.data)
.mapError { $0 }
.eraseToAnyPublisher()
}
}
@getbiks
Copy link

getbiks commented Oct 23, 2019

@getbiks Hey, first of all create an enum or struct which conforms to Request protocol. Then you can use one of the extension methods of URLSession to make a request with that enum or struct ;)

Hi, If you could help me with an example using the code I hv presented in the first post. Thanks.

@wbbernardes
Copy link

wbbernardes commented Oct 25, 2020

@getbiks Hey, first of all create an enum or struct which conforms to Request protocol. Then you can use one of the extension methods of URLSession to make a request with that enum or struct ;)

Hi, If you could help me with an example using the code I hv presented in the first post. Thanks.

Hey dude, if you don't figure out how to use this class, follow an example.

enum CountryProvider {
    case listCountries
}

extension CountryProvider: Request {
    var path: String {
        switch self {
        case .listCountries:
            return "value"
        }
    }
    
    var host: String {
        return "www.google.com"
    }
    
    var queryItems: [URLQueryItem] {
        return [URLQueryItem(name: "", value: "")]
    }
    
    var method: HTTPMethod {
        return .post
    }
    
}

If i understood well this is how you should use it.
I suggest that you read this article, is more clarify than just a gist.
URLSessionProtocol

@mecid
Copy link
Author

mecid commented Nov 21, 2020

I've updated the networking code to use Combine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment