Skip to content

Commit

Permalink
FEATURE: Create User Session
Browse files Browse the repository at this point in the history
  • Loading branch information
adamayoung committed Feb 6, 2024
1 parent 7365efc commit bd95731
Show file tree
Hide file tree
Showing 26 changed files with 147 additions and 121 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ env:
jobs:
analyze:
name: Analyze
runs-on: macos-13
runs-on: macos-14
timeout-minutes: 120
permissions:
actions: read
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -30,35 +30,11 @@ final class URLSessionHTTPClientAdapter: HTTPClient {
self.urlSession = urlSession
}

func get(url: URL, headers: [String: String]) async throws -> HTTPResponse {
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "GET"
for header in headers {
urlRequest.addValue(header.value, forHTTPHeaderField: header.key)
}

let data: Data
let response: URLResponse

do {
(data, response) = try await perform(urlRequest)
} catch let error {
throw error
}

guard let httpURLResponse = response as? HTTPURLResponse else {
return HTTPResponse(statusCode: -1, data: nil)
}

let statusCode = httpURLResponse.statusCode
return HTTPResponse(statusCode: statusCode, data: data)
}

func post(url: URL, body: Data, headers: [String: String]) async throws -> HTTPResponse {
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "POST"
urlRequest.httpBody = body
for header in headers {
func perform(request: HTTPRequest) async throws -> HTTPResponse {
var urlRequest = URLRequest(url: request.url)
urlRequest.httpMethod = request.method.rawValue
urlRequest.httpBody = request.body
for header in request.headers {
urlRequest.addValue(header.value, forHTTPHeaderField: header.key)
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/TMDb/Models/TMDbError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public enum TMDbError: Equatable, LocalizedError {
case (.notFound, .notFound):
true

case (let .unauthorised(lhsMessage), let .unauthorised(rhsMessage)):
case let (.unauthorised(lhsMessage), .unauthorised(rhsMessage)):
lhsMessage == rhsMessage

case (.network, .network):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,26 +25,13 @@ import Foundation
public protocol HTTPClient {

///
/// Performs an HTTP GET request.
/// Performs an HTTP request.
///
/// - Parameters:
/// - url: The URL to use for the request.
/// - headers: Additional HTTP headers to use in the request.
/// - request: The HTTP request.
///
/// - Returns: An HTTP response object.
///
func get(url: URL, headers: [String: String]) async throws -> HTTPResponse

///
/// Performs an HTTP POST request.
///
/// - Parameters:
/// - url: The URL to use for the request.
/// - body: The body of the request.
/// - headers: Additional HTTP headers to use in the request.
///
/// - Returns: An HTTP response object.
///
func post(url: URL, body: Data, headers: [String: String]) async throws -> HTTPResponse
func perform(request: HTTPRequest) async throws -> HTTPResponse

}
50 changes: 50 additions & 0 deletions Sources/TMDb/Networking/HTTPRequest.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//
// HTTPRequest.swift
// TMDb
//
// Copyright © 2024 Adam Young.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an AS IS BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import Foundation

public struct HTTPRequest {

public let url: URL
public let method: HTTPRequest.Method
public let headers: [String: String]
public let body: Data?

public init(
url: URL,
method: HTTPRequest.Method = .get,
headers: [String: String] = [:],
body: Data? = nil
) {
self.url = url
self.method = method
self.headers = headers
self.body = body
}

}

public extension HTTPRequest {

enum Method: String {
case get = "GET"
case post = "POST"
}

}
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,10 @@ final class TMDbAPIClient: APIClient {
"Accept": "application/json"
]

let response: HTTPResponse

do {
response = try await httpClient.get(url: url, headers: headers)
} catch let error {
throw TMDbAPIError.network(error)
}
let request = HTTPRequest(url: url, headers: headers)
let responseObject: Response = try await perform(request: request)

let decodedResponse: Response = try await decodeResponse(response: response)

return decodedResponse
return responseObject
}

func post<Response: Decodable>(path: URL, body: some Encodable) async throws -> Response {
Expand All @@ -66,12 +59,28 @@ final class TMDbAPIClient: APIClient {
"Content-Type": "application/json",
"Accept": "application/json"
]
let bodyData = try await serialiser.encode(body)
let data: Data
do {
data = try await serialiser.encode(body)
} catch let error {
throw TMDbAPIError.encode(error)
}

let request = HTTPRequest(url: url, method: .post, headers: headers, body: data)
let responseObject: Response = try await perform(request: request)

return responseObject
}

}

extension TMDbAPIClient {

private func perform<Response: Decodable>(request: HTTPRequest) async throws -> Response {
let response: HTTPResponse

do {
response = try await httpClient.post(url: url, body: bodyData, headers: headers)
response = try await httpClient.perform(request: request)
} catch let error {
throw TMDbAPIError.network(error)
}
Expand All @@ -81,18 +90,14 @@ final class TMDbAPIClient: APIClient {
return decodedResponse
}

}

extension TMDbAPIClient {

private func urlFromPath(_ path: URL) -> URL {
guard var urlComponents = URLComponents(url: path, resolvingAgainstBaseURL: true) else {
return path
}

urlComponents.scheme = baseURL.scheme
urlComponents.host = baseURL.host
urlComponents.path = "\(baseURL.path)\(urlComponents.path)"
urlComponents.path = baseURL.appending(path: urlComponents.path).path()

return urlComponents.url!
.appendingAPIKey(apiKey)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ enum TMDbAPIError: Error {
///
case gatewayTimeout(String?)

///
/// Data encode error.
///
case encode(Error)

///
/// Data decode error.
///
Expand Down
File renamed without changes.
3 changes: 2 additions & 1 deletion Sources/TMDb/TMDb.docc/Extensions/AuthenticationService.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Topics

### Creating am Authentication Service
### Creating an Authentication Service

- ``init()``

Expand All @@ -11,3 +11,4 @@
- ``guestSession()``
- ``requestToken()``
- ``authenticateURL(for:redirectURL:)``
- ``createSession(withRequestToken:)``
2 changes: 1 addition & 1 deletion Sources/TMDb/TMDb.docc/GettingStarted/ConfiguringTMDb.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ The adapter should conform to ``HTTPClient``.

```swift
class MyHTTPClient: HTTPClient {
func get(url: URL, headers: [String: String]) async throws -> HTTPResponse {
func perform(request: HTTPRequest) async throws -> HTTPResponse {
// Implement performing a network request.
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ final class TMDbAPIClientTests: XCTestCase {

_ = try? await apiClient.get(path: URL(string: "/object")!) as String

let result = httpClient.lastHeaders?["Accept"]
let result = httpClient.lastRequest?.headers["Accept"]

XCTAssertEqual(result, expectedResult)
}
Expand All @@ -147,37 +147,37 @@ final class TMDbAPIClientTests: XCTestCase {

_ = try? await apiClient.get(path: URL(string: path)!) as String

let result = httpClient.lastURL
let result = httpClient.lastRequest?.url

XCTAssertEqual(result, expectedResult)
}

func testPostURLRequestAcceptHeaderSetToApplicationJSON() async throws {
httpClient.postResult = .success(HTTPResponse())
httpClient.result = .success(HTTPResponse())
let expectedResult = "application/json"
let pathURL = try XCTUnwrap(URL(string: "/object"))

_ = try? await apiClient.post(path: pathURL, body: "adam") as String

let result = httpClient.lastPostHeaders?["Accept"]
let result = httpClient.lastRequest?.headers["Accept"]

XCTAssertEqual(result, expectedResult)
}

func testPostURLRequestContentTypeHeaderSetToApplicationJSON() async throws {
httpClient.postResult = .success(HTTPResponse())
httpClient.result = .success(HTTPResponse())
let expectedResult = "application/json"
let pathURL = try XCTUnwrap(URL(string: "/object"))

_ = try? await apiClient.post(path: pathURL, body: "adam") as String

let result = httpClient.lastPostHeaders?["Content-Type"]
let result = httpClient.lastRequest?.headers["Content-Type"]

XCTAssertEqual(result, expectedResult)
}

func testPostURLRequestHasCorrectURL() async throws {
httpClient.postResult = .success(HTTPResponse())
httpClient.result = .success(HTTPResponse())
let path = "/object"
let pathURL = try XCTUnwrap(URL(string: path))
let language = "en"
Expand All @@ -186,7 +186,7 @@ final class TMDbAPIClientTests: XCTestCase {

_ = try? await apiClient.post(path: pathURL, body: "adam") as String

let result = httpClient.lastPostURL
let result = httpClient.lastRequest?.url

XCTAssertEqual(result, expectedResult)
}
Expand Down
Loading

0 comments on commit bd95731

Please sign in to comment.