Skip to content

Commit

Permalink
feat(request): [#11] Rename Endpoint -> Path (#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
pjechris authored Oct 7, 2022
1 parent ba61a94 commit f3d0d1c
Show file tree
Hide file tree
Showing 11 changed files with 94 additions and 86 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ extension Request {
}
```

This defines a `Request.login(_:)` method which create a request targeting "login" endpoint by sending a `UserBody` and expecting a `UserResponse` as response.
This defines a `Request.login(_:)` method which create a request targeting "login" path by sending a `UserBody` and expecting a `UserResponse` as response.

### Sending a request

Expand All @@ -64,7 +64,7 @@ try await session.response(for: .login(UserBody(username: "pjechris", password:

A few words about Session:

- `baseURL` will be prepended to all call endpoints
- `baseURL` will be prepended to all call paths
- You can skip encoder and decoder if you use JSON
- You can provide a custom `URLSession` instance if ever needed

Expand Down Expand Up @@ -138,13 +138,13 @@ extension Request {
}
```

## Constant endpoints
## Constant paths

You can declare constant endpoints if needed (refer to Endpoint documentation to see more):
You can declare constant paths if needed (refer to Path documentation to see more):

```swift
extension Endpoint {
static let login: Endpoint = "login"
extension Path {
static let login: Path = "login"
}

extension Request {
Expand Down
44 changes: 0 additions & 44 deletions Sources/SimpleHTTP/Request/Endpoint.swift

This file was deleted.

44 changes: 44 additions & 0 deletions Sources/SimpleHTTP/Request/Path.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import Foundation

/// A path represents a path a request can query to
///
/// You can create paths using plain String, for instance:
/// ```swift
/// extension Path {
/// static let user = "v1/users"
/// }
///
/// If you want to regroup a set of paths you can use your own "namespace" and add a forward declaration in `Path`.
/// Adding a declaration provide autocompletion when using it in `Request`.
/// ```swift
/// enum MyPaths {
/// static let user: Path = "v1/users"
/// }
///
/// extension Path {
/// static let myPaths = MyPaths.self
/// }
///
/// let user: Path = .myPaths.user
/// ```
public struct Path: Equatable, ExpressibleByStringLiteral, ExpressibleByStringInterpolation {
/// relative path
public let value: String

init(value: String) {
self.value = value
}

public init(stringLiteral value: StringLiteralType) {
self.init(value: value)
}

public init(stringInterpolation: DefaultStringInterpolation) {
self.init(value: stringInterpolation.description)
}

public static func ==(lhs: Path, rhs: String) -> Bool {
lhs.value == rhs
}
}

56 changes: 32 additions & 24 deletions Sources/SimpleHTTP/Request/Request.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,68 +17,76 @@ public enum Body {
///
/// Highly inspired by https://swiftwithmajid.com/2021/02/10/building-type-safe-networking-in-swift/
public struct Request<Output> {
/// request relative endpoint
public let endpoint: Endpoint
/// request relative path
public let path: Path
public let method: Method
public let body: Body?
public let query: [String: QueryParam]
public private(set) var cachePolicy: URLRequest.CachePolicy = .useProtocolCachePolicy
public private(set) var headers: HTTPHeaderFields = [:]
public var cachePolicy: URLRequest.CachePolicy = .useProtocolCachePolicy
public var headers: HTTPHeaderFields = [:]

/// Creates a request suitable for a HTTP GET
public static func get(_ endpoint: Endpoint, query: [String: QueryParam] = [:]) -> Self {
self.init(endpoint: endpoint, method: .get, query: query, body: nil)
public static func get(_ path: Path, query: [String: QueryParam] = [:]) -> Self {
self.init(path: path, method: .get, query: query, body: nil)
}

/// Creates a request suitable for a HTTP POST with a `Encodable` body
public static func post(_ endpoint: Endpoint, body: Encodable?, query: [String: QueryParam] = [:])
public static func post(_ path: Path, body: Encodable?, query: [String: QueryParam] = [:])
-> Self {
self.init(endpoint: endpoint, method: .post, query: query, body: body.map(Body.encodable))
self.init(path: path, method: .post, query: query, body: body.map(Body.encodable))
}

/// Creates a request suitable for a HTTP POST with a `MultipartFormData` body
@_disfavoredOverload
public static func post(_ endpoint: Endpoint, body: MultipartFormData?, query: [String: QueryParam] = [:])
public static func post(_ path: Path, body: MultipartFormData?, query: [String: QueryParam] = [:])
-> Self {
self.init(endpoint: endpoint, method: .post, query: query, body: body.map(Body.multipart))
self.init(path: path, method: .post, query: query, body: body.map(Body.multipart))
}

/// Creates a request suitable for a HTTP PUT with a `Encodable` body
public static func put(_ endpoint: Endpoint, body: Encodable, query: [String: QueryParam] = [:])
public static func put(_ path: Path, body: Encodable, query: [String: QueryParam] = [:])
-> Self {
self.init(endpoint: endpoint, method: .put, query: query, body: .encodable(body))
self.init(path: path, method: .put, query: query, body: .encodable(body))
}

/// Creates a request suitable for a HTTP PUT with a `MultipartFormData` body
public static func put(_ endpoint: Endpoint, body: MultipartFormData, query: [String: QueryParam] = [:])
public static func put(_ path: Path, body: MultipartFormData, query: [String: QueryParam] = [:])
-> Self {
self.init(endpoint: endpoint, method: .put, query: query, body: .multipart(body))
self.init(path: path, method: .put, query: query, body: .multipart(body))
}

/// Create a HTTP PUT request with no body
public static func put(_ path: Path, query: [String: QueryParam] = [:]) -> Self {
self.init(path: path, method: .put, query: query, body: nil)
}

/// Creates a request suitable for a HTTP PATCH with a `Encodable` body
public static func patch(_ endpoint: Endpoint, body: Encodable, query: [String: QueryParam] = [:])
public static func patch(_ path: Path, body: Encodable, query: [String: QueryParam] = [:])
-> Self {
self.init(endpoint: endpoint, method: .patch, query: query, body: .encodable(body))
self.init(path: path, method: .patch, query: query, body: .encodable(body))
}

/// Creates a request suitable for a HTTP PATCH with a `MultipartFormData` body
public static func patch(_ endpoint: Endpoint, body: MultipartFormData, query: [String: QueryParam] = [:])
public static func patch(_ path: Path, body: MultipartFormData, query: [String: QueryParam] = [:])
-> Self {
self.init(endpoint: endpoint, method: .patch, query: query, body: .multipart(body))
self.init(path: path, method: .patch, query: query, body: .multipart(body))
}

/// Creates a request suitable for a HTTP DELETE
/// Default implementation does not allow for sending a body. If you need such a case extend Request with your
/// own init method
public static func delete(_ endpoint: Endpoint, query: [String: QueryParam] = [:]) -> Self {
self.init(endpoint: endpoint, method: .delete, query: query, body: nil)
public static func delete(_ path: Path, query: [String: QueryParam] = [:]) -> Self {
self.init(path: path, method: .delete, query: query, body: nil)
}

/// Creates a DELETE request with a Encodable body
public static func delete(_ path: Path, body: Encodable, query: [String: QueryParam] = [:]) -> Self {
self.init(path: path, method: .delete, query: query, body: nil)
}

/// Creates a Request.
///
/// Use this init only if default provided static initializers (`.get`, `.post`, `.put`, `patch`, `.delete`) do not suit your needs.
public init(endpoint: Endpoint, method: Method, query: [String: QueryParam], body: Body?) {
self.endpoint = endpoint
public init(path: Path, method: Method, query: [String: QueryParam], body: Body?) {
self.path = path
self.method = method
self.body = body
self.query = query
Expand Down
6 changes: 3 additions & 3 deletions Sources/SimpleHTTP/Request/URL+Request.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import FoundationNetworking

extension URL {
init<Output>(from request: Request<Output>) throws {
guard var components = URLComponents(string: request.endpoint.path) else {
throw URLComponents.Error.invalid(endpoint: request.endpoint)
guard var components = URLComponents(string: request.path.value) else {
throw URLComponents.Error.invalid(path: request.path)
}

let queryItems = (components.queryItems ?? []) + request.query.queryItems
Expand All @@ -24,7 +24,7 @@ extension URL {

extension URLComponents {
public enum Error: Swift.Error {
case invalid(endpoint: Endpoint)
case invalid(path: Path)
case cannotGenerateURL(components: URLComponents)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Foundation

extension URLRequest {
/// Return a new URLRequest whose endpoint is relative to `baseURL`
/// Return a new URLRequest whose path is relative to `baseURL`
public func relativeTo(_ baseURL: URL) -> URLRequest {
var urlRequest = self
var components = URLComponents(string: baseURL.appendingPathComponent(url?.path ?? "").absoluteString)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Foundation
import XCTest
@testable import SimpleHTTP
@testable import SimpleHTTPFoundation

class URLRequestURLTests: XCTestCase {
func test_relativeTo_requestURLHasBaseURL() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import XCTest
import SimpleHTTP
import SimpleHTTPFoundation

#if canImport(FoundationNetworking)
import FoundationNetworking
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import XCTest
import SimpleHTTP
import SimpleHTTPFoundation

#if canImport(FoundationNetworking)
import FoundationNetworking
Expand Down
6 changes: 3 additions & 3 deletions Tests/SimpleHTTPTests/Request/RequestTests.swift
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import XCTest
@testable import SimpleHTTP

extension Endpoint {
fileprivate static let test: Endpoint = "test"
extension Path {
fileprivate static let test: Path = "test"
}

class RequestTests: XCTestCase {
let baseURL = URL(string: "https://google.fr")!

func test_init_withPathAsString() {
XCTAssertEqual(Request<Void>.get("hello_world").endpoint, "hello_world")
XCTAssertEqual(Request<Void>.get("hello_world").path, "hello_world")
}

func test_toURLRequest_setHttpMethod() throws {
Expand Down
4 changes: 2 additions & 2 deletions Tests/SimpleHTTPTests/Session/SessionTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ class SessionAsyncTests: XCTestCase {
}
}

private extension Endpoint {
static let test: Endpoint = "test"
private extension Path {
static let test: Path = "test"
}

private struct Content: Codable, Equatable {
Expand Down

0 comments on commit f3d0d1c

Please sign in to comment.