How to do HTTPS GET request AFNetworking - ios

This is the method I use to do HTTP GET request. How can I change it to use HTTPS?
AS_NET_BASE_URL = http://www.myapp.com
Is it just as simple as replacing the http:// with https:// ?
Thank you in advance
+(void)startGETRequestAtUrlRoute:(NSString *)route withParameters:(NSString *)slashSeparatedParams completion:(void (^)(BOOL, id))completion{
//If internet is rachable, start request
if ([self isInternetReachable]) {
//Where request is going
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:AS_NET_BASE_URL]];
NSString *path = [NSString stringWithFormat:#"%#%#%#", AS_NET_BASE_URL, route, slashSeparatedParams];
//Tell operation to expect JSON
[httpClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
[httpClient setDefaultHeader:#"Accept" value:#"application/json"];
//Start spinner
[self startNetworkIndicator];
//Set up actual GET request
[httpClient getPath:path
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
//Stop spinning
[self stopNetworkIndicator];
//Make the response JSON valid
if (responseObject) {
completion(YES, responseObject);
}
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[self stopNetworkIndicator];
completion(NO, NULL);
//Error
NSLog(#"%#", error);
}
];
//No internet connection
}else{
completion(NO, NULL);
}
}

Yes.
HTTP/HTTPS is determined by the scheme of the URL, which in your case is specified in AS_NET_BASE_URL.

Related

AFNetworking request header missing after being set

I'm attempting to set custom headers on a per-request basis using AFNetworking, but occasionally the headers will seemingly disappear after being set. Below is the code used to make a request...
+ (void) getWithURI: (NSString*) uri header: (NSDictionary*) header success: (NSString*) successCallback failure: (NSString*)errorCallback dispatch: (NSString*)dispatchedId
{
createManagerInstance();
AFHTTPRequestOperation* operation = [manager GET:uri
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
[RestWrapper succeededWithJson:operation.responseString dispatchedId:dispatchedId successCallback:successCallback];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[RestWrapper failedWithJson:operation.responseString dispatchedId:dispatchedId errorCallback:errorCallback];
}];
NSMutableURLRequest* request = (NSMutableURLRequest*)operation.request;
for (NSString* key in header)
{
if([request valueForHTTPHeaderField:key] != nil)
{
[request setValue:header[key] forHTTPHeaderField:key];
}
else
{
[request addValue:header[key] forHTTPHeaderField:key];
}
}
NSLog(#"Headers: %#", request.allHTTPHeaderFields);
[operation start];
}
For 95% of my requests, they go through as anticipated. Sporadically, however, some will fail and indicate a header is missing. This has been confirmed by capturing the requests in question using Fiddler and seeing that the headers are actually missing. Despite this, the console log of request.allHTTPHeaderFields always shows the headers in place.
The only other thing I noticed is that in general Fiddler reports the caching policy as "max-age=0, private, must-revalidate" for each request. However, whenever a request loses the custom headers, it's caching policy is "no-cache".
This is because you're adding HTTP Header fields in wrong way.
You should add it before request. You may try something like this :
+ (void) getWithURI: (NSString*) uri header: (NSDictionary*) header success: (NSString*) successCallback failure: (NSString*)errorCallback dispatch: (NSString*)dispatchedId{
createManagerInstance();
manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager.requestSerializer setValue:header[key] forHTTPHeaderField:key];
AFHTTPRequestOperation* operation = [manager GET:uri
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
[RestWrapper succeededWithJson:operation.responseString dispatchedId:dispatchedId successCallback:successCallback];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[RestWrapper failedWithJson:operation.responseString dispatchedId:dispatchedId errorCallback:errorCallback];
}];
[operation start];
}

AFNetworking making requests while offline

