Code Monkey home page Code Monkey logo

afoauth1client's Introduction

AFNetworking is Deprecated

As of Jan. 17, 2023, AFNetworking is deprecated and there will be no further releases. This repo will remain online in perpetuity as an archive. There are a couple options for continued AFNetworking use:

  1. Copy AFNetworking into your project and compile it directly. This gives you full control over the code.
  2. Fork AFNetworking and use the fork in your dependency manager. There will be no official forks but anyone can fork at any time and can even publish those forks under a different name, in accordance with AFNetworking's license.

Moving forward, Alamofire is the suggested migration path for networking in modern Swift. Anyone who needs help making that migration is welcome to ask on StackOverflow and tag alamofire and afnetworking, or open a discussion on Alamofire's GitHub Discussions regarding any migration issues or missing features.


AFNetworking

Build Status CocoaPods Compatible Carthage Compatible Platform Twitter

AFNetworking is a delightful networking library for iOS, macOS, watchOS, and tvOS. It's built on top of the Foundation URL Loading System, extending the powerful high-level networking abstractions built into Cocoa. It has a modular architecture with well-designed, feature-rich APIs that are a joy to use.

Perhaps the most important feature of all, however, is the amazing community of developers who use and contribute to AFNetworking every day. AFNetworking powers some of the most popular and critically-acclaimed apps on the iPhone, iPad, and Mac.

How To Get Started

Communication

  • If you need help, use Stack Overflow. (Tag 'afnetworking')
  • If you'd like to ask a general question, use Stack Overflow.
  • If you found a bug, and can provide steps to reliably reproduce it, open an issue.
  • If you have a feature request, open an issue.
  • If you want to contribute, submit a pull request.

Installation

AFNetworking supports multiple methods for installing the library in a project.

Installation with CocoaPods

To integrate AFNetworking into your Xcode project using CocoaPods, specify it in your Podfile:

pod 'AFNetworking', '~> 4.0'

Installation with Swift Package Manager

Once you have your Swift package set up, adding AFNetworking as a dependency is as easy as adding it to the dependencies value of your Package.swift.

dependencies: [
    .package(url: "https://github.com/AFNetworking/AFNetworking.git", .upToNextMajor(from: "4.0.0"))
]

Note: AFNetworking's Swift package does not include it's UIKit extensions.

Installation with Carthage

Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. To integrate AFNetworking, add the following to your Cartfile.

github "AFNetworking/AFNetworking" ~> 4.0

Requirements

AFNetworking Version Minimum iOS Target Minimum macOS Target Minimum watchOS Target Minimum tvOS Target Notes
4.x iOS 9 macOS 10.10 watchOS 2.0 tvOS 9.0 Xcode 11+ is required.
3.x iOS 7 OS X 10.9 watchOS 2.0 tvOS 9.0 Xcode 7+ is required. NSURLConnectionOperation support has been removed.
2.6 -> 2.6.3 iOS 7 OS X 10.9 watchOS 2.0 n/a Xcode 7+ is required.
2.0 -> 2.5.4 iOS 6 OS X 10.8 n/a n/a Xcode 5+ is required. NSURLSession subspec requires iOS 7 or OS X 10.9.
1.x iOS 5 Mac OS X 10.7 n/a n/a
0.10.x iOS 4 Mac OS X 10.6 n/a n/a

(macOS projects must support 64-bit with modern Cocoa runtime).

Programming in Swift? Try Alamofire for a more conventional set of APIs.

Architecture

NSURLSession

  • AFURLSessionManager
  • AFHTTPSessionManager

Serialization

  • <AFURLRequestSerialization>
    • AFHTTPRequestSerializer
    • AFJSONRequestSerializer
    • AFPropertyListRequestSerializer
  • <AFURLResponseSerialization>
    • AFHTTPResponseSerializer
    • AFJSONResponseSerializer
    • AFXMLParserResponseSerializer
    • AFXMLDocumentResponseSerializer (macOS)
    • AFPropertyListResponseSerializer
    • AFImageResponseSerializer
    • AFCompoundResponseSerializer

Additional Functionality

  • AFSecurityPolicy
  • AFNetworkReachabilityManager

Usage

AFURLSessionManager

AFURLSessionManager creates and manages an NSURLSession object based on a specified NSURLSessionConfiguration object, which conforms to <NSURLSessionTaskDelegate>, <NSURLSessionDataDelegate>, <NSURLSessionDownloadDelegate>, and <NSURLSessionDelegate>.

Creating a Download Task

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];

NSURL *URL = [NSURL URLWithString:@"http://example.com/download.zip"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];

NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
    NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
    return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
    NSLog(@"File downloaded to: %@", filePath);
}];
[downloadTask resume];

Creating an Upload Task

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];

NSURL *URL = [NSURL URLWithString:@"http://example.com/upload"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];

NSURL *filePath = [NSURL fileURLWithPath:@"file://path/to/image.png"];
NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithRequest:request fromFile:filePath progress:nil completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
    if (error) {
        NSLog(@"Error: %@", error);
    } else {
        NSLog(@"Success: %@ %@", response, responseObject);
    }
}];
[uploadTask resume];

Creating an Upload Task for a Multi-Part Request, with Progress

NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:@"http://example.com/upload" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
        [formData appendPartWithFileURL:[NSURL fileURLWithPath:@"file://path/to/image.jpg"] name:@"file" fileName:@"filename.jpg" mimeType:@"image/jpeg" error:nil];
    } error:nil];

AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

