source/UberRides/EndpointsManager.swift (311 lines of code) (raw):
//
// EndpointsManager.swift
// UberRides
//
// Copyright © 2015 Uber Technologies, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import CoreLocation
import UberCore
/// Convenience enum for managing versions of resources.
private enum Resources: String {
case estimates = "estimates"
case history = "history"
case me = "me"
case paymentMethod = "payment-methods"
case places = "places"
case products = "products"
case request = "requests"
private var version: String {
switch self {
case .estimates: return "v1.2"
case .history: return "v1.2"
case .me: return "v1.2"
case .paymentMethod: return "v1.2"
case .places: return "v1.2"
case .products: return "v1.2"
case .request: return "v1.2"
}
}
fileprivate var basePath: String {
return "/\(version)/\(rawValue)"
}
}
/**
Endpoints related to components.
- RideRequestWidget: Ride Request Widget endpoint.
- Warning: The Ride Request Widget is deprecated, and will no longer work for new apps.
Existing apps have until 05/31/2018 to migrate. See the Uber API Changelog for more details.
*/
enum Components: APIEndpoint {
case rideRequestWidget(rideParameters: RideParameters?)
var method: UberHTTPMethod {
switch self {
case .rideRequestWidget:
return .get
}
}
var host: String {
return "https://components.uber.com"
}
var path: String {
switch self {
case .rideRequestWidget:
return "/rides/"
}
}
var query: [URLQueryItem] {
switch self {
case .rideRequestWidget(let rideParameters):
let environment = Configuration.shared.isSandbox ? "sandbox" : "production"
var queryItems = queryBuilder( ("env", "\(environment)") )
if let rideParameters = rideParameters {
queryItems.append(contentsOf: RequestURLUtil.buildRequestQueryParameters(rideParameters))
}
return queryItems
}
}
}
/**
API endpoints for the Products resource.
- GetAll: Returns information about the Uber products offered at a given location (lat, long).
- GetProduct: Returns information about the Uber product specified by product ID.
*/
enum Products: APIEndpoint {
case getAll(location: CLLocation)
case getProduct(productID: String)
var method: UberHTTPMethod {
switch self {
case .getAll:
fallthrough
case .getProduct:
return .get
}
}
var path: String {
switch self {
case .getAll:
return Resources.products.basePath
case .getProduct(let productID):
return "\(Resources.products.basePath)/\(productID)"
}
}
var query: [URLQueryItem] {
switch self {
case .getAll(let location):
return queryBuilder(
("latitude", "\(location.coordinate.latitude)"),
("longitude", "\(location.coordinate.longitude)"))
case .getProduct:
return queryBuilder()
}
}
}
/**
API Endpoints for the Estimates resource.
- Price: Returns an estimated range for each product offered between two locations (lat, long).
- Time: Returns ETAs for all products offered at a given location (lat, long).
*/
enum Estimates: APIEndpoint {
case price(startLocation: CLLocation, endLocation: CLLocation)
case time(location: CLLocation, productID: String?)
var method: UberHTTPMethod {
switch self {
case .price:
fallthrough
case .time:
return .get
}
}
var path: String {
switch self {
case .price:
return "\(Resources.estimates.basePath)/price"
case .time:
return "\(Resources.estimates.basePath)/time"
}
}
var query: [URLQueryItem] {
switch self {
case .price(let startLocation, let endLocation):
return queryBuilder(
("start_latitude", "\(startLocation.coordinate.latitude)"),
("start_longitude", "\(startLocation.coordinate.longitude)"),
("end_latitude", "\(endLocation.coordinate.latitude)"),
("end_longitude", "\(endLocation.coordinate.longitude)"))
case .time(let location, let productID):
return queryBuilder(
("start_latitude", "\(location.coordinate.latitude)"),
("start_longitude", "\(location.coordinate.longitude)"),
("product_id", productID == nil ? "" : "\(productID!)"))
}
}
}
/**
API Endpoints for the History v1.2 resource.
- Get: Returns limited data about a user's lifetime activity with Uber.
*/
enum History: APIEndpoint {
case get(offset: Int?, limit: Int?)
var method: UberHTTPMethod {
switch self {
case .get:
return .get
}
}
var path: String {
switch self {
case .get:
return Resources.history.basePath
}
}
var query: [URLQueryItem] {
switch self {
case .get(let offset, let limit):
return queryBuilder(
("offset", offset == nil ? "" : "\(offset!)"),
("limit", limit == nil ? "" : "\(limit!)"))
}
}
}
/**
API Endpoints for the Me resource.
- UserProfile: Returns information about the Uber user that has authorized the application.
*/
enum Me: APIEndpoint {
case userProfile
var method: UberHTTPMethod {
switch self {
case .userProfile:
return .get
}
}
var path: String {
switch self {
case .userProfile:
return Resources.me.basePath
}
}
var query: [URLQueryItem] {
switch self {
case .userProfile:
return queryBuilder()
}
}
}
/**
API endpoints for the Requests resource.
- Make: Request a ride on behalf of Uber user.
- GetCurrent: Returns real-time details for an ongoing trip.
- GetRequest: Get the status of an ongoing or completed trip that was created using the Ride Request endpoint.
- Estimate: Gets an estimate for a ride given the desired product, start, and end locations.
*/
enum Requests: APIEndpoint {
case deleteCurrent
case deleteRequest(requestID: String)
case estimate(rideParameters: RideParameters)
case getCurrent
case getRequest(requestID: String)
case make(rideParameters: RideParameters)
case patchCurrent(rideParameters: RideParameters)
case patchRequest(requestID: String, rideParameters: RideParameters)
case rideMap(requestID: String)
case rideReceipt(requestID: String)
var body: Data? {
switch self {
case .deleteCurrent:
fallthrough
case .deleteRequest:
return nil
case .estimate(let rideParameters):
return RideRequestDataBuilder(rideParameters: rideParameters).build()
case .getCurrent:
fallthrough
case .getRequest:
return nil
case .make(let rideParameters):
return RideRequestDataBuilder(rideParameters: rideParameters).build()
case .patchCurrent(let rideParameters):
return RideRequestDataBuilder(rideParameters: rideParameters).build()
case .patchRequest(_, let rideParameters):
return RideRequestDataBuilder(rideParameters: rideParameters).build()
case .rideMap:
return nil
case .rideReceipt:
return nil
}
}
var headers: [String : String]? {
return ["Content-Type": "application/json"]
}
var method: UberHTTPMethod {
switch self {
case .deleteCurrent:
fallthrough
case .deleteRequest:
return .delete
case .estimate:
return .post
case .getCurrent:
fallthrough
case .getRequest:
return .get
case .make:
return .post
case .patchCurrent:
fallthrough
case .patchRequest:
return .patch
case .rideMap:
return .get
case .rideReceipt:
return .get
}
}
var path: String {
switch self {
case .deleteCurrent:
return "\(Resources.request.basePath)/current"
case .deleteRequest(let requestID):
return "\(Resources.request.basePath)/\(requestID)"
case .estimate:
return "\(Resources.request.basePath)/estimate"
case .getCurrent:
return "\(Resources.request.basePath)/current"
case .getRequest(let requestID):
return "\(Resources.request.basePath)/\(requestID)"
case .make:
return Resources.request.basePath
case .patchCurrent:
return "\(Resources.request.basePath)/current"
case .patchRequest(let requestID, _):
return "\(Resources.request.basePath)/\(requestID)"
case .rideMap(let requestID):
return "\(Resources.request.basePath)/\(requestID)/map"
case .rideReceipt(let requestID):
return "\(Resources.request.basePath)/\(requestID)/receipt"
}
}
var query: [URLQueryItem] {
return []
}
}
enum Payment: APIEndpoint {
case getMethods
var body: Data? {
return nil
}
var method: UberHTTPMethod {
return .get
}
var path: String {
return Resources.paymentMethod.basePath
}
var query: [URLQueryItem] {
return []
}
}
enum Places: APIEndpoint {
case getPlace(placeID: String)
case putPlace(placeID: String, address: String)
var body: Data? {
switch self {
case .getPlace:
return nil
case .putPlace(_, let address):
do {
let data = try JSONSerialization.data(withJSONObject: ["address": address], options: [])
return data
} catch { }
return nil
}
}
var headers: [String : String]? {
switch self {
case .getPlace:
return nil
case .putPlace:
return ["Content-Type": "application/json"]
}
}
var method: UberHTTPMethod {
switch self {
case .getPlace:
return .get
case .putPlace:
return .put
}
}
var path: String {
switch self {
case .getPlace(let placeID):
return "\(Resources.places.basePath)/\(placeID)"
case .putPlace(let placeID, _):
return "\(Resources.places.basePath)/\(placeID)"
}
}
var query: [URLQueryItem] {
return []
}
}