So I am trying to handle posting something to server and this works while the iPhone is with internet. Now I need to handle the request if there is no internet. I tried a bit of code below tho handle operation queue in relation to reachability. I dont think I need cache as I'm posting. What am I missing here? I want the request to be sent soon as the internet is available. While I might be doing something else in the app. The only thing I suspect is that my OperationManager is initialised in each request like POST or GET so maybe the previous one could be wipeout. But that is operation manager and not operation queue.
- (void)sendRequestPOST:(NSString *)url parameters:(NSMutableDictionary *)parameters {
NSLog(#"POST Request URL : %#", url);
NSLog(#"POST Request Body : %#", parameters);
__block AFHTTPRequestOperation *opr;
[[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
AFJSONRequestSerializer *jsonRS = [[AFJSONRequestSerializer alloc] init];
[manager setRequestSerializer:jsonRS];
[[manager requestSerializer] setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[[manager requestSerializer] setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[[manager responseSerializer] setAcceptableContentTypes:[NSSet setWithObjects:#"application/json", #"text/html", nil]];
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
NSLog(#"Reachability: %#", AFStringFromNetworkReachabilityStatus(status));
}];
NSOperationQueue *operationQueue = manager.operationQueue;
[manager.reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
switch (status) {
case AFNetworkReachabilityStatusReachableViaWWAN:
case AFNetworkReachabilityStatusReachableViaWiFi:
[operationQueue setSuspended:NO];
break;
case AFNetworkReachabilityStatusNotReachable:
default:
[operationQueue setSuspended:YES];
break;
}
}];
[manager.reachabilityManager startMonitoring];
[manager POST:url parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
[MBProgressHUD hideHUDForView:self.mainView animated:YES];
opr = operation;
[self.mainView setUserInteractionEnabled:YES];
NSLog(#"POST Response : %#",responseObject);
NSLog(#"Status Code : %ld",(long)[[operation response] statusCode]);
if([_delegate respondsToSelector:#selector(didFinish:dictInfo:)]) {
[AFNetworkActivityIndicatorManager sharedManager].enabled = NO;
[_delegate didFinish:self dictInfo:(NSMutableDictionary *)responseObject];
NSLog(#"Request finished");
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
opr = operation;
[MBProgressHUD hideHUDForView:self.mainView animated:YES];
[self.mainView setUserInteractionEnabled:YES];
NSLog(#"POST Error: %#", error);
// [[AFHTTPRequestOperationManager manager].operatonQueue addOperation:operation];
if([_delegate respondsToSelector:#selector(failRequest:statusCode:)]) {
[AFNetworkActivityIndicatorManager sharedManager].enabled = NO;
[_delegate failRequest:self statusCode:[[operation response] statusCode]];
NSLog(#"Request failed");
}
}];}
I wrote a Swift pod that allows network requests to be wrapped in a way that they can be enqueued regardless of current network connectivity and saved until it goes through - https://cocoapods.org/pods/OfflineRequestManager. Might be useful to anybody seeing this.
The simplest use case would look something like the following, though most actual cases (saving to disk, specific request data, etc.) will have a few more hoops to jump through:
import OfflineRequestManager
class SimpleRequest: OfflineRequest {
func perform(completion: #escaping (Error?) -> Void) {
doMyNetworkRequest(withCompletion: { response, error in
handleResponse(response)
completion(error)
})
}
}
///////
OfflineRequestManager.defaultManager(queueRequest: SimpleRequest())

AFJSONRequestOperation not working (postpath works)

I am trying to post a JSON using AFNetworking.
Here's the code that im using:
+ (RESTAPI *)sharedClient
{
static RESTAPI *_sharedClient = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_sharedClient = [[self alloc] initWithBaseURL:[NSURL URLWithString:#"https://mybaseurl.com"]];
});
return _sharedClient;
}
- (id)initWithBaseURL:(NSURL *)url
{
self = [super initWithBaseURL:url];
if (!self) {
return nil;
}
[self setParameterEncoding:AFJSONParameterEncoding];
[self registerHTTPOperationClass:[AFJSONRequestOperation class]];
[self setDefaultHeader:#"Accept" value:#"application/json"];
[self setAllowsInvalidSSLCertificate:YES];
return self;
}
The following code does not works. Everytime i try i get the following error:
The operation couldn’t be completed. (NSURLErrorDomain error -1012.)
// this code does not works
//
- (void)loginNOTWORKING
{
RESTAPI *client = [RESTAPI sharedClient];
[[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES];
[[AFNetworkActivityIndicatorManager sharedManager] incrementActivityCount];
NSDictionary *parameter = #{#"tgout": #"1",
#"tgin": #2,
#"username": #"foo",
#"password":#"bar"};
NSURLRequest *request = [client requestWithMethod:#"POST" path:#"/login" parameters:parameter];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
// code for successful return goes here
[[AFNetworkActivityIndicatorManager sharedManager] decrementActivityCount];
NSLog(#"THIS IS NEVER CALLED: %#", JSON);
// do something with return data
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
// code for failed request goes here
[[AFNetworkActivityIndicatorManager sharedManager] decrementActivityCount];
NSLog(#"SAD, VERY SAD: %#", error.localizedDescription);
// do something on failure
}];
[operation start];
}
This code works:
// this code WORKS
- (void)loginWORKING
{
RESTAPI *client = [RESTAPI sharedClient];
[[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES];
[[AFNetworkActivityIndicatorManager sharedManager] incrementActivityCount];
NSDictionary *parameter = #{#"tgout": #"1",
#"tgin": #2,
#"username": #"foo",
#"password":#"bar"};
[client postPath:#"/login" parameters:parameter success:^(AFHTTPRequestOperation *operation, id responseObject) {
// Print the response body in text
NSLog(#"IT WORKS: %#",responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Response: %#", error.localizedDescription);
}];
}
Why the first login method does not works? What am i doing wrong?
Try by replacing
NSURLRequest *request = [client requestWithMethod:#"POST" path:#"/login" parameters:parameter];
with
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"/*HERE THE URL STRING TO CALL*/"]]
You can find the error -1012 in file CFNetworkErrors.h:
kCFURLErrorUserCancelledAuthentication = -1012
"The connection failed because the user cancelled required authentication."
I guess, there is an issue with your authentication. The error description is possibly misleading with regard to "the user" - it is actually a delegate method that gets invoked which cancels the authentication, or the authentication simply fails.
This of course can be caused by not properly serializing the parameters. I would suggest to use a lower level API, create the request manually, encode the JSON manually with NSJSONSerialization, and set the body data and the URL of the request. IMHO, this is certainly more readable code, and likely requires less code.

AFHttpclient get json body in block but outer function returns null

I am trying to send post request on some url and in body to be only json data (trying to register new user sending json like
{
"username": "test",
"password": "test",
"email": "email#gmail.com"
}
I have function like
-(NSString*) sendPostOnUrl:(NSString*) url
withParameters:(NSDictionary*)params{
__block NSString* response = nil;
NSError *error;
NSURL *u = [NSURL URLWithString:url];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL: u];
[httpClient postPath:REGISTER
parameters:params
success:^(AFHTTPRequestOperation *operation, id responseObject) {
response = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSLog(#"Request Successful, response '%#'", response);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"[HTTPClient Error]: %#", error.localizedDescription);
}];
return response;
}
where params are NSDictionary with keys username, password and email and values for those keys.
Problem is when I send I always in return get null in response (the latest line) but in NSLog I get json response.. I am very new to ios, and it looks to me that I need to sync on some way block with return from function but don't know how, can anybody give me a clue what am I doing wrong ? (params contains all those keys when I try to debug, url is ok, REGISTER is NSString constant)
Blocks are asynchronous - the problem here is that "response = [[NSString alloc] initWithData..." is within the block which gets executed after you've exited the method. A better approach is to not do this in a method, instead place this code where you were calling sendPostOnUrl:withParameters: and do whatever it is you need to do within the success block. So instead of:
self.something = [self sendPostOnUrl:url withParameters:#{"username":"test" etc}];
you do this:
NSError *error;
NSURL *u = [NSURL URLWithString:url];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL: u];
__weak YourClassName *me = self;
[httpClient postPath:REGISTER
parameters:params
success:^(AFHTTPRequestOperation *operation, id responseObject) {
me.something = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSLog(#"Request Successful, response '%#'", response);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"[HTTPClient Error]: %#", error.localizedDescription);
}];
Also, take note of "__weak YourClassName *me = self", you cannot reference self within a block because it will cause a retain cycle.

AFNetworking POST Never Succeeding - Unexpected Behavior Occurring on Different Devices

I am currently developing an iOS app that allows a user to post a classified listing for other users to see. On all devices, that app hangs in a "O% Uploaded" SVProgressHUD for a while before displaying "Our server is temporarily unavailable. Please try again later.", which is what I have coded in the case of a Status Code 500 error from the server side. However, on the iOS simulator, everything works smoothly.
All other functionality involving network requests is working perfectly except for this, so it must have something to do with the actual upload process. I've posted the corresponding code below; if you require anything additional to help figure this out, please let me know.
Networking Code
- (IBAction)publishPressed:(UIBarButtonItem *)sender {
[SVProgressHUD showWithStatus:#"Loading..." maskType:SVProgressHUDMaskTypeBlack];
// Set the params for the API call in an NSMutableDictionary called mutableParams.
// Create the form request with the post parameters and image data to pass to the API.
NSMutableURLRequest *request = [[UAPIClient sharedClient] multipartFormRequestWithMethod:#"POST"
path:#"mobPost.php"
parameters:mutableParams
constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
if (self.imageHasBeenSet) {
[self.listingImageView.image fixOrientation];
NSData *imageData = UIImagePNGRepresentation(self.listingImageView.image);
[formData appendPartWithFileData:imageData name:#"userfile"
fileName:#"postImage.png" mimeType:#"image/png"];
}
}];
// Create the `AFJSONRequestOperation` from the form request, with appropriate success and failure blocks.
AFJSONRequestOperation *operation = [[AFJSONRequestOperation alloc] initWithRequest:request];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseJSON) {
if ([[responseJSON objectForKey:#"status"] intValue] == 1) {
dispatch_async(dispatch_get_main_queue(), ^{
[SVProgressHUD showSuccessWithStatus:#"Success!"];
});
// Pass a message back to the delegate so that the modal view controller
// can be dismissed successfully.
[self.delegate uCreateListingTableViewController:self didCreateListing:YES];
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[SVProgressHUD showErrorWithStatus:#"Post failed. Please try again."];
});
NSLog(#"Status %#", [responseJSON objectForKey:#"status"]);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
dispatch_async(dispatch_get_main_queue(), ^{
[SVProgressHUD showErrorWithStatus:#"Our server is temporarily unavailable. Please try again later."];
});
}];
[operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
dispatch_async(dispatch_get_main_queue(), ^{
[SVProgressHUD showSuccessWithStatus:[[NSString stringWithFormat:#"%lli", (totalBytesWritten / totalBytesExpectedToWrite)] stringByAppendingString:#"% Uploaded"]];
});
}];
[[UAPIClient sharedClient] enqueueHTTPRequestOperation:operation];
}
UAPIClient.m
#import "UAPIClient.h"
#import "AFJSONRequestOperation.h"
static NSString * const kUAPIBaseURLString = #"hiding string for privacy";
#implementation UAPIClient
+ (UAPIClient *)sharedClient {
static UAPIClient *_sharedClient;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedClient = [[UAPIClient alloc] initWithBaseURL:[NSURL URLWithString:kUAPIBaseURLString]];
});
return _sharedClient;
}
- (id)initWithBaseURL:(NSURL *)url {
self = [super initWithBaseURL:url];
if (self) {
[self registerHTTPOperationClass:[AFJSONRequestOperation class]];
// Accept HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
[self setDefaultHeader:#"Accept" value:#"application/json"];
}
return self;
}
#end

Resources