NSURLSessionUploadTask *uploadTask;
uploadTask = [manager
              uploadTaskWithStreamedRequest:request
              progress:^(NSProgress * _Nonnull uploadProgress) {
                  // This is not called back on the main queue.
                  // You are responsible for dispatching to the main queue for UI updates
                  dispatch_async(dispatch_get_main_queue(), ^{
                      //Update the progress view
                      [progressView setProgress:uploadProgress.fractionCompleted];
                  });
              }
              completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
                  if (error) {
                      NSLog(@"Error: %@", error);
                  } else {
                      NSLog(@"%@ %@", response, responseObject);
                  }
              }];

[uploadTask resume];

Creating a Data Task

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];

NSURL *URL = [NSURL URLWithString:@"http://httpbin.org/get"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];

NSURLSessionDataTask *dataTask = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
    if (error) {
        NSLog(@"Error: %@", error);
    } else {
        NSLog(@"%@ %@", response, responseObject);
    }
}];
[dataTask resume];

Request Serialization

Request serializers create requests from URL strings, encoding parameters as either a query string or HTTP body.

NSString *URLString = @"http://example.com";
NSDictionary *parameters = @{@"foo": @"bar", @"baz": @[@1, @2, @3]};

Query String Parameter Encoding

[[AFHTTPRequestSerializer serializer] requestWithMethod:@"GET" URLString:URLString parameters:parameters error:nil];
GET http://example.com?foo=bar&baz[]=1&baz[]=2&baz[]=3

URL Form Parameter Encoding

[[AFHTTPRequestSerializer serializer] requestWithMethod:@"POST" URLString:URLString parameters:parameters error:nil];
POST http://example.com/
Content-Type: application/x-www-form-urlencoded

foo=bar&baz[]=1&baz[]=2&baz[]=3

JSON Parameter Encoding

[[AFJSONRequestSerializer serializer] requestWithMethod:@"POST" URLString:URLString parameters:parameters error:nil];
POST http://example.com/
Content-Type: application/json

{"foo": "bar", "baz": [1,2,3]}

Network Reachability Manager

AFNetworkReachabilityManager monitors the reachability of domains, and addresses for both WWAN and WiFi network interfaces.

  • Do not use Reachability to determine if the original request should be sent.
    • You should try to send it.
  • You can use Reachability to determine when a request should be automatically retried.
    • Although it may still fail, a Reachability notification that the connectivity is available is a good time to retry something.
  • Network reachability is a useful tool for determining why a request might have failed.
    • After a network request has failed, telling the user they're offline is better than giving them a more technical but accurate error, such as "request timed out."

See also WWDC 2012 session 706, "Networking Best Practices.".

Shared Network Reachability

[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
    NSLog(@"Reachability: %@", AFStringFromNetworkReachabilityStatus(status));
}];

[[AFNetworkReachabilityManager sharedManager] startMonitoring];

Security Policy

AFSecurityPolicy evaluates server trust against pinned X.509 certificates and public keys over secure connections.

Adding pinned SSL certificates to your app helps prevent man-in-the-middle attacks and other vulnerabilities. Applications dealing with sensitive customer data or financial information are strongly encouraged to route all communication over an HTTPS connection with SSL pinning configured and enabled.

Allowing Invalid SSL Certificates

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.securityPolicy.allowInvalidCertificates = YES; // not recommended for production

Unit Tests

AFNetworking includes a suite of unit tests within the Tests subdirectory. These tests can be run simply be executed the test action on the platform framework you would like to test.

Credits

AFNetworking is owned and maintained by the Alamofire Software Foundation.

AFNetworking was originally created by Scott Raymond and Mattt Thompson in the development of Gowalla for iPhone.

AFNetworking's logo was designed by Alan Defibaugh.

And most of all, thanks to AFNetworking's growing list of contributors.

Security Disclosure

If you believe you have identified a security vulnerability with AFNetworking, you should report it as soon as possible via email to [email protected]. Please do not post it to a public issue tracker.

License

AFNetworking is released under the MIT license. See LICENSE for details.

afoauth1client's People

Contributors

alexanderedge avatar ay8s avatar choco avatar echoz avatar ejensen avatar falkobuttler avatar hexrain avatar iwasrobbed avatar jnormore avatar joergsimon avatar kgn avatar kudomo avatar lxcid avatar mattt avatar ninjinkun avatar oliverletterer avatar owen-bnr avatar pj4533 avatar plantpurecode avatar samskiter avatar seivan avatar shir avatar tomburns avatar touchbyte avatar vtourraine avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

afoauth1client's Issues

Token request call uses "GET" even if accessMethod is set to "POST"

Hi, I am working with an oauth provider that uses POST for request token API. Here is how I am using AFOAuth1Client to make a request:

    self.client = [[AFOAuth1Client alloc] initWithBaseURL:[NSURL URLWithString:SERVER_URL] key:kOAuthKey secret:kOAuthSecret];
    self.client.oauthAccessMethod = @"POST";

[self.client authorizeUsingOAuthWithRequestTokenPath:@"api/auth/v1/oauth/token/request" userAuthorizationPath:@"/services/api/auth" callbackURL:[NSURL URLWithString:@"MYURL://success"] accessTokenPath:@"/api/auth/v1/oauth/token/access" accessMethod:@"POST" scope:@"" success:^(AFOAuth1Token *accessToken, id responseObject) {

        [SVProgressHUD dismiss];

    } failure:^(NSError *error) {

        [SVProgressHUD dismiss];
        [UIAlertView showErrorWithMessage:error.localizedDescription handler:nil];

    }];

The problem is, I see that the initial request to request token is triggered as a GET request, instead of POST. Any ideas what's going on?

No visibile interface error.

/AFOAuth1Client/Twitter iOS Example Client/Twitter iOS Example Client/AppDelegate.m:41:6: No visible @interface for 'AFOAuth1Client' declares the selector 'authorizeUsingOAuthWithRequestTokenPath:userAuthorizationPath:callbackURL:accessTokenPath:accessMethod:success:failure:'

