ishkawa / apikit Goto Github PK
View Code? Open in Web Editor NEWType-safe networking abstraction layer that associates request type with response type.
License: MIT License
Type-safe networking abstraction layer that associates request type with response type.
License: MIT License
Currently if the response status code is not 2xx, it won't parse the response body at all.
However sometimes the response body may contain useful info even if the response status code is not 2xx (mostly 4xx), for example, validation errors of object creation.
Can we please at least having an option to choose whether to parse the response body even if the response status code is not 2xx?
I have read the issue, but still having problems. Here is the code
struct UploadAvatar: RequestType {
typealias Response = ImageResponse
var path: String { return "/passport/user/avatar" }
var method: HTTPMethod { return .PUT }
var bodyParameters: BodyParametersType? {
return MultipartFormDataBodyParameters(parts: [MultipartFormDataBodyParameters.Part(data: imageData, name: "avatar", fileName: "avatar")])
}
let imageData: NSData
}
I use Charles to capture the package, found that the content-type
is Content-Type:application/json
, but in MultipartFormDataBodyParameters
is not.
Does one need to include the Box framework in the main bundle? After 0.8.0 I am getting this error
dyld: Library not loaded: @rpath/Box.framework/Box
To follow the Semantic Versioning, a form 1.0.0-beta.5
would be more appropriate than 1.0.0-beta5
IMO.
To use iOS7, I try to install manualy.
Copy APIKit/.swift and Carthage/Checkouts/Result/Result/.swift to your project.
https://github.com/ishkawa/APIKit#3-copying-source-files
But I can't find Carthage/Checkouts/Result/Result/*.swift
after git clone
$ ls Carthage/Checkouts/
Assertions OHHTTPStubs
after carthage update
$ ls Carthage/Checkouts/
Assertions Result
But still has error on import Box
in Result.swift
Swift Compiler Error No such module 'Box'
So, I added Box.swift, BoxType.swift, MutableBox.swift.
And commented out import Box
Then build succeeded.
Please modify document or code to install more easily.
(英語下手くそなので、もしわかりづらかったら日本語で補足します。個人的にはAlamofireみたくgit submoduleでインストールできたらうれしいです。ちょっと試したのですがAPIKit.hが赤いテキストになり、うまくいきませんでした)
I am trying to install APIKit with carthage
And as the result of running
carthage update --platform iOS --use-submodules --no-use-binaries
I get error
A shell task (/usr/bin/env git submodule --quiet update --init --recursive) failed with exit code 1: fatal: reference is not a tree: 3c3be9d5f9735a034e5e9434e03f6db764e9125e Unable to checkout '3c3be9d5f9735a034e5e9434e03f6db764e9125e' in submodule path 'Carthage/Checkouts/OHHTTPStubs'
I use submodules as I am building a framework and want to be able to use it outside carthage. (I am following this guide: https://robots.thoughtbot.com/creating-your-first-ios-framework)
dyld: Symbol not found: OBJC_METACLASS$__TtC6APIKit3API
Got this error after upgrading to v0.4 when trying to run the app on device (works fine in simulator).
And it would work if rolled back to old version.
I'm sorry to be not good at English.
I want to halt a process response by validating HTTP response headers.
For example,
There is app versions in both the client app and http headers in the server response.
If it's number in the former is less than it in the latter, I want to halt a process server response i.e. parse,
and show alert to encourage users to update app.
// FooRequet
func responseFromObject(object: AnyObject, URLResponse: NSHTTPURLResponse) -> Response? {
let headers = URLResponse. allHeaderFields
if let version = headers["mobile-version"] where version > currentVersion { // release new version
// halt and handling error at place calling `Session#sendRequest`
}
...
return ...
}
// ViewController
session.sendRequest(request) { result in
// if error of app version
presentAlert("update app")
}
Is there a solution?
Here is imagination I think casually,
// FooRequet
// add throws
func responseFromObject(object: AnyObject, URLResponse: NSHTTPURLResponse) throws -> Response? {
// if current version is outdated
throw FooError.AppVersionOutdated(version)
return ...
}
// RequestType
public func parseData(data: NSData, URLResponse: NSURLResponse?) -> Result<Self.Response, APIError> {
...
do {
guard let response = responseFromObject(object, URLResponse: HTTPURLResponse) else {
return .Failure(.InvalidResponseStructure(object))
}
...
} catch {
return .Failure(.InvalidResponseError(error))
}
...
}
Thanks.
Sorry if i ask too many question here, wonder if there is any way we could get a progress when we upload a file like Alamofire upload method. Thanks 👍
Podを使ってAPIKitを使用させて頂いております。
現在、Xcode8 Swift2.3を使用しており、
APIKitを2.0.5にアップデートを行ったのですが、
ビルドエラーになりました。
調査した結果
Support FilesのAPIKit.xcconfigに下記を追加して解決しました。
SWIFT_VERSION = 2.3
※Podの場合のみ発生するようです。
I want to upload stream without creating NSData (like Alamofire/AFNetworking)
because uploading very large file(like long movie file) will cause crash by memory problem.
I tried to create custom RequestBodyBuilder but buildBodyFromObject return NSData...
Please tell me how to fix this problem on APIKit 1 or 2?
Hi, Session
always return the error in .Failure
closure as APIError
, but i send a custom ErrorType
and there is no way to cast the error to another, here is a example:
public enum CustomError: ErrorType {
case ValidationError(message: String)
}
public struct EmailSignupRequest: StarflowRequest {
public typealias Response = STAccessToken
public func errorFromObject(object: AnyObject, URLResponse: NSHTTPURLResponse) -> ErrorType? {
guard let dictionary = object as? [String: AnyObject] else {
return nil
}
guard let message = dictionary["error_description"] as? String else {
return nil
}
return CustomError.ValidationError(message: message)
}
}
and when i send the request like this i can print the error and it shows as CustomError.ValidationError
but i can't handle the error!
let req = EmailSignupRequest()
Session.sendRequest(req) { result in
switch result {
case .Success(_):
print("success")
case .Failure(let error):
print("did get error signin up \(error)")
}
}
}
when i do like this
let error = error as? StarflowKitError
i get Cast from 'APIError' to unrelated type 'CustomError' always fails
Depends on antitypical/Result#101. This may be the final issue for our 1.0 😄
Hey there,
Does APIKit cache any requests that are made/the response that is received? If so, how? Does it use the default NSURLCache? If I modified it and did something like the following in my app delegate NSURLCache.setSharedURLCache(URLCache)
would APIKit automatically pick up the changes?
Does it take e-tags into consideration?
Thanks
Is there anyway we could do SSL Pinning in APIKit? like Alamofire ServerTrustPolicy
There are 2 issues that are pinned at 1.0 milestone, but I would like to release current master
as 1.0 for the following reasons:
~> 0.6.0
. #89After releasing 1.0.0, I'm planning to work on following topics:
multipart/form-data
These changes may be breaking, but scale of changes is smaller than that of 0.x -> 1.0.
I'm confident that they improve library interface significantly 😉
Xcode 7 beta 5 caused APIKit/Request.swift to fail to build:
*** Fetching APIKit
*** Fetching Result
*** Checking out APIKit at "1.0.0-beta2"
*** Checking out Result at "0.6-beta.1"
*** xcodebuild output can be found in /var/folders/zs/nrb9j0ws1q79l86sbfstq3180000gn/T/carthage-xcodebuild.TMppnX.log
*** Building scheme "Result-Mac" in Result.xcodeproj
*** Building scheme "Result-watchOS" in Result.xcodeproj
*** Building scheme "Result-iOS" in Result.xcodeproj
*** Building scheme "APIKit-Mac" in APIKit.xcworkspace
** BUILD FAILED **
The following build commands failed:
CompileSwift normal x86_64 /Users/user/Projects/Demo/Carthage/Checkouts/APIKit/APIKit/Request.swift
CompileSwiftSources normal x86_64 com.apple.xcode.tools.swift.compiler
(2 failures)
/Users/user/Projects/Demo/Carthage/Checkouts/APIKit/APIKit/Request.swift:92:51: error: 'stringByAppendingPathComponent' is unavailable: Use stringByAppendingPathComponent on NSString instead.
A shell task failed with exit code 65:
** BUILD FAILED **
The following build commands failed:
CompileSwift normal x86_64 /Users/user/Projects/Demo/Carthage/Checkouts/APIKit/APIKit/Request.swift
CompileSwiftSources normal x86_64 com.apple.xcode.tools.swift.compiler
(2 failures)
I see the Request
implementations are easily unit-testable which is nice. But what is the preferred approach to testing for clients of the Session
API? It's declared as a class rather than a protocol so it's not simply a matter of substituting a fake a test time. I don't see a "MockSessionAdapter
" in the test tree, but is that the appropriate hook point?
以下のようなリクエストを送っています。
idsというkeyでInt型のArrayを送信したいのですが、パラメータが["(\n 672,\n 669\n)"]
こういった形になってしまします。
やり方が悪いのでしょうか...?
何卒よろしくお願いします。
struct deleteImage: UserImageRequestType {
typealias Response = Bool
let ids: [Int]
let method = HTTPMethod.DELETE
var path: String { return "/v1/user_images/delete" }
var parameters: [String: AnyObject] { return ["ids": ids] }
func responseFromObject(object: AnyObject, URLResponse: NSHTTPURLResponse) -> Response? {
...
}
}
xcodebuild
complains when linking to tvOS TopShelf extension app.
I didn't know if it's okay to just enable "Allow app extension API only".
Hi, I'm new to swift, so I'm sorry if I made mistake.
in XCode7.3 and swift 2.2, example code with himotoki got 'DecodedType' is not a member type of 'Self.Response'
here's full code that i got the error.
import Foundation
import Himotoki
import APIKit
protocol ExampleRequest : RequestType {}
extension ExampleRequest {
var baseURL: NSURL {
return NSURL(string: "https://example.com/")!
}
}
extension ExampleRequest where Self.Response: Decodable, Self.Response == Self.Response.DecodedType {
func responseFromObject(object: AnyObject, URLResponse: NSHTTPURLResponse) -> Self.Response? {
return try? decode(object)
}
}
Is there any workaround to solve this error?
thanks.
When adding APIKIt into a project I get the following error when the project is compiled and launched. Removing it makes the error go away.
dyld_sim`dyld_fatal_error:
0x100309000 <+0>: int3
-> 0x100309001 <+1>: nop
Have you seen this before? Kind of lost on ideas here 😔 tried 9.0, 9.1 and 9.2
In Swift standard library, protocol names follow naming conventions like ...able or ...Type. For example, Equiatable
, SequenceType
and ErrorType
. I think RequestType
is more suitable for the name of request protocol, and this change should be applied before 1.0.0 is released.
@ikesyo What do you think?
IMO, singleton implementation based on class name is not obvious and tricky (it forces API to be NSObject subclass) + sometimes users of this kinds of libs do not want use singletons (for example for testing).
Also, the type of Github.instance
in demo app is not Github
but API
, that's a bug.
Hi,
I am trying to upload an image to a server, at the moment is working great.. but since I need to register a new URLSession to get the progress of the upload, this makes the APIKit skip the response callback entirely.
let session = Session(URLSession: NSURLSession(configuration: .defaultSessionConfiguration(), delegate: self, delegateQueue: nil))
session.sendRequest(request) { response in
print("never gets called")
}
Am I doing this correctly? or is there another method I should be using within the library?
Thanks
Hey there,
I have a specific requirement for my app that I'm working on. The API web service uses JSON Web Tokens. It requires me to pass in a valid x-session-token header for each protected API endpoint.
These session tokens expire every 24h, which means I need to reauthenticate and retry my existing request. Is that currently possible with APIKit? I've seen some PRs about interceptors for version 2.0 but I'm not sure if that's what I need.
Here's an example of what I mean:
Let's say I need to call the GET /user endpoint of my API and it requires me to pass in a valid x-session-token in the header. If the token has expired, I will get an error response, something like this:
success: false, error: {
code = E1100;
hint = Token;
message = "Session token has expired.";
}
Now whenever I get an error response with the error.code == "E1100", what I want to do is, automatically call the POST /authenticate_session endpoint, get the new session token and automatically retry the GET /user request with the updated x-session-token header.
Can you point me in the right direction of how I could best implement this with APIKit?
I'm currently using a different API library for my app and it's proving to be a pain (I'm literally at the point of where I'm trying to fight and go against how the framework was intended to work). Before I start implementing my API logic from scratch, I'm exploring my options and would like to research if I could accomplish this functionality requirement using APIKit (or any other open source library).
Thanks for your help.
Hi, When i use APIKit with Carthage i get some errors,
this is my Cartfile
github "ishkawa/APIKit" ~> 1.0
first issue is that it checks out as Checking out APIKit at "1.0.0-beta5"
and i think the problem is that you changed beta5
to point style (beta.6
) so it always checks out at beta5
and the second issue is that i get this error:
A shell task failed with exit code 128: fatal: reference is not a tree: 2e38ee3e7a3e1dd01be31edb94368c2f4a840915
I want to be extending / subclassing Session
for file downloading / uploading.
So, I want to use CallbackQueue.execute()
outside APIKit module.
May I send pull request?
日本語ですみません。
当方swiftに関しては使い始めたばかりで見当違いな指摘かもしれませんが、RequestTypeのconfigureURLRequestの戻り値が使われていないような気がします。副作用でのconfigurationを期待するメソッドなのでしょうか?
Some API requests parameter with array format with GET method.
some.api.com?data[id]=10
I tried to set parameter like:
var parameters: [String: AnyObject] {
return ["data[id]": 10]
}
and
var parameters: [String: AnyObject] {
return ["data": ["id": 10]]
}
Both throws error
NSInvalidArgumentException', reason: '*** +[NSURLComponents setPercentEncodedQuery:]: invalid characters in percentEncodedQuery
Maybe parameter contains invalid characater '[' and ']'.
I should escape parameter key myself or any easy way to build such parameter?
It'd be great if API.responseErrorFromObject(object:) returned a NSHTTPURLResponse - it'd help to validate HTTP status codes.
Hey there,
I've got an endpoint which I'm trying to call but it doesn't work. I've debugged the issue and it's because the .DELETE method returns true for "prefersQueryParameters". That's not what I need, I need it to return false.
I need to post an array of strings back to my endpoint via the .DELETE method, but it doesn't parse properly if it uses query parameters instead of the body parameters.
What would be the best way for me to override the default behaviour of the .DELETE method to return false instead of true inside of "prefersQueryParameters"?
A query parameter with GET method is double encoded. It converts "あ" into "%25E3%2581%2582", it should be "%E3%81%82".
query
property of NSURLComponents will be encoded automatically when getting to complete NSURL. You can use NSURLComponents.percentEncodedQuery
or just use NSURLComponents and NSURLQueryItem for query encoding.
Session.send(request)
.success { response in
// Type of `response` is `[Repository]`,
print(response)
}
.failure { error in
self.printError(error)
}
}
It can remove a lot of switch ... case...
,I think this syntax is much more clarity.
Hi im trying to migrate to V2 and i have a problem with BodyParametersType
but i get an error from server that some fileds are missing, is there something im doing wrong?
public struct EmailSignupRequest: SFRequest {
public typealias Response = String
private let name: String
private let password: String
private let username: String
private let email: String
private let avatar: UIImage?
public var method: HTTPMethod {
return .POST
}
public var authenticate: Bool {
return true
}
public var path: String {
return "users"
}
public init(email: String, username: String, password: String, avatar: UIImage?, name: String) {
self.email = email
self.name = name
self.password = password
self.username = username
self.avatar = avatar
}
public var parameters: AnyObject? {
return [
"email": email,
"name": name,
"password": password,
"username": username
]
}
public var bodyParameters: BodyParametersType? {
if let image = self.avatar, let imageData = UIImageJPEGRepresentation(image, 0.8) {
return MultipartFormDataBodyParameters(parts: [
MultipartFormDataBodyParameters.Part(data: imageData, name: "avatar", fileName: "avatar")
])
}
return nil
}
}
Not found how to basic auth by use APIKit.
If Alamofire, can pass auth to write .authenticate(user: user, password: password)
.
Best regards.
I am running into this error when trying to use the sendRequest
, the only "thing different" that I think I am doing is embedding APIKit and LlamaKit into an umbrella framework called ProductHuntKit
let request = ProductHunt.Endpoint.Posts(day: .Today)
ProductHunt.sendRequest(request) { response in
switch response {
case .Success(let box):
let content = box.unbox
case .Failure(let box):
let alertController = UIAlertController(title: "Error", message: box.unbox.localizedDescription, preferredStyle: .Alert)
let action = UIAlertAction(title: "OK", style: .Default, handler: nil)
alertController.addAction(action)
self.presentViewController(alertController, animated: true, completion: nil)
}
}
Undefined symbols for architecture x86_64:
"__TIZFC6APIKit3API11sendRequestFMS0_US_7Request_U__FTQ_10URLSessionCSo12NSURLSession7handlerFGO8LlamaKit6ResultQQ_8ResponseCSo7NSError_T__GSqCSo20NSURLSessionDataTask_A0_", referenced from:
__TFC11ProductHunt20DetailViewController11viewDidLoadfS0_FT_T_ in DetailViewController.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Anything comes to mind?
See the search result:
https://github.com/ishkawa/APIKit/search?utf8=%E2%9C%93&q=UnexpectedURLRequest
Is there anyway in APIKit that we can POST with a file (multpart/form-data)?
Sorry if i ask here
Hey there,
I thought I was using the beta for 2.0 before, but looks like I was still on 1.3!
I decided to update today and sort out all the issues. I managed to get it all refactored and building, however now I have 1 issue and that's related to the http headers.
First of all, you should include in the migration guide that HTTPHeaderFields
has changed to headerFields
.
Now to my problem, after I updated my existing classes to use headerFields
, it doesn't seem to be picking up my custom header. I'm doing something like this right now:
var headerFields: [String: String] {
return [APIHeaders.BasicAuth.rawValue: constructBasicAuth()!]
}
Inside the constructBasicAuth
function, I have some print()
statements which are NOT printing in the console. I'm not sure why, but it seems like it's not using the headerFields
property at all?
Do you have any ideas what I might be doing wrong? Am I maybe missing a step?
I can not update as 1.0.0-beta13 using command pod update
.
The CocoaPods recognize 1.0.0-beta9 as the latest version.
Maybe problem on ascending of the version string.
It will be fixed if you update version as 1.0.1.
I try 2.0-development
branch just now.
RequestError
's access control is internal
.
Is this on purpose?
RequestError.swift
Is it possible to public
?
maybe it's simple, but i can't find it, please...
Hi, There is no example on how its possible to map an array of objects, here is my issue
/X/Client/TestRequest.swift:21:8: Type 'TestRequest' does not conform to protocol 'RequestType'
the issue is that there is no responseFromObject
function for arrays
struct TestRequest: XPRequest {
typealias Response = [LKObject]
private var page: Int!
private var perPage: Int!
var method: HTTPMethod {
return .GET
}
var authenticate: Bool {
return true
}
var path: String {
return "/api/exps"
}
init(page: Int, perPage: Int) {
self.page = page
self.perPage = perPage
}
var parameters: [String : AnyObject] {
return ["page": page, "per_page": perPage]
}
}
I made a wrapper like this
struct PaginatedExperience: Decodable {
let items: [LKObject]
static func decode(json: AnyObject) throws -> PaginatedExperience {
return try PaginatedExperience(items: [LKObject].decode(json))
}
}
and it works no but its not the best way
JsonRpc has Batch feature, whose request parameter is an array of json objects, so I think RequestType
should accept Array type as parameters
as well as Dictionary type.
Maybe we should add arrayParameters
to RequestType
protocol ?
I try 2.0-dev branch.
interceptURLRequest
is removed at this commit 022d256 .
Is there how to customize NSURLRequest?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.