TestsTested | ✗ |
LangLanguage | SwiftSwift |
License | Apache 2 |
ReleasedLast Release | Mar 2019 |
SPMSupports SPM | ✗ |
Maintained by Edison Santiago.
Depends on: | |
SwiftHTTP | >= 0 |
Locksmith | >= 0 |
PKHUD | >= 0 |
Neorequest is a simple wrapper around SwiftHTTP with some extras features and providing a cleaner syntax by decoupling error and sucess handling.
Neorequest
is available through CocoaPods. Just add pod 'Neorequest'
to your Podfile and run pod install
All responses are automatically parsed to an object using the 'Decodable' protocol. Making a request with Neorequest is as simple as:
Neorequest<Object>.GET(
url: "https://yoururl.com",
onError: {
error in
//Handle request error here
},
onSuccess: {
obj in
//Handle success response here
}
)
You can simply pass a Dictionary<String: Any>
to the parameters
property with the data you want to send.
Neorequest<Object>.POST(
url: "https://yoururl.com",
parameters: ["name": "John Doe", "age": 7],
onError: {
error in
//Handle request error here
},
onSuccess: {
obj in
//Handle success response here
}
)
For uploading files you can refer to the Swift HTTP Upload and simply pass the Upload
object as a parameter. To learn how to send a x-www-form-urlencoded request please refer to the NeorequestConfiguration
section of this file.
onSuccess((T) -> Void)
receives the parsed object specified on the call. All objects are created using the Decodable
protocol, so make sure you conform to the protocol.
If the response is an empty object ({}
) or an empty response you can provide an empty object as the generic parameter. For convenience, Neorequest
provides a NeorequestEmptyResponse
out of the box for those cases.
For information about configuring the JSONDecoder
to set the dateFormat and other options please refer to the NeorequestConfiguration
section of this file.
You can retrieve the values for the response values the same way you do with any Dictionary:
Neorequest<Object>.GET(
url: "https://yoururl.com",
onError: {
error in
//Handle request error here
},
onSuccess: {
obj in
//The object is already created an ready for use. No need to parsing.
print(obj.name)
}
)
Please note that the response is always parsed to an object using the Swift 4 Decodable
Protocol. If an error is thrown during the parsing the onError((Error) -> Void)
closure will be called with an error NeorequestError.ParseError(content: String?)
, where content is a conversion of the original Data
received to an UTF8 String
.
Arrays on first level are supported by Neorequest
. Since the Swift 4 Decodable
makes an array of Decodable
conformant to Decodable
by default all you have to do is pass an array as the call parameter. Please note that a single object is not convertible to an array and vice versa, so passing the wrong type will result in a parse error.
Neorequest<[Object]>.GET(
url: "https://yoururl.com",
onError: {
error in
//Handle request error here
},
onSuccess: {
objects in
for object in objects {
//Do something with the objects of the array
print(object.name)
}
}
)
If you must include a custom HTTP header in all the requests made on your app you can simply add it to Neorequest.globalHeaders: [String:String]
.
import Neorequest
//The globalHeaders are saved on NSUserDefaults, so you must retrieve the array to edit it
var globalHeaders = Neorequest<Object>.globalHeaders
globalHeaders["Header"] = "Value"
Neorequest<Object>.globalHeaders = globalHeaders
Do not set the Authorization HTTP header here if you are using NeorequestAuthorization.
The NeorequestConfiguration
struct let you set some specific configurations of the request. We put this parameters on a separate struct so the main request call doesn't get bloated with parameters that won't be used all the time.
Please note that all requests has an associated NeorequestConfiguration
with it. If no configuration object is passed one with the default values specified below is created.
loadingType: NeorequestLoadingType
: A enum telling if we should show a loading on the desired view along the request. You can show a fullScreen
loading or an overScreen
loading, as specified below. The default value is none and no loading is shown unless specified.
fullScreen(loadingViewController: UIViewController, loadingIconColor: UIColor?)
: A overlay view is created on top of all UIViewController
views with the same backgroundColor as the viewController.view
and with an UIActivityIndicator
centered and with the desired color.overScreen
: We rely on PKHUD to show a loading over the entire app when this mode is set. Since PKHUD
uses UIWindow there's no need to a reference of the UIViewController
to display the loading.numberOfRetries: Int
: How many times the request should fail before calling the error handler. Default: 1isJsonRequest: Bool
: Specify if the request must not be sent as json. If set to false we sent the request as x-www-form-urlencoded (but the response is always treated as json). Default: trueprogress: ((Float) -> Void)?
: The progress closure to be set on the original Request. For more information on this please refer to the SwiftHTTP Documentation. Default: nilonOperationCreated: ((HTTP) -> Void)?
: A closure called with the original Operation object after it's creation if you want to use NSOperationQueue
. Default: niljsonDecoderConfigurationHandler: ((JSONDecoder) -> JSONDecoder)
: A closure for configuring the decoder used by Swift Decodable
Protocol to create the object.import Neorequest
var config = NeorequestConfiguration()
config.loadingType = .fullScreen(
loadingViewController: myViewController,
loadingIconColor: UIColor.lightGray
)
Neorequest<Object>.GET(
url: "https://yoururl.com",
configuration: config,
onError: {
error in
//Handle request error here
},
onSuccess: {
obj in
//Handle success response here
}
)
import Neorequest
var config = NeorequestConfiguration()
config.isJsonRequest = false
config.numberOfRetries = 10
config.loadingType = .overScreen
Neorequest<Object>.GET(
url: "https://yoururl.com",
configuration: config,
onError: {
error in
//Handle request error here
},
onSuccess: {
obj in
//Handle success response here
}
)
import Neorequest
var config = NeorequestConfiguration()
config.jsonDecoderConfigurationHandler = {
decoder in
let dateFmt = DateFormatter()
dateFmt.locale = Locale.current
dateFmt.timeZone = TimeZone(identifier: "UTC")
dateFmt.dateFormat = "yyyy-MM-dd'T'HH:mm"
decoder.dateDecodingStrategy = .formatted(dateFmt)
return decoder
}
Neorequest<Object>.GET(
url: "https://yoururl.com",
configuration: config,
onError: {
error in
//Handle request error here
},
onSuccess: {
obj in
//Handle success response here
}
)
NeorequestAuthorization
is a singleton class that provides a simple way to manage the authorization of all the requests across the entire app. It handles the token expiration and regeneration for you, so you don't need to worry if the token is still valid or not before making a request. If needed, they will be regenerated before the request proceeds.
The NeorequestAuthorization
data is used by default on all HTTP requests made after the values are saved. If you need to make a call where the authorization must not be used (i.e., the authentication request) you can specify it with authorization: nil
on the request call.
Neorequest<Object>.POST(
url: "https://yoururl.com",
authorization: nil,
parameters: ["name": "John Doe", "age": 7],
onError: {
error in
//Handle request error here
},
onSuccess: {
obj in
//Handle success response here
}
)
NeorequestAuthorization
has some properties to hold the values used on the authorization. All the data is saved only on the iOS Keychain, using Locksmith, so the user sensitive information can be kept secure.
authType
: We support bearer
authorization, basic auth
and also a custom
authorization method where you must provide the tokenString generation. Default: NeorequestAuthorizationType.beareraccount: String?, password: String?
: Save the authentication info only once so you can retrieve it anytime during the token generation process. Default: niltokenString: String? | tokenExpirationDate: Date? | tokenUsageTime: TimeInterval
: Manage the token regeneration. The token is only regenerated when needed, and in .bearer
mode the class manage this by itself and knows when to regenerate the token. The default tokenUsageTime is 1800.While NeorequestAuthorization
manages a lot of stuff automatically, you need to set some closures with some specific logic for you app if you are using .bearer
or .custom
auth.
NeorequestAuthorization.regenerateBearerTokenHandler((NeorequestAuthorization, onError: ((NeorequestError) -> Void), onSuccess: (() -> Void)) -> Void)
NeorequestAuthorization
object passed to it contains all the info you previously saved, so you can retrieve then now. Please remember that this method can be called during other requests, so always calls the received closures onError
and onSucess
to make sure that the other request can continue.401 Not Authorized
, you can get in a loop if you try to make a request with bad authentication data. Because of this, the user data will not be saved automatically, and you should call .save()
when you are sure that the credentials are valid. After the user data are saved and a token is generated you no longer need to worry about it and all will be handled for you.bearer
mode, so we recommend setting it on the app initialization.NeorequestAuthorization.regenerateCustomTokenHandler((NeorequestAuthorization, @escaping ((NeorequestError) -> Void), @escaping (() -> Void)) -> Void)
regenerateBearerTokenHandler
. Please refer to this closure explanation above for more info.NeorequestAuthorization.getCustomValidAuthHeaderStringHandler((NeorequestAuthorization, @escaping ((NeorequestError) -> Void), @escaping ((String) -> Void)) -> Void)
Authorization
header of the string. Since you are using a custom auth we can't do this for you.NeorequestAuthorization
or if the saved token is still valid. If needed, you can call .regenerateCustomTokenHandler
to get another token.onSucess
closure. If you need to append any fixed value to the header please do it here.Create a new instance of the NeorequestAuthorization, set the desired properties and regenerate the token. The regenerateBearerTokenHandler you provided must save the new values. Please note that saving new data will override any existing data since we still do not support handling multiple accounts.
let auth = NeorequestAuthorization()
auth.account = "account"
auth.password = "password"
auth.regenerateBearerToken(
onError: {
error in
//Manage the error
},
onSuccess: {
//User authenticated and token regenerated
}
)
NeorequestAuthorization.load()
will return an object with all the info initialized from the keychain if it exists or return nil if no data is saved on the keychain.
If for some reason you must force a token regeneration on the next request you can call expirateToken
on a populated object, which will set the token as expired and it will be renewed at the next request. To regenerate the token right now you can use regenerateBearerToken(onError: ((NeorequestError) -> Void), onSuccess: @escaping (() -> Void))
.
NeorequestAuthorization.load()?.delete()
will remove any existing data.
import Neorequest
NeorequestAuthorization.regenerateBearerTokenHandler = {
auth, onError, onSuccess in
//The remote api authentication endpoint uses x-www-form-url-encoded
var config = NeorequestConfiguration()
config.isJsonRequest = false
Neorequest<TokenObject>.POST(
url: "http://yoururl.com/auth",
authorization: nil,
parameters: ["account": auth.account, "password": auth.password],
configuration: config,
onError: onError, //Use the provided error handler to return to the original request
onSuccess: {
tokenObj in
//Retrieve the token and save it
auth.tokenString = "..."
//Since the request is valid we can save the auth data now
auth.save()
//Proceed with the request
onSuccess()
}
)
}
import Neorequest
let auth = NeorequestAuthorization()
auth.account = account
auth.password = password
auth.regenerateBearerToken(
onError: {
error in
//Problem regenerating the token. Maybe the user provided bad credentials?
},
onSuccess: {
//Token regenerated. Proceed with the next requests
}
)
Neorequest is licensed under the Apache v2 License. See the LICENSE file for more info.