The name of the methods was changed in
'authorizeUsingOAuthWithRequestTokenPath:userAuthorizationPath:callbackURL:accessTokenPath:accessMethod:_scope:_success:failure:

Problem with ~ symbol

Hi,

First of all, great library, been working like a charm for me!

The only issue I get is with the ~ char, every other special character I've tried work just fine. For some reason if I have ~ in the content I'm posting, I get:Error Domain=AFNetworkingErrorDomain Code=-1011 , status code 400 - 40104:incorrect signature". I have tried to encode the '~' char with urlEncoding format, but still get the same error. I also noticed you have ~ removed from the encoding list on your code - but either by adding it back or not, it still gives the same.

Any help?

Thanks,

baseURL that has a few path levels get truncated

When using a baseURL such as https://staging.geocaching.com/oAuth/mobileoauth.ashx/ it gets cut down to https://staging.geocaching.com/ which makes requests not work since https://staging.geocaching.com/request_token is not a valid page.

Why is this happening?

Cannot acquire access_token, while trying to use with Fitbit OAuth 1.0 API

AFOAuth1Client *oAuthClient = [[AFOAuth1Client alloc] initWithBaseURL:[NSURL URLWithString:@"http://api.fitbit.com/"] key:@"key-removed" secret:@"secret-removed"];

[oAuthClient authorizeUsingOAuthWithRequestTokenPath:@"/oauth/request_token" userAuthorizationPath:@"http://www.fitbit.com/oauth/authorize?display=touch" callbackURL:[NSURL URLWithString:@"bitrockr://fitbit/success"] accessTokenPath:@"/oauth/access_token" accessMethod:@"POST" scope:nil success:^(AFOAuth1Token *accessToken, id responseObject) {
    NSLog(@"AUTH COMPLETE :: %@", accessToken);
} failure:^(NSError *error) {
    NSLog(@"AUTH FAILED");
}];

I am using this for an iphone application. On running the code, the request_token is fetched, and the user is redirected to fitbit website for auth, once the user allows the app, he is returned to app with oauth_token and oauth_verifier, but it throws an error while requesting access_token. While sending the request, the only thing I could find was the oauth_verifier was not being sent.

Request sent for access_token

