diff --git a/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Package.swift b/Package.swift index 6fa8241..c0b5a29 100644 --- a/Package.swift +++ b/Package.swift @@ -15,7 +15,8 @@ let package = Package( // Targets are the basic building blocks of a package, defining a module or a test suite. // Targets can depend on other targets in this package and products from dependencies. .target( - name: "SwiftDevRant"), + name: "SwiftDevRant" + ), .testTarget( name: "SwiftDevRantTests", dependencies: ["SwiftDevRant"] diff --git a/Sources/SwiftDevRant/DevRantBackend.swift b/Sources/SwiftDevRant/DevRantBackend.swift new file mode 100644 index 0000000..14bda95 --- /dev/null +++ b/Sources/SwiftDevRant/DevRantBackend.swift @@ -0,0 +1,3 @@ +struct DevRantBackend: Backend { + let baseURL = "https://devrant.com/api/" +} diff --git a/Sources/SwiftDevRant/Request/Backend.swift b/Sources/SwiftDevRant/Request/Backend.swift new file mode 100644 index 0000000..a823620 --- /dev/null +++ b/Sources/SwiftDevRant/Request/Backend.swift @@ -0,0 +1,3 @@ +public protocol Backend { + var baseURL: String { get } +} diff --git a/Sources/SwiftDevRant/Request/Request.swift b/Sources/SwiftDevRant/Request/Request.swift new file mode 100644 index 0000000..ab7faf4 --- /dev/null +++ b/Sources/SwiftDevRant/Request/Request.swift @@ -0,0 +1,64 @@ +import Foundation + +public struct Request { + public enum Error: Swift.Error, CustomStringConvertible { + case notHttpResponse + case notFound + case apiError(_ error: ApiError) + case generalError + + public var description: String { + switch self { + case .notHttpResponse: "response is not HTTP" + case .notFound: "Not found" + case .apiError(error: let error): "\(error)" + case .generalError: "General error" + } + } + } + + struct EmptyError: Decodable { + + } + + public enum Method: String { + case get = "GET" + case post = "POST" + case put = "PUT" + case delete = "DELETE" + case patch = "PATCH" + } + + public struct Config { + let method: Method + let backend: Backend + let path: String + var urlParameters: [String: String] = [:] + var headers: [String: String] = [:] + } + + var session = URLSession(configuration: .ephemeral) + + func makeURLRequest(config: Config, body: Data?) -> URLRequest { + let urlQuery = urlEncodedQueryString(from: config.urlParameters) + guard let url = URL(string: config.backend.baseURL + config.path + urlQuery) else { + fatalError("Couldn't create a URL") + } + var urlRequest = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData) + urlRequest.httpMethod = config.method.rawValue + urlRequest.httpBody = body + config.headers.forEach { + urlRequest.setValue($0.value, forHTTPHeaderField: $0.key) + } + return urlRequest + } + + func urlEncodedQueryString(from query: [String: String]) -> String { + guard !query.isEmpty else { return "" } + var components = URLComponents() + components.queryItems = query.map { URLQueryItem(name: $0.key, value: $0.value) } + let absoluteString = components.url?.absoluteString ?? "" + let plusCorrection = absoluteString.replacingOccurrences(of: "+", with: "%2b") + return plusCorrection + } +}