diff options
author | Finn Behrens <me@kloenk.dev> | 2021-09-29 10:26:02 +0200 |
---|---|---|
committer | Finn Behrens <me@kloenk.dev> | 2021-09-29 10:26:02 +0200 |
commit | bcef3014398f4a941ec87c15344905a10b9a6130 (patch) | |
tree | b1f8833a55ff4b842747023ac85f42333ab28dc2 | |
parent | 5ded103c98e35dbfe450099b3be7f53f177e221a (diff) | |
download | MatrixCore-bcef3014398f4a941ec87c15344905a10b9a6130.tar.gz MatrixCore-bcef3014398f4a941ec87c15344905a10b9a6130.tar.xz MatrixCore-bcef3014398f4a941ec87c15344905a10b9a6130.zip |
MatrixRequest and Response protocol
Signed-off-by: Finn Behrens <me@kloenk.dev>
-rw-r--r-- | Sources/MatrixClient/API/HomeServer.swift (renamed from Sources/MatrixClient/HomeServer.swift) | 39 | ||||
-rw-r--r-- | Sources/MatrixClient/API/Request.swift | 67 | ||||
-rw-r--r-- | Sources/MatrixClient/MatrixClient.swift | 4 |
3 files changed, 105 insertions, 5 deletions
diff --git a/Sources/MatrixClient/HomeServer.swift b/Sources/MatrixClient/API/HomeServer.swift index 64b44b0..db8a853 100644 --- a/Sources/MatrixClient/HomeServer.swift +++ b/Sources/MatrixClient/API/HomeServer.swift @@ -21,9 +21,29 @@ public struct MatrixHomeserver: Codable { self.url = components } + + public func path(_ path: String) -> URLComponents { + var components = url + components.path = path + return components; + } +} + +public struct MatrixServerInfoRequest: MatrixRequest { + public typealias Response = MatrixServerInfo + + public typealias URLParameters = () + + public func path(with parameters: ()) -> String { + return "/_matrix/client/versions" + } + + public static var httpMethod = "GET" + + public static var requiresAuth = false } -public struct MatrixServerInfo: Codable { +public struct MatrixServerInfo: MatrixResponse { /// The supported versions. public var versions: [String] @@ -37,7 +57,21 @@ public struct MatrixServerInfo: Codable { } } -public struct MatrixWellKnown { +public struct MatrixWellKnownRequest: MatrixRequest { + public typealias Response = MatrixWellKnown + + public typealias URLParameters = () + + public func path(with parameters: ()) -> String { + return "/.well-known/matrix/client" + } + + public static var httpMethod = "GET" + + public static var requiresAuth = false +} + +public struct MatrixWellKnown: MatrixResponse { /// Used by clients to discover homeserver information. public var homeserver: ServerInformation? @@ -67,7 +101,6 @@ public struct MatrixWellKnown { } } -// TODO: encode for extraInfos extension MatrixWellKnown: Codable { private enum KnownCodingKeys: String, CodingKey, CaseIterable { case homeserver = "m.homeserver" diff --git a/Sources/MatrixClient/API/Request.swift b/Sources/MatrixClient/API/Request.swift new file mode 100644 index 0000000..1f2cc0d --- /dev/null +++ b/Sources/MatrixClient/API/Request.swift @@ -0,0 +1,67 @@ +// +// File.swift +// File +// +// Created by Finn Behrens on 29.09.21. +// + +import Foundation + +public protocol MatrixRequest: Codable { + associatedtype Response: MatrixResponse + + associatedtype URLParameters + func path(with parameters: URLParameters) -> String + + static var httpMethod: String { get } + static var requiresAuth: Bool { get } + // TODO: rate limited property? +} + +public extension MatrixRequest { + func request(on homeserver: MatrixHomeserver, withToken token: String? = nil, with parameters: URLParameters) throws -> URLRequest { + let components = homeserver.path(self.path(with: parameters)) + // components.queryItems = self.queryParameters + + var urlRequest = URLRequest(url: components.url!) + + if Self.requiresAuth { + guard let token = token else { + throw MatrixError.Forbidden + } + urlRequest.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization") + } + + urlRequest.httpMethod = Self.httpMethod + if ["POST", "PUT", "PATCH"].contains(Self.httpMethod) { + urlRequest.httpBody = try? JSONEncoder().encode(self) + } + + return urlRequest + } + + func repsonse(on homeserver: MatrixHomeserver, withToken token: String? = nil, with parameters: URLParameters, withUrlSession urlSession: URLSession = URLSession.shared) async throws -> Response { + let request = try request(on: homeserver, withToken: token, with: parameters) + + let (data, urlResponse) = try await urlSession.data(for: request) + + guard let response = urlResponse as? HTTPURLResponse else { + throw MatrixError.Unknown + } + guard response.statusCode == 200 else { + throw try MatrixServerError(json: data, code: response.statusCode) + } + + return try Response(fromMatrixRequestData: data) + } +} + +public protocol MatrixResponse: Codable { +} + +public extension MatrixResponse { + init(fromMatrixRequestData data: Data) throws { + let decoder = JSONDecoder() + self = try decoder.decode(Self.self, from: data) + } +} diff --git a/Sources/MatrixClient/MatrixClient.swift b/Sources/MatrixClient/MatrixClient.swift index 9e0a493..32bcd8b 100644 --- a/Sources/MatrixClient/MatrixClient.swift +++ b/Sources/MatrixClient/MatrixClient.swift @@ -33,7 +33,7 @@ public struct MatrixClient { /// Requires auth: No. /// ``` public func getVersions() async throws -> MatrixServerInfo { - return try await request("/_matrix/client/versions", withAuthorization: false, forType: MatrixServerInfo.self) + return try await MatrixServerInfoRequest().repsonse(on: homeserver, with: (), withUrlSession: urlSession) } /// Gets discovery information about the domain. The file may include additional keys, which MUST follow the Java package naming convention, @@ -46,7 +46,7 @@ public struct MatrixClient { /// Requires auth: No. ///``` public func getWellKnown() async throws -> MatrixWellKnown { - return try await request("/.well-known/matrix/client", withAuthorization: false, forType: MatrixWellKnown.self) + return try await MatrixWellKnownRequest().repsonse(on: homeserver, with: (), withUrlSession: urlSession) } /// Gets the homeserver's supported login types to authenticate users. Clients should pick one of these and supply it as the type when logging in. |