POST /oauth/access_token HTTP/1.1
Host: api.fitbit.com
Authorization: OAuth oauth_consumer_key="key-removed", oauth_nonce="271686CA-A50B-4D55-BD6E-AF84C9F5A28F", oauth_signature="aLpVwPCGTCWbeio4VXFj3YxI%2Fvo%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1377836692", oauth_token="a4bd32439b8c07831071b5385e1b15c0", oauth_version="1.0"
Accept: */*
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Accept-Language: en;q=1, fr;q=0.9, de;q=0.8, ja;q=0.7, nl;q=0.6, it;q=0.5
Content-Length: 0
Connection: keep-alive
User-Agent: Bitrockr/1.0 (iPhone Simulator; iOS 6.1; Scale/1.00)

Response

HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
X-UA-Compatible: IE=edge,chrome=1
WWW-Authenticate: OAuth realm="http%3A%2F%2Fapi01.fitbit.com", oauth_problem="permission_denied"
Set-Cookie: fhttps=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Cache-control: no-store, no-cache, must-revalidate
Pragma: no-cache
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
Content-Language: en-US
Content-Length: 31
Date: Fri, 30 Aug 2013 04:24:52 GMT

oauth_problem=permission_denied

Link: Fitbit OAuth API

Tutorial / Example help

Hi all
I'm new to AFOAuth1Client so please bear with me.

I am able to make requests using

AFHTTPRequestOperation *NewOperation = [oAuth HTTPRequestOperationWithRequest:NewRequest success: failure: ];
and
[oAuth enqueueHTTPRequestOperation:NewOperation];

However I'm needing to make multiple requests. So within the first success I need to make more Requests and enqueueHTTP...

  1. How can you request oAuth connections synchronously ?

  2. If I where to use a [oAuth postPath]; Where does one set the HTTP Body ?
    Currently I use:

NSMutableURLRequest    *NewRequest   = [oAuth requestWithMethod:@"POST" path:@"customer"  parameters:nil];
[NewRequest setValue:@"application/xml"  forHTTPHeaderField:@"Content-Type"];
[NewRequest setHTTPBody:[customer dataUsingEncoding:NSUTF8StringEncoding]];
AFHTTPRequestOperation *NewOperation = [oAuth HTTPRequestOperationWithRequest:NewRequest success:   failure:  ];

How can I achieve this with a postPath ?

Thanks In Advance

Nonce always the same?

Im not sure why, maybe I dont fully understand oauth but, the oauth_nonce is always the same for me. Shouldnt this just be a randomly generated string of characters usually something to do with the timestamp etc?

Attempting to authenticate against another oauth api besides twitter and I still generate the same nonce every time.

oauth_nonce="cmVxdWVzdF90bw",

Im using the simulator, should I be using a device instead?

Make expiration a public property?

I'm wondering if expiration should be a public property. This is coming up as I'm serializing the parameters so I can recreate my auth'd sessions when leaving and returning to the app, using this to reinstate my AFOAuth1Client:

- (id)initWithKey:(NSString *)key
           secret:(NSString *)secret
          session:(NSString *)session
       expiration:(NSDate *)expiration
        renewable:(BOOL)canBeRenewed;

It's minor, but maybe there's a good reason it's not already.

"Nonce has already been used"

I get this every time. Am I doing something wrong?

Error Error Domain=AFNetworkingErrorDomain Code=-1011 "Expected status code in (200-299), got 400" UserInfo=0x6080000f4500 {NSLocalizedRecoverySuggestion={
  "status": 400,
  "message": "Nonce has already been used. Make sure your nonces are reasonablely random and large",
  "additional": "",
  "reference": ""
}, NSErrorFailingURLKey=https://api.appfigures.com/v2/reports/sales?group_by=dates&start_date=2014-10-26

oauth_signature in authorizationHeaderForMethod: parameters error when add body

I'm using AFOAuth1Client fore read and create products in Magento.

Well, i have a NSDictionary of product properties; This is the body of the request.

I'm calling the method:

- (void)postPath:(NSString *)path
      parameters:(NSDictionary *)parameters
         success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
         failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure

where the parameters argument is the dictionary above.

When AFOAuth1Client execute the method

- (NSString *)authorizationHeaderForMethod:(NSString*)method
                                      path:(NSString*)path
                                parameters:(NSDictionary *)parameters

it sets the oauth_signature calling the method OAuthSignatureForMethod... like below.

    [mutableAuthorizationParameters setValue:[self OAuthSignatureForMethod:method path:path parameters:mutableParameters token:self.accessToken] forKey:@"oauth_signature"];

The issue is that the mutableParameters object, passed like "parameters", is not correct (it contains the oauth_ and the products key/value properties).

If you replace mutableParameters with mutableAuthorizationParameters (mutableAuthorizationParameters contains only the oauth_ key/value properties) it will works perfectly.

0.3.2 Breaks and CocoaPods Issue

So I just noticed that upgrading from 0.3.2 from 0.3.1 breaks for me. Not sure exactly why yet but reverting back to 0.3.1 fixed the issue (I am using AFOAuth1Client to connect to the Yelp API but without any user authentication). BTW great library.

Anyway for now I was planning to fix this by staying on 0.3.1, but what is odd is that CocoaPods will still install the latest version. I updated my Podfile like this:

pod 'AFOAuth1Client', '~> 0.3.1'

But when I run pod update it still does this:

Installing AFOAuth1Client (0.3.2)

It seems like the Podspec for 0.3.1 is there in the repo and everything (https://github.com/CocoaPods/Specs/tree/master/AFOAuth1Client) so I'm not sure what the issue is. Is this a CocoaPods issue you think? I tried running pod repo update too and it still installs 0.3.2.

0.2.1 Podspec needs to be updated to not pull AFNetworking 2.0.0+

AFNetworking 2.0 causes conflicts with projects with platform targets < iOS 7 and with other CocoaPods that use earlier versions of AFNetworking.

If the dependency on AFNetworking was more restrictive than "> 1.0", like "~> 1.0", that could fix the problem.

isExpired check

Right now token expiration is checked this way:

 [self.expiration compare:[NSDate date]] == NSOrderedDescending;

Which, if I'm not mistaken, means (expiration > now), while it should be (expiration < now) because we want to test if token expires at a date in the future?

Failed to validate oauth signature and token

I've run your example, and this is what I've got.

Error: Error Domain=AFNetworkingErrorDomain Code=-1011 "Expected status code in (200-299), got 401" UserInfo=0x8945ef0 {NSLocalizedRecoverySuggestion=Failed to validate oauth signature and token, AFNetworkingOperationFailingURLRequestErrorKey=<NSMutableURLRequest https://api.twitter.com/oauth/request_token>, NSErrorFailingURLKey=https://api.twitter.com/oauth/request_token, NSLocalizedDescription=Expected status code in (200-299), got 401, AFNetworkingOperationFailingURLResponseErrorKey=<NSHTTPURLResponse: 0x71603d0>}

Quick Question about Login requiring Oauth

Just had an app rejected for kicking out to perform OAuth...
mainly(authorizeUsingOAuthWithRequestTokenPath )

Is it possible to for it to use a WebView, Would that be best practice for this...
Or would i need to fork and add the webView code myself?

Just wondered what other people might have done who are using this Library.

Cheers,
Michael.

Tumblr OAuth 1.0a

Hi Mattt, I can't make it work with Tumblr OAuth 1.0a (http://www.tumblr.com/docs/en/api/v2#auth), for some reason oauth_signature generated by AFOAuth1Client doesn't match value expected by Tumblr. Could you please advise, what can be possibly wrong?

Error Domain=AFNetworkingErrorDomain Code=-1011 "Expected status code in (200-299), got 401" UserInfo=0x9c6ad40 {NSLocalizedRecoverySuggestion=oauth_signature [9ExDk1efS/c3j3GNua/9FUu/jhI=] does not match expected value [8M3R+nuZ9FTBgqI1jb1eNJe7EQI=], AFNetworkingOperationFailingURLRequestErrorKey=<NSMutableURLRequest http://www.tumblr.com/oauth/access_token?oauth_consumer_key=ISY7GdYtCDXfzo4hSfWTlaAVmkRreLBttE15Igedfr4sfaAYxW&oauth_nonce=EEA112B3-B7F5-4119-B7BE-03A1B5FEDD2C&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1359338368&oauth_token=qDuc2OAcIyonkNP2tZlrj1IDWskGziDQRwlgx5nhlHgTYUygFo&oauth_verifier=XgpmG5hKTvIhXe1CEo9nn9TS8olfc0CWQXHk6fRebEeVN0WXyy&oauth_version=1.0&realm=http%3A%2F%2Fwww.tumblr.com%2F>, NSErrorFailingURLKey=http://www.tumblr.com/oauth/access_token?oauth_consumer_key=ISY7GdYtCDXfzo4hSfWTlaAVmkRreLBttE15Igedfr4sfaAYxW&oauth_nonce=EEA112B3-B7F5-4119-B7BE-03A1B5FEDD2C&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1359338368&oauth_token=qDuc2OAcIyonkNP2tZlrj1IDWskGziDQRwlgx5nhlHgTYUygFo&oauth_verifier=XgpmG5hKTvIhXe1CEo9nn9TS8olfc0CWQXHk6fRebEeVN0WXyy&oauth_version=1.0&realm=http%3A%2F%2Fwww.tumblr.com%2F, NSLocalizedDescription=Expected status code in (200-299), got 401, AFNetworkingOperationFailingURLResponseErrorKey=<NSHTTPURLResponse: 0xac4a2b0>}

My code:

AFOAuth1Client *client = [[AFOAuth1Client alloc] initWithBaseURL:[NSURL URLWithString:@"http://www.tumblr.com"]
                                                             key:@"ISY7GdYtCDXfzo4hSfWTlaAVmkRreLBttE15Igedfr4sfaAYxW"
                                                          secret:@"JX994q7T9va9Rm6VNgrMw6hiLgllEQzhsB2T7TtXWhN5yYj2IZ"];

[client authorizeUsingOAuthWithRequestTokenPath:@"/oauth/request_token"
                          userAuthorizationPath:@"/oauth/authorize"
                                    callbackURL:[NSURL URLWithString:@"testapp://success"]
                                accessTokenPath:@"/oauth/access_token"
                                   accessMethod:@"GET"
                                        success:^(AFOAuth1Token *accessToken) {
                                            NSLog(@"Success: %@", accessToken);
                                        } failure:^(NSError *error) {
                                            NSLog(@"Error: %@", error);
                                        }];

Error trying to get Home Timeline

I am using AFOAuth1Client in order to Authenticate and then retrieve the Home Timeline of a given Twitter User. However when I run my code I get this error:

Error Domain=AFNetworkingErrorDomain Code=-1011 "Expected status code in (200-299), got 403" UserInfo=0x7fe160ca0070 {NSLocalizedRecoverySuggestion={"errors":[{"message":"Your credentials do not allow access to this resource","code":220}]}, NSErrorFailingURLKey=https://api.twitter.com/1.1/statuses/home_timeline.json, AFNetworkingOperationFailingURLRequestErrorKey=<NSMutableURLRequest: 0x7fe160ca88c0> { URL: https://api.twitter.com/1.1/statuses/home_timeline.json }, AFNetworkingOperationFailingURLResponseErrorKey=<NSHTTPURLResponse: 0x7fe160dad9b0> { URL: https://api.twitter.com/1.1/statuses/home_timeline.json } { status code: 403, headers {
    "Content-Encoding" = deflate;
    "Content-Length" = 94;
    "Content-Type" = "application/json;charset=utf-8";
    Date = "Wed, 31 Dec 2014 20:19:49 UTC";
    Server = "tsa_b";
    "Set-Cookie" = "guest_id=v1%3A142005718900451202; Domain=.twitter.com; Path=/; Expires=Fri, 30-Dec-2016 20:19:49 UTC";
    "Strict-Transport-Security" = "max-age=631138519";
    "x-connection-hash" = 2a42433adec68c7f4e4410d0df3e6713;
    "x-response-time" = 5;
    "x-spdy-version" = "3.1-NPN";
} }, NSLocalizedDescription=Expected status code in (200-299), got 403}

Here is how I am attempting to Authenticate:

SettingsViewController.m

- (void)authenticateWithTwitter  {
    self.twitterClient = [[AFOAuth1Client alloc] initWithBaseURL:[NSURL URLWithString:@"https://api.twitter.com/"]
                                                             key:@"XXXXXXXXXXXX"
                                                          secret:@"XXXXXXXXXXXX"];

    [self.twitterClient authorizeUsingOAuthWithRequestTokenPath:@"oauth/request_token"
                                          userAuthorizationPath:@"oauth/authorize"
                                                    callbackURL:[NSURL URLWithString:@"floadt://success"]
                                                accessTokenPath:@"oauth/access_token"
                                                   accessMethod:@"GET"
                                                          scope:nil
                                                        success:^(AFOAuth1Token *accessToken, id response) {
                                                            [AFOAuth1Token storeCredential:accessToken withIdentifier:@"TwitterToken"];
                                                            [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"twitterActive"];
                                                            [[NSUserDefaults standardUserDefaults] synchronize];
                                                        } failure:^(NSError *error) {
                                                            NSLog(@"Error: %@", error);
                                                        }];
}

StreamViewController.m

-(void)fetchTweets {
    AFOAuth1Token *twitterToken = [AFOAuth1Token retrieveCredentialWithIdentifier:@"TwitterToken"];
    [self.twitterClient setAccessToken:twitterToken];

    self.twitterClient = [[AFOAuth1Client alloc] initWithBaseURL:[NSURL URLWithString:@"https://api.twitter.com/1.1/"] key:@"XXXXXXXXX" secret:@"XXXXXXXXXX"];

    [self.twitterClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
    [self.twitterClient getPath:@"statuses/home_timeline.json" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSArray *responseArray = (NSArray *)responseObject;
        NSLog(@"Response: %@", responseObject);
        [responseArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
            tweets = responseArray;
        }];
        [self.tableView reloadData];
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Error: %@", error);
    }];
}

ForegroundObserver isn't removed

I remember this PR from @eriksundin aa789ce

that would take care of it.
It seems slightly altered now in 2.0, but from what I can tell, observers aren't being removed at all.

Here's a sample app
https://github.com/seivan/SHOmniAuthLinkedIn

Steps to reproduce

  1. Clone master https://github.com/seivan/SHOmniAuthLinkedIn

  2. Run sample

  3. Tap Add account on UIActionSheet button

  4. Tap Cancel on Linkedin auth

  5. Repeat 3) and 4)

You'd see three "null" messages in the console, you should only see two.

-requestWithMethod:path:parameters: with 'GET' method fails in version 0.3.0

I updated AFOAuth1Client to 0.3.0 and find my program failed with signature error from server. I tried to diagnose the problem today and found the cause is reversion 6bda44463131755f4a7d88e86d718a67c622dc5f.

The method checks if Content-Type header is application/x-www-form-urlencoded to decide whether the parameter argument is used for signature. And since it is not set for GET method, authorizationParameters is always nil, hence the signature is always wrong.

I've read RFC 5849, Section 3.4.1.3.1, and I believe the author missed the first item:

The query component of the HTTP request URI as defined by
[RFC3986], Section 3.4. The query component is parsed into a list
of name/value pairs by treating it as an
"application/x-www-form-urlencoded" string, separating the names
and values and decoding them as defined by
[W3C.REC-html40-19980424], Section 17.13.4.

I'm not sure what's the correct way to fix, hence I'll let the author to worry about it.

AFOAuth1Client to authenticate received 404

On my wordpress site, I have two plugins installed WP REST API (version 2.0-beta15) and WP REST API - OAuth 1.0a Server (version 0.3.0).

On my iOS app, I'm using AFNetworking and AFOAuth1Client to authenticate the app but I'm receiving the 404 error.

Here is the code I was testing:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.backgroundColor = [UIColor whiteColor];
    self.window.rootViewController = [[UITableViewController alloc] initWithStyle:UITableViewStylePlain];
    [self.window makeKeyAndVisible];

    self.twitterClient = [[AFOAuth1Client alloc] initWithBaseURL:[NSURL URLWithString:@"http://example.com/wp-json/"] key:@"WP Key" secret:@"WP secret"];

    [self.twitterClient authorizeUsingOAuthWithRequestTokenPath:@"/oauth1/request_token" userAuthorizationPath:@"/oauth1/authorize" callbackURL:[NSURL URLWithString:@"af-twitter://success"] accessTokenPath:@"/oauth1/access_token" accessMethod:@"POST" scope:nil success:^(AFOAuth1Token *accessToken, id responseObject) {

        [self.twitterClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
        [self.twitterClient getPath:@"statuses/user_timeline.json" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
            NSArray *responseArray = (NSArray *)responseObject;
            [responseArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
                NSLog(@"Success: %@", obj);
            }];
        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            NSLog(@"Error: %@", error);
        }];
    } failure:^(NSError *error) {
        NSLog(@"Error: %@", error);
    }];

    return YES;
}

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation
{
    NSNotification *notification = [NSNotification notificationWithName:kAFApplicationLaunchedWithURLNotification object:nil userInfo:[NSDictionary dictionaryWithObject:url forKey:kAFApplicationLaunchOptionsURLKey]];
    [[NSNotificationCenter defaultCenter] postNotification:notification];

    return YES;
}

Wrong sort order for AFHMACSHA1Signature

The OAuth RFC standard states in 3.4.1.3.2:

  1. The parameters are sorted by name, using ascending byte value ordering. If two or more parameters share the same name, they are sorted by their value.

AFHMACSHA1Signature sorts the parameters case insensitive which is not ascending byte value ordering. You should use case sensitve ordering instead:

NSString *queryString = AFPercentEscapedQueryStringPairMemberFromStringWithEncoding([[[[[request URL] query] componentsSeparatedByString:@"&"] sortedArrayUsingSelector:@selector(compare:)] componentsJoinedByString:@"&"], stringEncoding);

If you for example use OAuth with the SmugMug photo service, most API functions work fine, but the smugmug.albums.create function is not working correctly with AFOAuth1Client because SmugMug uses a Title parameter for this API function. With the current release Title is sorted after all the oauth_... parameters but it must be prior to this parameters because the uppercase 'T' is prior to the lowercase 'o' in byte value ordering.
This leads to an invalid signature error in the SmugMug API request.

about cocoapods and AFNetworking

Hi~
I add AFOAuth1Client and AFNetworking to my podfile, the cocoapods shows that AFOAuth1Client requires AFNetworking 1.3.4, so it installs AFNetworking 1.3.4 not the 2.0, many new methods cannot use, hope you can fix this problem : ]

AFOAuth1Client won't build against 2.0.0-rc1

This client doesn't build against AFNetworking 2.0.0-rc1, and doesn't specify 1.3 in the podfile, so new projects using it don't build out of the box without manually specifiying AFNetworking ~> 1.3. Should we just stick with manually specifying both pods in our workspace Podfiles for now, or get a patch in?

"Nonce check failed" when trying update object in api.

Hi, when I try update object in api I receive "Nonce check failed", but when I use getObjectsAtPath I get correct data.

NSString *name = @"john";
    C_Manager *m = [C_Manager new];
    RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:[m getObjectMapping] method:RKRequestMethodGET pathPattern:nil keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
    RKObjectManager *manager = [RKObjectManager sharedManager];
    [manager addResponseDescriptor:responseDescriptor];
    [manager getObjectsAtPath:[NSString stringWithFormat:@"%@managers/%@/", url_path, name] parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {

        C_Manager *mm = mappingResult.array.firstObject;
        DDLogInfo(@"---------------- response  result -----------------");
        DDLogInfo(@"response: %@", mm.username);
        mm.password = @"new_password";

        AFOAuth1Client *oauthClient = [[AFOAuth1Client alloc] initWithBaseURL:[NSURL URLWithString:oauth_url_access] key:oauth_consumer_key secret:oauth_consumer_secret];
        [oauthClient authorizeUsingOAuthWithRequestTokenPath:@"/oauth/request_token"
                                       userAuthorizationPath:@"/oauth/authorize"
                                                 callbackURL:[NSURL URLWithString:@"mycallback-ios://success"]
                                             accessTokenPath:@"/oauth/access_token"
                                                accessMethod:@"PATCH"
                                                       scope:nil
                                                     success:^(AFOAuth1Token *accessToken, id responseObject) {
                                                         DDLogInfo(@"%@  Success: %@", NSStringFromSelector(_cmd), accessToken);

                                                         //                                                         [oauthClient setAccessToken: accessToken];
                                                         [[RKObjectManager sharedManager] setHTTPClient:oauthClient];

                                                         // PATCH object
                                                         RKObjectMapping *requestMapping = [RKObjectMapping requestMapping];
                                                         [requestMapping addAttributeMappingsFromArray:@[@"password"]];
                                                         RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:requestMapping objectClass:[C_Manager class] rootKeyPath:nil method:RKRequestMethodPATCH];
                                                         [[RKObjectManager sharedManager] addRequestDescriptor:requestDescriptor];
                                                         [[RKObjectManager sharedManager] patchObject:mm path:@"/api/v1/managers/john/" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
                                                             DDLogWarn(@"!+!+!+!+!+------ %@", [mappingResult.array.firstObject valueForKey:@"email"]);
                                                         } failure:^(RKObjectRequestOperation *operation, NSError *error) {
                                                             DDLogError(@"%@ |::| Error: %@", NSStringFromSelector(_cmd), error);
                                                         }];
                                                     } failure:^(NSError *error) {
                                                         DDLogError(@"%@ Errror: %@", NSStringFromSelector(_cmd), error);
                                                     }];
    } failure:^(RKObjectRequestOperation *operation, NSError *error) {
        DDLogError(@"%@ |::| Error: %@", NSStringFromSelector(_cmd), error);
    }];

Output:

request.headers={
    "Accept-Language" = en;q=0.9, fr;q=0.8, de;q=0.7, ja;q=0.6, nl;q=0.5";
    Authorization = "..."
    "Content-Type" = "application/x-www-form-urlencoded; charset=utf-8";
    "User-Agent" = "(iPhone; iOS 7.1.2; Scale/2.00)";
}
request.body=password=new_password
2014-08-07 12:27:44.054 [17280:470b] E restkit.network:RKObjectRequestOperation.m:576 Object request failed: Underlying HTTP request operation failed with error: Error Domain=org.restkit.RestKit.ErrorDomain Code=-1011 "Expected status code in (200-299), got 401" UserInfo=0x157c2820 {NSLocalizedRecoverySuggestion={"detail": "Nonce check failed"}, AFNetworkingOperatnFailingURLRequestErrorKey=<NSMutableURLRequest: 0x1579bf60> { URL: https://api.url.be/api/v1/managers/john/ }, NSErrorFailingURLKey=https://api.url.be/api/v1/managers/john/, NSLocalizedDescription=Expected status code in (200-299), got 401, AFNetworkingOperationFailingURLResponseErrorKey=<NSHTTPURLResponse: 0x157d3820> { URL: https://api.url.be/api/v1/managers/john/ } { status code: 401, headers {
    Allow = "GET, PUT, PATCH, DELETE, HEAD, OPTIONS";
    Connection = "keep-alive";
    "Content-Language" = pl;
    "Content-Type" = "application/json";
    Date = "Thu, 07 Aug 2014 10:27:44 GMT";
    "Keep-Alive" = "timeout=20";
    "Transfer-Encoding" = Identity;
    Vary = "Accept, Accept-Language, Cookie";
    "Www-Authenticate" = "OAuth realm=\"api\"";
} }}
2014-08-07 12:27:44.061 [17280:470b] E restkit.network:RKObjectRequestOperation.m:238 PATCH 'https://api.url.be/api/v1/managers/john/' (401 Unauthorized / 0 objects) [request=0.4761s mapping=0.0000s total=0.4939s]:
error=Error Domain=org.restkit.RestKit.ErrorDomain Code=-1011 "Expected status code in (200-299), got 401" UserInfo=0x157c2820 {NSLocalizedRecoverySuggestion={"detail": "Nonce check failed"}, AFNetworkingOperationFailingURLRequestErrorKey=<NSMutableURLRequest: 0x1579bf60> { URL: https://api.url.be/api/v1/managers/john/ }, NSErrorFailingURLKey=https://api.url.be/api/v1/managers/john/, NSLocalizedDescription=Expected status code in (200-299), got 401, AFNetworkingOperationFailingURLResponseErrorKey=<NSHTTPURLResponse: 0x157d3820> { URL: https://api.url.be/api/v1/managers/john/ } { status code: 401, headers {
    Allow = "GET, PUT, PATCH, DELETE, HEAD, OPTIONS";
    Connection = "keep-alive";
    "Content-Language" = pl;
    "Content-Type" = "application/json";
    Date = "Thu, 07 Aug 2014 10:27:44 GMT";
    "Keep-Alive" = "timeout=20";
    "Transfer-Encoding" = Identity;
    Vary = "Accept, Accept-Language, Cookie";
    "Www-Authenticate" = "OAuth realm=\"api\"";
} }}
response.body={"detail": "Nonce check failed"}
 12:27:38:374 [17280:60b] patchTest  Success: <AFOAuth1Token: 0x157a0c80>

Last request is executed when switching from WIFI to 3g or vice versa

I've nearly finishing my application which is Rails API interfacing,I've noticed that the last network request is executed again when switching from 3G to WiFi or vice versa.
Here is an example of HTTP request and JSON response parsing

-(void)getServerData{
    __block NSError *error = nil;
    __block NSMutableDictionary *JSON;
    MBProgressHUD* progressHUD = [MBProgressHUD showHUDAddedTo:self.view animated:MBProgressHUDAnimationZoom];
    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    [[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status){
        progressHUD.labelText = @"Fetching Data";

        NSDictionary *parameters = @{@"id": [share auth_token]};
        [manager POST:[NSString stringWithFormat:@"%@%@", SERVERURI , DATAURL] parameters:parameters
              success:^(AFHTTPRequestOperation *operation, id responseObject) {
                  JSON = [NSJSONSerialization JSONObjectWithData: [operation.responseString dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error: &error];
                  //Door Names array filling
                  doorsData = [JSON objectForKey:@"data"];
                  [self.tableView reloadData];
                  [MBProgressHUD hideHUDForView:self.view animated:YES];
              }
              failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                  JSON = [NSJSONSerialization JSONObjectWithData: [operation.responseString dataUsingEncoding:NSUTF8StringEncoding] options: NSJSONReadingMutableContainers error: &error];
                  UIAlertView *notPermitted = [[UIAlertView alloc]
                                               initWithTitle:@"Error"
                                               message: [JSON valueForKey:@"message"]
                                               delegate:nil
                                               cancelButtonTitle:@"Back !"
                                               otherButtonTitles:nil];
                  // shows alert to user
                  [notPermitted show];
                  [MBProgressHUD hideHUDForView:self.view animated:YES];
              }];
      }];
    [manager.reachabilityManager startMonitoring];
}

I cannot find similar issue after searching , so can anyone help with that?!

Goodreads API failure and some workaround findings

I'm having troubles using AFOAuth1Client, specifically the access_token piece. Goodreads is Oauth 1, not 1a if that makes a difference.

They suggest using the OAuthConsumer code which does work - I was able to look at that to determine what some of the differences were between requests generated between the two libraries.

I only have a hacked and working version of this but not a clean code implementation. (It certainly doesn't take into account how compatible this might be with other OAuth1 access_token requests either.)

But this what I've found so far - I'll comment on this further as I find out more.

  1. Their access_token request is a GET not a POST
  2. The access_token request construction code should only have the oauth_token query param.
 - (void)acquireOAuthAccessTokenWithPath...
{
    // GOODREADS HACK CHANGE
    //NSMutableDictionary *parameters = [[self OAuthParameters] mutableCopy];
    NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init];
  1. Then I add the [OAuthParameters] to the mutableParams dict once we're creating the URLRequest
// GOODREADS HACK CHANGE
// new method adapted from AFOAuth1Client.requestWithMethod
- (NSMutableURLRequest *)requestForAccessTokenWithMethod:(NSString *)method
                                          path:(NSString *)path
                                    parameters:(NSDictionary *)parameters
                                    requestToken:(AFOAuth1Token *) requestToken
{
    NSMutableDictionary *mutableParameters = parameters ? [parameters mutableCopy] :          [NSMutableDictionary dictionary];
    // GOODREADS HACK CHANGE
    [mutableParameters addEntriesFromDictionary:[self OAuthParameters]];
  1. The OAuth signature creation code has 2 differences:
  1. The request token secret is used in conjunction with the application secret.
  2. The query param in this case oauth_token is included with the authorization params. In this instance, the request string used in the OAuth sig contains "oauth_token" twice -

GET&http%3A%2F%2Fwww.goodreads.com%2Foauth%2Faccess_token&oauth_consumer_key%3D[consumerKeyValue]%26oauth_nonce%3D9383CF2A-D611-4C93-9B6E-F3B0D6E77A3E%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1359649280%26oauth_token%3DEzn4noEYUA3aCWrQL99Q%26oauth_token%3DEzn4noEYUA3aCWrQL99Q%26oauth_version%3D1.0

I did create an alternate signature method that does this - I can post my hacked version of AFOAuth1Client if you'd like...but I can't say it's pretty ;)

LinkedIn OAuth1.0a fails

Two problems:

  • Content-Type needs to be text/xml. Probably nothing to be done here, since this seems very LinkedIn-only-ish.
  • "Properly handling oauth_token_secret" - Apparently 'Twitter is particularly lenient with the use of oauth_token_secret' (http://developer.linkedin.com/documents/common-issues-oauth-authentication). Maybe this deserves a pull-request update in AFOAuth1Client?

I made a subclass that works here: https://github.com/pj4533/AFLinkedInOAuth1Client

Interested to hear your thoughts. I'll make a pull request, if you think necessary.

LinkedIn wants different characters escaped

I was having trouble in my AFLinkedInOAuth1Client class, and tracked down the issue to the escaping function in AFOAuth1Client. I changed it to this to get it working:

static NSString * AFPercentEscapedQueryStringPairMemberFromStringWithEncoding(NSString *string, NSStringEncoding encoding) {
    static NSString * const kAFCharactersToBeEscaped = @":/?&=;+!@#$(),";
    static NSString * const kAFCharactersToLeaveUnescaped = @"[].~";
//    static NSString * const kAFCharactersToBeEscaped = @":/?&=;+!@#$()~";
//    static NSString * const kAFCharactersToLeaveUnescaped = @"[].";

    return (__bridge_transfer  NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, (__bridge CFStringRef)kAFCharactersToLeaveUnescaped, (__bridge CFStringRef)kAFCharactersToBeEscaped, CFStringConvertNSStringEncodingToEncoding(encoding));
}

Ideally, I'd like to be able to override the escapable characters in my subclass. Does it make sense to move this static function to something that could be easily overridden? Or maybe make the kAFCharactersToBeEscape/LeaveUnescaped as properties on the client?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.