Skip to content

Latest commit

 

History

History
96 lines (71 loc) · 3.73 KB

ConvenienceParametersAndActualParameters.md

File metadata and controls

96 lines (71 loc) · 3.73 KB

Convenience Parameters and Actual Parameters

To satisfy both ease and accuracy, Request has 2 kind of parameters properties, convenience property and actual properties. If you implement convenience parameters only, actual parameters are computed by default implementation of Request.

  1. Convenience parameters
  2. Actual parameters

Convenience parameters

Most documentations of web APIs express parameters in dictionary-like notation:

Name Type Description
q string The search keywords, as well as any qualifiers.
sort string The sort field. One of stars, forks, or updated. Default: results are sorted by best match.
order string The sort order if sort parameter is provided. One of asc or desc. Default: desc

Request has a property var parameter: Any? to express parameters in this kind of notation. That is the convenience parameters.

struct SomeRequest: Request {
    ...

    var parameters: Any? {
        return [
            "q": "Swift",
            "sort": "stars",
            "order": "desc",
        ]
    }
}

Request provides default implementation of parameters nil.

public extension Request {
    public var parameters: Any? {
        return nil
    }
}

Actual parameters

Actually, we have to translate dictionary-like notation in API docs into HTTP/HTTPS request. There are 2 places to express parameters, URL query and body. Request has interface to express them, var queryParameters: [String: Any]? and var bodyParameters: BodyParameters?. Those are the actual parameters.

If you implement convenience parameters only, the actual parameters are computed from the convenience parameters depending on HTTP method. Here is the default implementation of actual parameters:

public extension Request {
    public var queryParameters: [String: Any]? {
        guard let parameters = parameters as? [String: Any], method.prefersQueryParameters else {
            return nil
        }

        return parameters
    }

    public var bodyParameters: BodyParameters? {
        guard let parameters = parameters, !method.prefersQueryParameters else {
            return nil
        }

        return JSONBodyParameters(JSONObject: parameters)
    }
}

If you implement actual parameters for the HTTP method, the convenience parameters will be ignored.

BodyParameters

There are several MIME types to express parameters such as application/json, application/x-www-form-urlencoded and multipart/form-data; boundary=foobarbaz. Because parameters types to express these MIME types are different, type of bodyParameters is a protocol BodyParameters.

BodyParameters defines 2 components, contentType and buildEntity(). You can create custom body parameters type that conforms to BodyParameters.

public enum RequestBodyEntity {
    case data(Data)
    case inputStream(InputStream)
}

public protocol BodyParameters {
    var contentType: String { get }
    func buildEntity() throws -> RequestBodyEntity
}

APIKit provides 3 body parameters type listed below:

Name Parameters Type
JSONBodyParameters Any
FormURLEncodedBodyParameters [String: Any]
MultipartFormDataBodyParameters [MultipartFormDataBodyParameters.Part]