CocoaPods trunk is moving to be read-only. Read more on the blog, there are 18 months to go.
TestsTested | ✓ |
LangLanguage | SwiftSwift |
License | MIT |
ReleasedLast Release | Apr 2017 |
SwiftSwift Version | 3.0 |
SPMSupports SPM | ✓ |
Maintained by Evan Liu.
Depends on: | |
Alamofire | ~> 4.4 |
Result | ~> 3.2 |
WebAPIKit is a network abstraction layer to build web API clients.
final class GitHubAPI: WebAPIProvider {
let baseURL = URL(string: "https://api.github.com")!
func getUser(login: String, handler: @escaping ResultHandler) {
makeRequest(path: "/users/\(login)").send(handler: handler)
}
}
GitHubAPI().getUser(login: "WebAPIKit") {
if case .success(let response) = $0, response.status.isSuccess {
// Read from response.data and/or response.headers
}
}
(Using Marshal for json parsing here but you can use any library as your choice)
struct User: ResponseJSONData {
var login: String
var name: String?
init(json: [String: Any]) throws {
login = try json.value(for: "login")
name = try json.value(for: "name")
}
}
extension GitHubAPI {
func getUser(login: String, handler: @escaping (Result<User, WebAPIError>) -> Void) {
makeRequest(path: "/users/\(login)").sendAndDecode(handler: handler)
}
}
GitHubAPI().getUser(login: "WebAPIKit") {
if case .success(let user) = $0 {
// user is of type User
}
}
final class GitHubAPI: WebAPIProvider {
let baseURL = URL(string: "https://api.github.com")!
let plugins = PluginHub()
.addRequestProcessor(RequestHeaderSetter(key: .accept, value: "application/vnd.github.v3+json"))
.addResponseProcessor(ResponseStatusValidator())
}
Requests can also have their own plugins:
extension GitHubAPI {
func getUser(login: String, handler: @escaping ResultHandler) {
makeRequest(path: "/users/\(login)").addPlugin(MyRequestHook()).send(handler: handler)
}
}
final class MyServerAPI: WebAPIProvider {
let baseURL = URL(string: "https://my-server.com/api/v1")!
let requireAuthentication = true
var authentication: WebAPIAuthentication = NoneAuthentication()
}
class MyLoginController {
func login(user: String, password: String) {
myServer.authentication = BasicAuthentication(user: user, password: password)
}
}
Requests will not be sent if requireAuthentication
is true but there is no valid authentication. Except some endpoints may not require authentication.
extension MyServerAPI {
func sayHi(message: String, handler: @escaping ResultHandler) {
makeRequest(path: "/hi", method: .post)
.addParameter(key: "message", value: message)
.setRequireAuthentication(false)
.send(handler: handler)
}
}
final class GitHubAPI: StubbableProvider {
let baseURL = URL(string: "https://api.github.com")!
var httpClient: HTTPClient? // Use Alamofire.SessionManager.default if not defined
}
// Stub for development
class SomeBusyClass {
fucn someMethod() {
let client = gitHub.stubClient()
client.stub(path: "/users", method: .post).withStatus(.code201)
client.stub(template: "/users/{login}").withTemplatedJSON { ["login": $0["login"]!, "name": "User"] }
client.stub().withStatus(.code404) // All other requests will fail with 404
}
}
// Stub for testing
class SomeTestCase {
func testSomeMethod() {
// ... After stub setup
client.stub(path: "/users").withJSON([["login": "test", "name": "Tester"]])
client.stub(path: "/users", method: .post).withStatus(.code201).withMode(.manual)
// ... After some method calls
XCTAssertTrue(client.hasConnection)
client.lastConnection!.respond() // For POST /users. GET /users will respond with json data automatically
// ... Verify success behaviour
XCTAssertFalse(client.hasActiveConnection) // No connection that is not yet responded to or canceled
}
}
extension GitHubAPI {
func getUser(login: String, handler: @escaping ResultHandler) -> Cancelable {
return makeRequest(path: "/users/\(login)").send(handler: handler)
}
}
class SomeClass {
func someMethod() {
let connection = gitHub.getUser(login: "WebAPIKit") { ... }
// No longer needed now
connection.cancel()
}
}
WebAPIKit is still working in progress.
Before Release:
Furture versions (or extension libraries):