Skip to content

Commit

Permalink
OID4VCI Integration (#27)
Browse files Browse the repository at this point in the history
Signed-off-by: Tiago Nascimento <[email protected]>
  • Loading branch information
theosirian authored Sep 11, 2024
1 parent e1e8d12 commit 0c07177
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 3 deletions.
4 changes: 2 additions & 2 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/spruceid/mobile-sdk-rs.git",
"state" : {
"revision" : "e8a1b7056989e4cb471281b464c1aeac298be97f",
"version" : "0.0.29"
"revision" : "b1e729b2adc97415019925c873b976648a2331cb",
"version" : "0.0.30"
}
},
{
Expand Down
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ let package = Package(
targets: ["SpruceIDMobileSdk"])
],
dependencies: [
.package(url: "https://github.com/spruceid/mobile-sdk-rs.git", from: "0.0.29"),
.package(url: "https://github.com/spruceid/mobile-sdk-rs.git", from: "0.0.30"),
// .package(path: "../mobile-sdk-rs"),
.package(url: "https://github.com/apple/swift-algorithms", from: "1.2.0")
],
Expand Down
123 changes: 123 additions & 0 deletions Sources/MobileSdk/OID4VCI.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import Foundation

import SpruceIDMobileSdkRs

public class Oid4vciSyncHttpClient: SyncHttpClient {
public func httpClient(request: HttpRequest) throws -> HttpResponse {
guard let url = URL(string: request.url) else {
throw HttpClientError.Other(error: "failed to construct URL")
}

let session = URLSession.shared
var req = URLRequest(url: url,
cachePolicy: .useProtocolCachePolicy,
timeoutInterval: 60)
req.httpMethod = request.method
req.httpBody = request.body
req.allHTTPHeaderFields = request.headers

// Semaphore used to wait for the callback to complete
let semaphore = DispatchSemaphore(value: 0)

var data: Data?
var response: URLResponse?
var error: Error?

let dataTask = session.dataTask(with: req) {
data = $0
response = $1
error = $2

// Signaling from inside the callback will let the outside function
// know that `data`, `response` and `error` are ready to be read.
semaphore.signal()
}
// Initiate execution of the http request
dataTask.resume()

// Blocking wait for the callback to signal back
_ = semaphore.wait(timeout: .distantFuture)

if let error {
throw HttpClientError.Other(error: "failed to execute request: \(error)")
}

guard let response = response as? HTTPURLResponse else {
throw HttpClientError.Other(error: "failed to parse response")
}

guard let data = data else {
throw HttpClientError.Other(error: "failed to parse response data")
}

guard let statusCode = UInt16(exactly: response.statusCode) else {
throw HttpClientError.Other(error: "failed to parse response status code")
}

let headers = try response.allHeaderFields.map({ (key, value) in
guard let key = key as? String else {
throw HttpClientError.HeaderParse
}

guard let value = value as? String else {
throw HttpClientError.HeaderParse
}

return (key, value)
})

return HttpResponse(
statusCode: statusCode,
headers: Dictionary(uniqueKeysWithValues: headers),
body: data)
}
}

public class Oid4vciAsyncHttpClient: AsyncHttpClient {
public func httpClient(request: HttpRequest) async throws -> HttpResponse {
guard let url = URL(string: request.url) else {
throw HttpClientError.Other(error: "failed to construct URL")
}

let session = URLSession.shared
var req = URLRequest(url: url,
cachePolicy: .useProtocolCachePolicy,
timeoutInterval: 60)
req.httpMethod = request.method
req.httpBody = request.body
req.allHTTPHeaderFields = request.headers

let data: Data
let response: URLResponse
do {
(data, response) = try await session.data(for: req)
} catch {
throw HttpClientError.Other(error: "failed to execute request: \(error)")
}

guard let response = response as? HTTPURLResponse else {
throw HttpClientError.Other(error: "failed to parse response")
}

guard let statusCode = UInt16(exactly: response.statusCode) else {
throw HttpClientError.Other(error: "failed to parse response status code")
}

let headers = try response.allHeaderFields.map({ (key, value) in
guard let key = key as? String else {
throw HttpClientError.HeaderParse
}

guard let value = value as? String else {
throw HttpClientError.HeaderParse
}

return (key, value)
})

return HttpResponse(
statusCode: statusCode,
headers: Dictionary(uniqueKeysWithValues: headers),
body: data)
}
}

0 comments on commit 0c07177

Please sign in to comment.