BothamNetworking

BothamNetworking 是用 Swift 编写的网络框架。
此项目将帮助您轻松设置所有 API 客户端并实现您的网络层。BothamNetworking 提供了类来发送 HTTP 请求并获取等待解析的 HTTP 响应,只需几行代码即可。
此外,
##使用方法
此框架包含实现您的网络层所需的所有类,并通过名为 BothamAPIClient
的易于使用的界面来实现。如果您喜欢 Swift Playgrounds,则可以克隆此项目并查看我们创建的 playgrounds,以了解如何使用此框架。
###使用不同的 HTTP 方法发送请求
let apiClient = BothamAPIClient(baseEndpoint: "https://api.github.com/repos/Karumi/BothamNetworking")
apiClient.GET("/issues")
apiClient.POST("/issues")
apiClient.PUT("/issues")
apiClient.DELETE("/issues/1")
###向请求添加头信息
apiClient.GET("/issues", headers: ["User-Agent": "BothamNetworking Headers", "Accept": "application/json; q=0.5"])
###向请求添加参数
apiClient.DELETE("/issues", parameters: ["id": "1"])
###向请求添加正文
apiClient.POST("/authorizations", body: ["scopes": ["repo_status", "user:email"]])
正文编码将由使用的 HTTP 头信息确定。要使用 json 编码您的正文,请向请求添加一个 "ContentType: application/json" 头信息
###请求执行结果
BothamNetworking 使用由 HTTPResponse
或 BothamAPIClientError
实例组成的 Result
返回类型。我们添加了一个 ResultType
扩展,以便能够通过使用 SwiftyJSON
作为解析库来提供一个易于使用的机制来解析您的响应信息。
apiClient.GET("/repos") { result in
result.mapJSON { json in
for result in json["results"].arrayValue {
let id = result["id"].stringValue
let name = result["name"].stringValue
}
}
}
这是在 HTTPResponse
结构中可用的信息
public struct HTTPResponse {
public let statusCode: Int
public let headers: CaseInsensitiveDictionary<String>?
public let body: NSData
...
}
BothamNetworking 可以返回的错误有
public enum BothamAPIClientError: ErrorType, Equatable {
case HTTPResponseError(statusCode: Int, body: NSData)
case NetworkError
case HTTPClientError(error: NSError)
case ParsingError(error: NSError)
case UnsupportedURLScheme
case Retry
}
###拦截器
BothamRequestInterceptor
和 BothamResponseInterceptor
是两个协议,您可以用它们在发送之前修改 HTTPRequest
实例,或者在接收之前修改 HTTPResponse
。这个机制可以用来实现认证策略,向请求中添加默认信息,添加日志跟踪或重试请求。一个例子可以是 NSLogInterceptor
、JSONHeadersRequestInterceptor
或 BasicAuthentication
。
class JSONHeadersRequestInterceptor: BothamRequestInterceptor {
func intercept(request: HTTPRequest) -> HTTPRequest {
return request.appendingHeaders(["Content-Type": "application/json", "Accept": "application:json"])
}
}
public protocol BasicAuthentication: BothamRequestInterceptor, BothamResponseInterceptor {
var credentials: (username: String, password: String) { get }
func onAuthenticationError(realm: String) -> Void
}
extension BasicAuthentication {
public func intercept(request: HTTPRequest) -> HTTPRequest {
let userPass = "\(credentials.username):\(credentials.password)"
let userPassData = userPass.dataUsingEncoding(NSUTF8StringEncoding)!
let base64UserPass = userPassData.base64EncodedStringWithOptions([])
let header = ["Authorization" : "Basic \(base64UserPass)"]
return request.appendingHeaders(header)
}
public func intercept(response: HTTPResponse,
completion: (Result<HTTPResponse, BothamAPIClientError>) -> Void) {
if response.statusCode == 401, let unauthorizedHeader = response.headers?["WWW-Authenticate"] {
let regex = try! NSRegularExpression(pattern: "Basic realm=\"(.*)\"", options: [])
let range = NSMakeRange(0, unauthorizedHeader.utf8.count)
if let match = regex.firstMatchInString(unauthorizedHeader, options: [], range: range) {
let realm = (unauthorizedHeader as NSString).substringWithRange(match.rangeAtIndex(1))
onAuthenticationError(realm)
}
}
completion(Result.Success(response))
}
}
拦截器可以添加到 BothamAPIClient
实例,或者同时添加到所有的 BothamAPIClient
实例。添加到全局的拦截器将在每个请求之前和之后独立于 BothamAPIClient
实例进行评估。添加到本地的拦截器将仅应用于添加那些拦截器的 BothamAPIClient
实例。
let apiClient = BothamAPIClient(baseEndpoint: "https://api.github.com/repos/Karumi/")
//Add interceptors locally
apiClient.requestInterceptors.append(NSLogInterceptor())
apiClient.responseInterceptors.append(NSLogInterceptor())
//Add interceptors globally
BothamAPIClient.globalRequestInterceptors.append(NSLogInterceptor())
BothamAPIClient.globalResponseInterceptors.append(NSLogInterceptor())
###重试请求
为了能够重试请求,添加一个 BothamResponseInterceptor
,并在需要时返回 BothamAPIClientError.RetryError
。BothamAPIClient
将自动重试您发送的原始请求。
class RetryInterceptor: BothamResponseInterceptor {
func intercept(response: HTTPResponse, completion: (Result<HTTPResponse, BothamAPIClientError>) -> Void) {
if response.statusCode == 401 {
completion(Result.Failure(.RetryError))
} else {
completion(Result.Success(response))
}
}
}
使用此机制时要小心,因为它可以创建无限循环或导致 DDoS 攻击。请记住,您应该始终调用完成回调,以避免破坏 BothamResponseInterceptor
链。
许可协议
版权所有 2016 Karumi
此软件依据 Apache License 2.0(以下简称“协议”)许可;除非在协议许可范围内许可,否则不得使用本软件。您可以在以下地址获取协议副本:
https://apache.ac.cn/licenses/LICENSE-2.0
除非根据适用的法律或书面同意进行分发,否则在协议下分发的软件是基于“现状”和“按原始状态”的,并不提供任何明示或暗示的保证或条件。有关许可协议的权限和限制的具体语言,请参阅该许可。