So - I have identical AFNetworking code, that, when run on the simulator, returns results as expected, and gives me all the proper JSON back.
Soon as I run it on the device, I get a 401. Now, I understand this means 'unauthorized,' but how on earth does it run absolutely swimmingly on the simulator and then give me a 401 on the device?
The code is below and has only been changed to remove the address of our API which must remain private.
phoneNumber = phoneNumberField.text;
[[NSUserDefaults standardUserDefaults] setObject:phoneNumber forKey:#"phone_number"];
NSString *UDIDstring = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
NSLog(#"UDID: %#",UDIDstring);
NSString *jsonRequest = [NSString stringWithFormat:#"{\"userId\":\"%#\",\"userType\":\"%#\",\"deviceId\":\"%#\",\"deviceType\":\"%#\"}",phoneNumberField.text,#"Number",UDIDstring,#"iPhone"];
NSLog(#"json: %#",jsonRequest);
NSDictionary *stuff = [[NSDictionary alloc] initWithObjectsAndKeys:
phoneNumberField.text, #"userId",
#"Number", #"userType",
UDIDstring,#"deviceId",
#"iPhone",#"deviceType",
nil];
NSLog(#"stuff: %#",stuff);
NSError *error;
NSData *postData = [NSJSONSerialization dataWithJSONObject:stuff options:0 error:&error];
NSString *urlString = #"(hidden for privacy reasons)"
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString]
cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10];
NSString *userpass = [#"vclient:VastV1" base64EncodedString];
NSLog(#"userpass: %#",userpass);
[request setHTTPMethod:#"POST"];
[request setValue:[NSString stringWithFormat:#"Basic: %#",userpass] forHTTPHeaderField:#"Authorization"];
//[request setValue:#"*/*" forHTTPHeaderField:#"Accept"];
[request setValue: #"application/json" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request];
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
securityPolicy.allowInvalidCertificates = YES;
op.securityPolicy = securityPolicy;
op.responseSerializer = [AFJSONResponseSerializer serializer];
[op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON responseObject: %# ",responseObject);
[infoLabel setText:#"You have been sent an activation code to the number you used. Please enter it above."];
[signupLabel setText:#"your code:"];
[mainButton setTitle:#"Activate" forState:UIControlStateNormal];
firstSignup=true;
[phoneNumberField setText:#""];
[phoneNumberField setPlaceholder:#"Enter activation code."];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", [error localizedDescription]);
}];
[op start];
One difference would be that you are reporting a different device ID. Maybe the API that you are using keeps track of device IDs that have been authorized. And your Mac has been authorized, but the iOS device hasn't.
You could try logging the device id on the Mac, and then change your code to use that ID as a hardcoded string, instead of using what the iPhone returns.
You can try this, I do it all the time
#import "AFNetworking.h"
NSDictionary *params = #{ #"key1": txtBox1.text, #"key2", txtbox2.text};
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
AFJSONRequestSerializer *serializerRequest = [AFJSONRequestSerializer serializer];
AFJSONResponseSerializer *serializerResponse = [AFJSONResponseSerializer serializer];
[serializerRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"]];
serializerResponse.acceptableContentTypes = [NSSet setWithObject:#"application/json"];
manager.requestSerializer = serializerRequest;
manager.responseSerializer = serializerResponse;
[manager.securityPolicy setAllowInvalidCertificates:YES];
[manager POST:#"url"
parameters:params
success:^(AFHTTPRequestOperation *operation, id responseObject) {
// DO WHAT YOU WANT IF SUCCESSED
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// DO WHAT YOU WANT IF FAILED
}];
Are you using an authentication scheme that depends on the time? I've seen drift on the simulator that causes it to 401.
Related
I'm using AFNetworking to post data into the web. The information I have is the URI which is baseURL/post_user_info and they want input as A JSON object containing each of the name-value pairs. In the code written below I've set the name-value pair in a dictionary. My question is how to make it's json and send it as input value?
NSString *string = [NSString stringWithFormat:#"%#?post_user_info",BaseURLString];
NSString *escapedPath = [string stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
NSDictionary *params = #{#"input_1": #"hello world",
#"input_2": #"my#you.com",
#"input_3": #"newworldorder"};
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:params options:kNilOptions error:nil];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setHTTPBody:jsonData];
[manager POST:escapedPath parameters:[[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding] progress:nil success:^(NSURLSessionTask *task, id responseObject)
{
NSLog(#"%#",responseObject);
}failure:^(NSURLSessionTask *operation, NSError *error)
{
NSLog(#"%#",[error localizedDescription]);
}];
I've updated the code because now I have generated the JSON but if I run the code now it give me Error: 400 which means If input_values is empty, a bad request error will be output.
#interface AFJSONRequestSerializer : AFHTTPRequestSerializer
AFJSONRequestSerializeris a subclass ofAFHTTPRequestSerializerthat encodes parameters as JSON using NSJSONSerialization.
add this AFJSONRequestSerializer is used for send JSON not a Raw Data add this and try once
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
e.g
NSString *string = [NSString stringWithFormat:#"%#?post_user_info",BaseURLString];
NSString *escapedPath = [string stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
/************** karthik Code added ******************/
AFHTTPSessionManager* manager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
/************** karthik Code added ******************/
NSDictionary *params = #{#"1": #"hello world",
#"2": #"my#you.com",
#"3": #"newworldorder"};
[manager POST:escapedPath parameters:params progress:nil success:^(NSURLSessionTask *task, id responseObject)
{
NSLog(#"%#",responseObject);
NSError *error = nil;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:nil];
NSLog(#"json == %#", json);
} failure:^(NSURLSessionTask *operation, NSError *error) {
NSLog(#"%#", [error localizedDescription]);
}];
Update Params
NSDictionary *params = #{#"1": #"hello world",
#"2": #"my#you.com",
#"3": #"newworldorder"};
NSMutableDictionary *modify = [NSMutableDictionary new];
[modify setObject:params forKey:#"input_values"];
you get output of
I am invoking A API its required Authorisation header.
this is API need on given URL
username : testingyouonit#gmail.com
password : testingyouonit2
to create the Authorisation header
step 1 - do a base64 encoding of the given password.
step 2 - do a SHA256 hash on the password obtained in step 1
step 3 - use the password obtained in step 2 and given username to create the authorization header
Now i am passing request using AFNetworking
NSString *email=#"testingyouonit#gmail.com";
NSString *password=[self encodeStringTo64:#"testingyouonit2"];
Here i encoded my password
- (NSString*)encodeStringTo64:(NSString*)fromString
{
NSData *plainData = [fromString dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64String;
if ([plainData respondsToSelector:#selector(base64EncodedStringWithOptions:)]) {
base64String = [plainData base64EncodedStringWithOptions:kNilOptions];
} else {
base64String = [plainData base64Encoding];
}
return base64String;
}
Now i am passing GET Request
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
[manager.requestSerializer setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[manager.requestSerializer setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
[manager.requestSerializer setAuthorizationHeaderFieldWithUsername:email password:password];
[manager.requestSerializer setValue:#"CAS256" forHTTPHeaderField:#"Authorization"];
[manager GET:#"https://myurlhere/youit" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
Now each time i am getting this
Error: Error Domain=com.alamofire.error.serialization.response Code=-1011 "Request failed: bad request (400)" UserInfo=0x7c361610 {com.alamofire.serialization.response.error.response=<NSHTTPURLResponse: 0x7aed9220> { URL: https://myurlhere/youit } { status code: 400, headers {
"Access-Control-Allow-Origin" = "*";
Connection = "keep-alive";
"Content-Length" = 114;
"Content-Type" = "application/json";
Date = "Sat, 11 Jul 2015 02:56:46 GMT";
Server = "nginx/1.1.19";
} }, NSErrorFailingURLKey=https://myurlhere/youit, NSLocalizedDescription=Request failed: bad request (400), com.alamofire.serialization.response.error.data=<7b0a2020 22657272 6f725f63 6f646522 3a202269 6e76616c 69645f61 7574685f 68656164 6572222c 0a202022 6d657373 61676522 3a202249 6e76616c 69642061 7574686f 72697a61 74696f6e 2e205573 6520616e 20617574 68206865 61646572 206f7220 61636365 73732068 61736822 0a7d>}
where is the mistake i am doing to make basic Auth
Lets create SHA256 and pass it password and try it
NSString *email=#"testingyouonit#gmail.com";
NSString *password=[self encodeStringTo64:#"testingyouonit2"];
add one more method to generate a Sha256 password and pass in to request
Step-1 using this method you need to #include <CommonCrypto/CommonDigest.h>
-(NSString*)sha256HashFor:(NSString*)input
{
const char* str = [input UTF8String];
unsigned char result[CC_SHA256_DIGEST_LENGTH];
CC_SHA256(str, strlen(str), result);
NSMutableString *ret = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH*2];
for(int i = 0; i<CC_SHA256_DIGEST_LENGTH; i++)
{
[ret appendFormat:#"%02x",result[i]];
}
return ret;
}
and call this
Note : pass here encoded password you used
NSString *password=[self encodeStringTo64:#"testingyouonit2"];
`password=[self sha256HashFor: password];`
and final step
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
[manager.requestSerializer setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[manager.requestSerializer setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
[manager.requestSerializer setAuthorizationHeaderFieldWithUsername:email password:password];
[manager GET:#"https://myurlhere/youit" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
let me see the result
You aren't constructing the header correctly. See the "client side" section here.
Incidentally, you are getting an error 400 which means your request is bad. If it was a security issue, you would be getting a 401. So, fix the Authorization header, but look further for the problem with your request.
try below code
NSString *URLString = #"url";
NSData *data = [NSJSONSerialization dataWithJSONObject:parameters options:NSJSONWritingPrettyPrinted error:nil];
NSString *jsonStr = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSString *username = [[NSUserDefaults standardUserDefaults] objectForKey:#"userName"];
NSString *password = [[NSUserDefaults standardUserDefaults] objectForKey:#"password"];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSURLCredential *credential = [NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistenceNone];
NSString *authenticationString = [NSString stringWithFormat:#"%#:%#", username, password];
NSData *authenticationData = [authenticationString dataUsingEncoding:NSASCIIStringEncoding];
NSString *authenticationValue = [authenticationData base64EncodedStringWithOptions:0];
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:URLString] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:20.0f];
[theRequest setHTTPMethod:#"POST"];
[theRequest setValue:[NSString stringWithFormat:#"Basic %#", authenticationValue] forHTTPHeaderField:#"Authorization"];
[theRequest setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[theRequest setValue:#"application/json; charset=UTF-8" forHTTPHeaderField:#"Content-Type"];
[theRequest setHTTPBody:[jsonStr dataUsingEncoding:NSUTF8StringEncoding]];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:theRequest];
[operation setCredential:credential];
[operation setResponseSerializer:[AFJSONResponseSerializer alloc]];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failure: %#", error);
}];
[manager.operationQueue addOperation:operation];
For people using AFNetworking 3.x here is full solution that worked for me.
This code sends file with basic authentication. Just change url, email and password.
NSString *serverUrl = [NSString stringWithFormat:#"http://www.yoursite.com/uploadlink", profile.host];
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] requestWithMethod:#"POST" URLString:serverUrl parameters:nil error:nil];
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
// Forming string with credentials 'myusername:mypassword'
NSString *authStr = [NSString stringWithFormat:#"%#:%#", email, emailPassword];
// Getting data from it
NSData *authData = [authStr dataUsingEncoding:NSASCIIStringEncoding];
// Encoding data with base64 and converting back to NSString
NSString* authStrData = [[NSString alloc] initWithData:[authData base64EncodedDataWithOptions:NSDataBase64EncodingEndLineWithLineFeed] encoding:NSASCIIStringEncoding];
// Forming Basic Authorization string Header
NSString *authValue = [NSString stringWithFormat:#"Basic %#", authStrData];
// Assigning it to request
[request setValue:authValue forHTTPHeaderField:#"Authorization"];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
NSURL *filePath = [NSURL fileURLWithPath:[url path]];
NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithRequest:request fromFile:filePath 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
LLog(#"progres increase... %# , fraction: %f", uploadProgress.debugDescription, uploadProgress.fractionCompleted);
});
} completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error) {
NSLog(#"Error: %#", error);
} else {
NSLog(#"Success: %# %#", response, responseObject);
}
}];
[uploadTask resume];
I'm getting error Request failed: bad request (400) while trying to post in LInkedIn
Below is my code
-(IBAction)btnLinkedIdShareClicked:(id)sender{
NSString *stringRequest = [NSString stringWithFormat:#"https://api.linkedin.com/v1/people/~/shares?oauth2_access_token=%#&format=json",[[NSUserDefaults standardUserDefaults] valueForKey:LINKED_IN_ACCESS_TOKEN]];
//Request parameter on a dictionary (keys in camel case)
NSDictionary *update = [[NSDictionary alloc] initWithObjectsAndKeys:[[NSDictionary alloc] initWithObjectsAndKeys: #"anyone",#"code",nil], #"visibility",
#"TEST", #"comment",[[NSDictionary alloc] initWithObjectsAndKeys:#"description share", #"description", #"link_url", #"submittedUrl", #"title share",#"title", #"image_url",#"submittedImageUrl",nil], #"content",nil];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
AFJSONRequestSerializer *requestSerializer = [AFJSONRequestSerializer serializer];
[requestSerializer setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[requestSerializer setValue:#"application/json" forHTTPHeaderField:#"Accept"];
manager.requestSerializer = requestSerializer;
[manager POST:stringRequest parameters:update success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"result: %#", responseObject);
//completionBlock(YES, responseObject, nil);
NSLog(#"Yes");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"%#",[error localizedDescription]);
NSLog(#"No");
}];
}
Thanks in advance, any solution to resolve this...?
It seems that AFNetworking isn't working correctly for me. Specifically when I send apiKey request to server it gives me an unauthorized error. ASIHTTPRequest works fine for me however, so there seems to be something I am doing wrong in AFNetWorking. I know the problem is sending apiKey because if I comment it out AFNetWork works correctly. I still need to send the API key however. Any help will be appreciated.
AFNetWorking
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager.requestSerializer setValue:apiKey forHTTPHeaderField:#"apiKey"];
NSMutableDictionary *userinfo = [[NSMutableDictionary alloc] init];
[manager POST:urlStr parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
[operation setUserInfo:userinfo];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[operation setUserInfo:userinfo];
}];
}
ASIHTTPRequest
NSString *urlStr = [NSString stringWithFormat:#"%#/%#", submitReportUrl, [self urlEncode:path]];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:urlStr]];
[request setDelegate:self];
NSMutableDictionary *userinfo = [[NSMutableDictionary alloc] init];
[userinfo setObject:NSStringFromSelector(self.didFinishSelector) forKey:#"didFinishSelector"];
[userinfo setObject:NSStringFromSelector(self.didFailSelector) forKey:#"didFailSelector"];
[request setUserInfo:userinfo];
[request addRequestHeader:#"apiKey" value:apiKey];
[request setRequestMethod:method];
NSArray *keys = [params allKeys];
for ( NSString *key in keys )
[request addPostValue:[params objectForKey:key] forKey:key];
[self.operationQueue addOperation:request];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
I had the same problem working with the post. So research where was the problem. If you did not add the about line of the code. AFNetworking will automatically add in the header
Content-Type : "text/html"
either one
Cotent-Type : "text/plain"
By adding above code becomes
Content-Type : "application/json"
So the problem is solved. Since the server is expecting JSON.
I have the following code below that uses a rather old library called ASIHTTPRequest. I am looking to upgrade the library, but need a little help to make sure I am doing it correctly and to get my feet wet. This is the code I need to convert to AFNetworking. Any tips or suggestions is appreciated.
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:urlStr]];
[request setDelegate:self];
NSMutableDictionary *userinfo = [[NSMutableDictionary alloc] init];
[userinfo setObject:NSStringFromSelector(self.didFinishSelector) forKey:#"didFinishSelector"];
[userinfo setObject:NSStringFromSelector(self.didFailSelector) forKey:#"didFailSelector"];
[request setUserInfo:userinfo];
[request setUserAgentString:USER_AGENT];
[request setTimeOutSeconds:60];
[request addRequestHeader:#"apiKey" value:apiKey];
[request setRequestMethod:method];
With AFNetworking the code should look like below
NSDictionary *parameters=#{"key":value};//The values you want to POST arrange in dictionary.
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager.requestSerializer setValue:apiKey forHTTPHeaderField:#"apiKey"];
[manager.requestSerializer setValue:USER_AGENT forHTTPHeaderField:#"User-Agent"];
[manager.requestSerializer setTimeoutInterval:60];
[manager POST:urlStr parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Result %#",responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"%#",error.description);
}];
I hope it helps. Cheers.