diff --git a/Sources/SwiftRedis/Redis.swift b/Sources/SwiftRedis/Redis.swift index 0354411..1c6a4d0 100644 --- a/Sources/SwiftRedis/Redis.swift +++ b/Sources/SwiftRedis/Redis.swift @@ -21,19 +21,19 @@ import Foundation /// The `Redis` class represents a handle for issueing commands to a Redis server. /// It provides a set of type safe functions for issueing those commands. public class Redis { - + /// Redis Serialization Protocol handle private var respHandle: RedisResp? - + /// Whether the client is connected or not. /// Does not reflect state changes in the event of a disconnect. public var connected: Bool { return respHandle?.status == .connected } - + /// Initializes a `Redis` instance public init () {} - + /// Connects to a redis server /// /// - Parameter host: the server IP address. @@ -48,40 +48,61 @@ public class Redis { callback(nil) } } - + + /// Disconnects from a redis server + public func disconnect(){ + respHandle?.disconnect() + } + /// Authenticate against the server /// /// - Parameter pswd: String for the password. /// - Parameter callback: callback function that is called after authenticating, /// NSError will be nil if successful. public func auth(_ pswd: String, callback: (NSError?) -> Void) { - + issueCommand("AUTH", pswd) {(response: RedisResponse) in let (_, error) = self.redisOkResponseHandler(response, nilOk: false) callback(error) } } - + + /// Authenticate against the server using a username. (Redis 6+) + /// + /// - Parameter username: String for the username. + /// - Parameter pswd: String for the password. + /// - Parameter callback: callback function that is called after authenticating, + /// NSError will be nil if successful. + public func auth(_ username: String, _ pswd: String, callback: (NSError?) -> Void) { + if username == "" { + return auth(pswd, callback: callback) + } + issueCommand("AUTH", username, pswd) {(response: RedisResponse) in + let (_, error) = self.redisOkResponseHandler(response, nilOk: false) + callback(error) + } + } + /// Select the database to use /// /// - Parameter db: numeric index for the database. /// - Parameter callback: callback function for after the database is selected, /// NSError will be nil if successful. public func select(_ db: Int, callback: (NSError?) -> Void) { - + issueCommand("SELECT", String(db)) {(response: RedisResponse) in let (_, error) = self.redisOkResponseHandler(response, nilOk: false) callback(error) } } - + /// Ping the server to test if a connection is still alive /// /// - Parameter pingStr: String for the ping message. /// - Parameter callback: callback function for after the pong is received, /// NSError will be nil if successful. public func ping(_ pingStr: String?=nil, callback: (NSError?) -> Void) { - + var command = ["PING"] if let pingStr = pingStr { command.append(pingStr) @@ -107,19 +128,19 @@ public class Redis { } } } - + /// Echos a message /// /// - Parameter str: String for the message. /// - Parameter callback: callback function with the String echoed back, /// NSError will be nil if successful. public func echo(_ str: String, callback: (RedisString?, NSError?) -> Void) { - + issueCommand("ECHO", str) {(response: RedisResponse) in self.redisStringResponseHandler(response, callback: callback) } } - + /// Get information and statistics about the server /// /// - Parameter callback: callback function with the response as a collection of text @@ -129,7 +150,7 @@ public class Redis { self.redisStringResponseHandler(response, callback: callback) } } - + /// Get information and statistics about the server /// /// - Parameter callback: callback function with the response as a struct @@ -140,7 +161,7 @@ public class Redis { self.redisDictionaryResponseHandler(response, callback: callback) } } - + /// Delete all the keys of the currently selected DB. This command never fails. /// /// - Parameter callback: a function returning the response, @@ -151,22 +172,22 @@ public class Redis { callback(ok, _: error) } } - - + + // // MARK: Transaction support // - + /// Create a `RedisMulti` object in order to perform a Redis transaction public func multi() -> RedisMulti { return RedisMulti(redis: self) } - - + + // // MARK: Base API functions // - + /// Issue a Redis command /// /// - Parameter stringArgs: A list of Strings making up the Redis command to issue @@ -174,7 +195,7 @@ public class Redis { public func issueCommand(_ stringArgs: String..., callback: (RedisResponse) -> Void) { issueCommandInArray(stringArgs, callback: callback) } - + /// Issue a Redis command /// /// - Parameter stringArgs: An array of Strings making up the Redis command to issue @@ -184,15 +205,15 @@ public class Redis { callback(RedisResponse.Error("Not connected to Redis server")) return } - + guard stringArgs.count > 0 else { callback(RedisResponse.Error("Empty command")) return } - + respHandle.issueCommand(stringArgs, callback: callback) } - + /// Issue a Redis command /// /// - Parameter stringArgs: A list of `RedisString` objects making up the Redis command to issue @@ -200,7 +221,7 @@ public class Redis { public func issueCommand(_ stringArgs: RedisString..., callback: (RedisResponse) -> Void) { issueCommandInArray(stringArgs, callback: callback) } - + /// Issue a Redis command /// /// - Parameter stringArgs: An array of `RedisString` objects making up the Redis command to issue @@ -210,19 +231,19 @@ public class Redis { callback(RedisResponse.Error("Not connected to Redis server")) return } - + guard stringArgs.count > 0 else { callback(RedisResponse.Error("Empty command")) return } - + respHandle.issueCommand(stringArgs, callback: callback) } - + // // MARK: Helper functions // - + func redisBoolResponseHandler(_ response: RedisResponse, callback: (Bool, NSError?) -> Void) { switch(response) { case .IntegerValue(let num): @@ -237,7 +258,7 @@ public class Redis { callback(false, _: createUnexpectedResponseError(response)) } } - + func redisIntegerResponseHandler(_ response: RedisResponse, callback: (Int?, NSError?) -> Void) { switch(response) { case .IntegerValue(let num): @@ -250,7 +271,7 @@ public class Redis { callback(nil, _: createUnexpectedResponseError(response)) } } - + func redisOkResponseHandler(_ response: RedisResponse, nilOk: Bool=true) -> (Bool, NSError?) { switch(response) { case .Status(let str): @@ -267,7 +288,7 @@ public class Redis { return (false, createUnexpectedResponseError(response)) } } - + func redisSimpleStringResponseHandler(response: RedisResponse, callback: (String?, NSError?) -> Void) { switch(response) { case .Status(let str): @@ -280,7 +301,7 @@ public class Redis { callback(nil, _: createUnexpectedResponseError(response)) } } - + func redisStringResponseHandler(_ response: RedisResponse, callback: (RedisString?, NSError?) -> Void) { switch(response) { case .StringValue(let str): @@ -293,11 +314,11 @@ public class Redis { callback(nil, _: createUnexpectedResponseError(response)) } } - + func redisArrayResponseHandler(response: RedisResponse, callback: ([RedisResponse?]?, NSError?) -> Void) { var error: NSError? = nil var result: [RedisResponse?]? - + switch(response) { case .Array(let responses): result = responses @@ -310,7 +331,7 @@ public class Redis { } callback(error == nil ? result : nil, _: error) } - + func getCoordinates(from responses: [RedisResponse?]?, callback: ([(Double, Double)?]?, NSError?) -> Void) { guard let responses = responses else { callback(nil, createError("Could not get coordinates from nil response.", code: 1)) @@ -332,11 +353,11 @@ public class Redis { } callback(result, nil) } - + func redisStringArrayResponseHandler(_ response: RedisResponse, callback: ([RedisString?]?, NSError?) -> Void) { var error: NSError? = nil var result: [RedisString?]? - + switch(response) { case .Array(let responses): var strings = [RedisString?]() @@ -360,11 +381,11 @@ public class Redis { } callback(error == nil ? result : nil, _: error) } - + func redisStringArrayOrIntegerResponseHandler(_ response: RedisResponse, callback: ([RedisString?]?, NSError?) -> Void) { var error: NSError? = nil var result: [RedisString?]? - + switch(response) { case .Array(let responses): var strings = [RedisString?]() @@ -390,12 +411,12 @@ public class Redis { } callback(error == nil ? result : nil, _: error) } - + func redisScanResponseHandler(_ response: RedisResponse, callback: (RedisString?, [RedisString?]?, NSError?) -> Void) { var error: NSError? = nil var cursor: RedisString? var result: [RedisString?]? - + switch(response) { case .Array(let responses): var strings = [RedisString?]() @@ -426,14 +447,14 @@ public class Redis { default: error = self.createUnexpectedResponseError(response) } - + if(error == nil) { callback(cursor, result, nil) } else { callback(nil, nil, error) } } - + func redisDictionaryResponseHandler(_ response: RedisResponse, callback: (RedisInfo?, NSError?) -> Void) { switch(response) { case .StringValue(let str): @@ -446,11 +467,11 @@ public class Redis { callback(nil, _: createUnexpectedResponseError(response)) } } - + func createUnexpectedResponseError(_ response: RedisResponse) -> NSError { return createError("Unexpected result received from Redis \(response)", code: 2) } - + func createError(_ errorMessage: String, code: Int) -> NSError { #if os(Linux) let userInfo: [String: Any] @@ -460,7 +481,7 @@ public class Redis { userInfo = [NSLocalizedDescriptionKey: errorMessage] return NSError(domain: "RedisDomain", code: code, userInfo: userInfo) } - + func createRedisError(_ redisError: String) -> NSError { return createError(redisError, code: 1) } diff --git a/Sources/SwiftRedis/RedisResp.swift b/Sources/SwiftRedis/RedisResp.swift index 9cdd9cf..c47c29a 100644 --- a/Sources/SwiftRedis/RedisResp.swift +++ b/Sources/SwiftRedis/RedisResp.swift @@ -22,7 +22,7 @@ enum RedisRespStatus { case connected } -class RedisResp { +public class RedisResp { /// /// Socket used to talk with the server private var socket: Socket? @@ -46,6 +46,10 @@ class RedisResp { try? socket?.connect(to: host, port: port) } + func disconnect(){ + socket?.close() + } + func issueCommand(_ stringArgs: [String], callback: (RedisResponse) -> Void) { guard let socket = socket else { return }