Skip to content

Commit

Permalink
Add docs
Browse files Browse the repository at this point in the history
  • Loading branch information
jasl committed Apr 9, 2016
1 parent 5689e08 commit fcbacbc
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 8 deletions.
13 changes: 13 additions & 0 deletions Sources/Backends/AlamofireBackend.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ internal final class AlamofireCancellableToken: Cancellable {
}
}

/// The backend for Alamofire
public class AlamofireBackend: BackendType {
/// Default Alamofire manager for backend.
public static let defaultManager: Manager = {
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
configuration.HTTPAdditionalHeaders = Manager.defaultHTTPHeaders
Expand All @@ -43,13 +45,21 @@ public class AlamofireBackend: BackendType {
return manager
}()

/// The Alamofire manager.
let manager: Alamofire.Manager
/// Called before starting request.
let willPerformRequest: ((Endpoint, Alamofire.Request) -> ())?
/// Called on Alamofire's response closure.
let didReceiveResponse: ((Endpoint, Alamofire.Response<NSData, NSError>) -> ())?

/// Default memory threshold used when encoding `MultipartFormData`.
private static let MultipartFormDataEncodingMemoryThreshold: UInt64 = 10 * 1024 * 1024
/// Memory threshold used when encoding `MultipartFormData`
let multipartFormDataEncodingMemoryThreshold: UInt64

/**
Constructor of the backend.
*/
public init(manager: Manager = defaultManager,
multipartFormDataEncodingMemoryThreshold: UInt64 = MultipartFormDataEncodingMemoryThreshold,
willPerformRequest: ((Endpoint, Alamofire.Request) -> ())? = nil,
Expand All @@ -60,6 +70,9 @@ public class AlamofireBackend: BackendType {
self.didReceiveResponse = didReceiveResponse
}

/**
Encodes the endpoint to Alamofire's Request and perform it.
*/
public func request(endpoint: Endpoint, completion: Completion) -> Cancellable {
let cancellableToken = AlamofireCancellableToken()

Expand Down
3 changes: 3 additions & 0 deletions Sources/Endpoint.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import Foundation

/// Endpoint is the intermediate representation for a target on requesting
public final class Endpoint {
/// The raw target instance
public let target: TargetType?
/// Set `false` will abort the request
public var willPerform = true

public let URL: NSURL
Expand Down
12 changes: 11 additions & 1 deletion Sources/Error.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
import Foundation

/**
Errors on requesting a target.

- BackendBuildingRequest: Raised on making request object. e.g raised by serializing multipart failure
- BackendResponse: Raised on backend's completion of a request. e.g raised by request timeout
- BackendUnexpect: All other errors raised by backend
- Aborted: Raised by setting `endpoint.willPerform = false`
- Cancelled: Raised by `cancellableToken.cancel()`
= Underlying: Uncategoried errors
*/
public enum Error: ErrorType {
case BackendBuildingRequest(ErrorType)
case BackendResponse(ErrorType)
case BackendUnexpect(ErrorType)
case Abort
case Aborted
case Cancelled
case Underlying(ErrorType)
}
2 changes: 1 addition & 1 deletion Sources/Middlewares/NetworkActivityMiddleware.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public final class NetworkActivityMiddleware: MiddlewareType {
self.networkActivityClosure = networkActivityClosure
}

// MARK: Plugin
// MARK: Middleware

/// Called by the provider as soon as the request is about to start
public func willSendRequest(target: TargetType, endpoint: Endpoint) {
Expand Down
61 changes: 58 additions & 3 deletions Sources/MoyaX.swift
Original file line number Diff line number Diff line change
@@ -1,37 +1,75 @@
import Foundation

/// Closure type for Provider's completion
public typealias Completion = Result<Response, Error> -> ()

/**
HTTP method definitions.
See https://tools.ietf.org/html/rfc7231#section-4.3
*/
public enum HTTPMethod: String {
case OPTIONS, GET, HEAD, POST, PUT, PATCH, DELETE, TRACE, CONNECT
}

/**
Used to specify the way to encoding parameters.

- URL: Encodes parameter to a query string to be set as or appended to any existing URL query for
`GET`, `HEAD`, and `DELETE` requests, or set as the body for requests with any other HTTP method.
The `Content-Type` HTTP header field of an encoded request with HTTP body is set to
`application/x-www-form-urlencoded; charset=utf-8`. Since there is no published specification
for how to encode collection types, the convention of appending `[]` to the key for array
values (`foo[]=1&foo[]=2`), and appending the key surrounded by square brackets for nested
dictionary values (`foo[bar]=baz`).
- MultipartFormData: Encodes parameters to `multipart/form-data` for uploads within an HTTP or HTTPS body.
- JSON: Encodes parameters by using `NSJSONSerialization`, which is set as the body of the request.
The `Content-Type` HTTP header field of an encoded request is set to `application/json`.
*/
public enum ParameterEncoding {
case URL
case MultipartFormData
case JSON
}

// http://www.iana.org/assignments/media-types/media-types.xhtml
/**
Used to create a multipart form data object for parameters.

File name and MIME type is required for all cases.
For information on MIME type, see http://www.iana.org/assignments/media-types/media-types.xhtml

- Data: For NSData
- File: For NSURL of a file
- Stream: For NSInputStream
*/
public enum MultipartFormData {
case Data(NSData, fileName: String, mimeType: String)
case File(NSURL, fileName: String, mimeType: String)
case Stream(NSInputStream, length: UInt64, fileName: String, mimeType: String)
}

/// Protocol to define the base URL, path, method, parameters and sample data for a target.
/// Protocol to define the base URL, path, method, parameters and etc. for a target.
public protocol TargetType {
/// Required
var baseURL: NSURL { get }
/// Required
var path: String { get }
/// Optional, default is `.GET`
var method: HTTPMethod { get }

/// Optional, default is `[:]`
var headerFields: [String: String] { get }

/// Optional, default is `[:]`
var parameters: [String: AnyObject] { get }
/// Optional, default is `.URL`, for multipart uploading, use `.MultipartFormData`
var parameterEncoding: ParameterEncoding { get }

/// Full path of the target, default is equivalent to `baseURL.URLByAppendingPathComponent(path)`,
/// can be overridden for advanced usage
var fullURL: NSURL { get }

/// Returns an endpoint instance computed by the target,
/// can be overridden for advanced usage
var endpoint: Endpoint { get }
}

Expand Down Expand Up @@ -60,22 +98,39 @@ public extension TargetType {
}
}

/// Protocol to define a middleware that can be regiestered to provider
public protocol MiddlewareType {
/**
Will be called before the endpoint be passed to backend.

- Parameters:
- target: The target instance which being requested
- endpoint: The intermediate representation of target, modify it will cause side-effect
*/
func willSendRequest(target: TargetType, endpoint: Endpoint)

/**
Will be called before calling completion closure.

- Parameters:
- target: The target instance which being requested
- response: The result of the request
*/
func didReceiveResponse(target: TargetType, response: Result<Response, Error>)
}


/// Protocol to define a backend which handle transform endpoint to request and perform it.
public protocol BackendType: class {
func request(endpoint: Endpoint, completion: Completion) -> Cancellable
}

/// Protocol to define the opaque type returned from a request
public protocol Cancellable: CustomDebugStringConvertible {
func cancel()
var debugDescription: String { get }
}

/// A fake Cancellable implementation for request which aborted by setting `endpoint.shouldPerform = false`
internal final class AbortingCancellableToken: Cancellable {
func cancel() {}

Expand Down
67 changes: 64 additions & 3 deletions Sources/Provider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@ public class MoyaXProvider {
public let middlewares: [MiddlewareType]
private let prepareForEndpoint: (Endpoint -> ())?

/// Initializes a provider.
/**
Initializes a provider.

- Parameter backend: The backend used to perform request.
- Parameter middlewares: Middlewares will be called on `request` method.
- Parameter prepareForEndpoint: a closure will be called on `request` method, mostly used for modifying endpoint,
e.g: add an authentication header
*/
public init(backend: BackendType = AlamofireBackend(),
middlewares: [MiddlewareType] = [],
prepareForEndpoint: (Endpoint -> ())? = nil) {
Expand All @@ -16,7 +23,28 @@ public class MoyaXProvider {
self.prepareForEndpoint = prepareForEndpoint
}

/// Designated request-making method. Returns a Cancellable token to cancel the request later.
/**
Creates a request for given target and call the completion once the request has finished.

The flow is equivalent to:

let endpoint = target.endpoint
prepareForEndpoint?(endpoint)
middlewares.each { $0.willSendRequest(target, endpoint) }
if endpoint.willPerform {
response = backend.request(endpoint)
} else {
response = .Incomplete(Error.Aborted)
}
middlewares.each { $0.didReceiveResponse(target, response) }
completion(response)

- Parameter target: The target.
- Parameter withCustomBackend: Optional, the backend used to perform request.
- Parameter completion: The handler to be called once the request has finished.

- Returns: The cancellable token for the request.
*/
public final func request(target: TargetType, withCustomBackend backend: BackendType? = nil, completion: Completion) -> Cancellable {
let endpoint = target.endpoint

Expand All @@ -25,7 +53,7 @@ public class MoyaXProvider {
self.middlewares.forEach { $0.willSendRequest(target, endpoint: endpoint) }

guard endpoint.willPerform else {
let error: Result<Response, Error> = .Incomplete(.Abort)
let error: Result<Response, Error> = .Incomplete(.Aborted)
self.middlewares.forEach { $0.didReceiveResponse(target, response: error) }

return AbortingCancellableToken()
Expand All @@ -41,13 +69,46 @@ public class MoyaXProvider {
}
}

/// Request provider class. Requests should be made through this class only.
/// This is the generic provider that convenient for `enum` targets
public class MoyaXGenericProvider<Target: TargetType>: MoyaXProvider {

/**
Initializes a provider.

- Parameter backend: The backend used to perform request.
- Parameter middlewares: Middlewares will be called on `request` method.
- Parameter prepareForEndpoint: a closure will be called on `request` method, mostly used for modifying endpoint,
e.g: add an authentication header
*/
public override init(backend: BackendType = AlamofireBackend(),
middlewares: [MiddlewareType] = [],
prepareForEndpoint: (Endpoint -> ())? = nil) {
super.init(backend: backend, middlewares: middlewares, prepareForEndpoint: prepareForEndpoint)
}

/**
Creates a request for given target and call the completion once the request has finished.

The flow is equivalent to:

let endpoint = target.endpoint
prepareForEndpoint?(endpoint)
middlewares.each { $0.willSendRequest(target, endpoint) }
if endpoint.willPerform {
response = backend.request(endpoint)
} else {
response = .Incomplete(Error.Aborted)
}
middlewares.each { $0.didReceiveResponse(target, response) }
completion(response)

- Parameter target: The target.
- Parameter withCustomBackend: Optional, the backend used to perform request.
- Parameter completion: The handler to be called once the request has finished.

- Returns: The cancellable token for the request.
*/
public func request(target: Target, withCustomBackend backend: BackendType? = nil, completion: Completion) -> Cancellable {
return super.request(target, withCustomBackend: backend, completion: completion)
}
Expand Down
11 changes: 11 additions & 0 deletions Sources/Response.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Foundation

/// Used to store all response data returned from a completed request.
public struct Response: CustomDebugStringConvertible {
public let response: NSURLResponse?

Expand All @@ -25,6 +26,16 @@ public struct Response: CustomDebugStringConvertible {
}
}

/**
The category for response status code

- Informational: status code in 100 to 199
- Success: status code in 200 to 299
- Redirection: status code in 300 to 399
- ClientError: status code in 400 to 499
- ServerError: status code in 500 to 599
- Undefined: other status code
*/
public enum ResponseClass {
case Informational
case Success
Expand Down

0 comments on commit fcbacbc

Please sign in to comment.