I am trying to add a custom header to all the http request from the app but on server side I am not getting it.
I tried following methods:
1.setting header in NSMutableURLRequest:
[request addValue:headerString forHTTPHeaderField:#"deviceDetails"];
NSLog( #"%#",[request valueForHTTPHeaderField:#"deviceDetails"]);
Here I get null just after setting the header value. Not sure what is happening.
2.setting default header in RKObjectManager
[manager.HTTPClient setDefaultHeader:#"deviceDetails" value:headerString];
Here header seems to be set but on server there is no header field with key "deviceDetails"
Any help would be appreciated.
Code:
NSMutableURLRequest *request =[self _createPostRequestWithParams:[NSJSONSerialization dataWithJSONObject:params options:NSJSONWritingPrettyPrinted error:nil] andPath:path];
[request setTimeoutInterval:20];
NSLog(#"%#",[request valueForHTTPHeaderField:#"deviceDetails"]);
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:BASE_URL]];
[manager setRequestSerializationMIMEType:#"application/json"];
[manager.HTTPClient setAuthorizationHeaderWithUsername:self.offlineService.user.username password:self.offlineService.user.password];
[manager addResponseDescriptor: [self _getResponseDescriptorWithKeyPath:keyPath andResponseClass:responseClass]];
[manager.HTTPClient setDefaultHeader:#"deviceDetails" value:#"String value" encoding:NSUTF8StringEncoding]];
RKObjectRequestOperation *operation = [self _createOperationForRequest:request successcallback:requestSuccessful failurecallback:requestFailure target:target manager:manager];
[operation start];
_createOperationForRequest:
- (RKObjectRequestOperation *)_createOperationForRequest:(NSMutableURLRequest *)request successcallback:(SEL)requestSuccessful failurecallback:(SEL)requestFailed target:(id)target manager:(RKObjectManager *)manager {
RKObjectRequestOperation *operation = [manager objectRequestOperationWithRequest:request
success:^(RKObjectRequestOperation *operation,RKMappingResult *result) {
}
failure:^(RKObjectRequestOperation *operation,NSError *error){
}];
return operation;
}
In above code both basic authentication and device details header are received on the server side.
Related
I have been using Restkit to connect to my API server, and it works perfectly. Now my situation is that I added a checker in my appdelegate.m in didFinishLaunchingWithOptions. it checks if there is already adminID in the coredata. if there was a adminID stored, when the app is relaunched, it will set the rootviewcontroller into a uinavigation controller. but when the uiviewcontroller is called, the Restkit enqueueObjectRequestOperation is not called.
Here's my code:
in appdelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//adminID is fetch from custom Entity in core data
if(adminID==0){
AllKommunScreenViewController *adminController = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"AllKommunScreenID"];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:adminController];
self.window.rootViewController = navController;
}
return YES;
}
Here's my code in the Navigation controller's Rootview:
-(void)fetchData{
RKObjectMapping *responseMapping = [RKObjectMapping mappingForClass:[Auth class]];
[responseMapping addAttributeMappingsFromArray:#[#"status", #"sucess", #"data"]];
NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
RKResponseDescriptor *userProfileDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:responseMapping method:RKRequestMethodAny pathPattern:nil keyPath:nil statusCodes:statusCodes];
NSString *apiPath = [NSString stringWithFormat:#"%#%#", baseURL,#"/api/kommun/all/stats/"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:apiPath]];
request setValue:_sharedManager.userAccessToken forHTTPHeaderField:#"X-ACCESS-TOKEN"];
RKObjectRequestOperation *operation =[[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:#[userProfileDescriptor]];
[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {} failure:^(RKObjectRequestOperation *operation, NSError *error) {}];
[RKObjectManager sharedManager] enqueueObjectRequestOperation:operation];
}
i called the fetchData in viewWillAppear.
Then i add a breakpoint to the function, and it goes there, the problem is that the restkit is not calling the enqueueObjectRequestOperation.
Please help!!!
By the way, i make a custom core data entity to store the adminID
Why are you calling?
[RKObjectManager sharedManager] enqueueObjectRequestOperation:operation];
I think you should call
RKObjectRequestOperation *operation =[[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:#[userProfileDescriptor]];
[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
//print something
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
// print something
}];
[operation start];
If you want to add it to queue of Object Request Operations you should first init RKObjectManager and than call enqueueObjectRequestOperation:
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:baseUrl];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:apiPath]];
request setValue:_sharedManager.userAccessToken forHTTPHeaderField:#"X-ACCESS-TOKEN"];
RKObjectRequestOperation *operation =[[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:#[userProfileDescriptor]];
[manager enqueueObjectRequestOperation:operation];
I am very new to iOS. I am trying to send data through post method to PHP. In PHP it can't take data like $_POST['data'], but it takes $_GET['data']. My iOS code is as follows.
NSString *strURL = [NSString stringWithFormat:#"http://example.com/app_respond_to_job?emp_id=%#&job_code=%#&status=Worker-Accepted&comment=%#",SaveID2,txtJobcode1,alertTextField.text];
NSURL *apiURL = [NSURL URLWithString:strURL];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:apiURL];
[urlRequest setHTTPMethod:#"POST"];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];
_receivedData = [[NSMutableData alloc] init];
[connection start];
NSLog(#"URL---%#",strURL);
Can someone explain why is that, it will be very helpful.
Please Download this file https://www.dropbox.com/s/tggf5rru7l3n53m/AFNetworking.zip?dl=0
And import file in your project
Define in #import "AFHTTPRequestOperationManager.h"
AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:[NSURL URLWithString:#"Your Url"]];
NSDictionary *parameters = #{#"emp_id":SaveID2,#"job_code":txtJobcode1.text,#"status":alertTextField.text};
AFHTTPRequestOperation *op = [manager POST:#"rest.of.url" parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success: %# ***** %#", operation.responseString, responseObject);
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[responseObject valueForKey: #"data"];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %# ***** %#", operation.responseString, error);
}];
[op start];
because you send your data via query string in url
i think it will work if you try to pass data in your request's body:[urlRequest setHTTPBody:...]
POST parameters come from the request body, not from the URL string. You'll need to:
Call setHTTPBody on the request and provide the URL-encoded string (sans question mark, IIRC) as the body data
Call setValue:forHTTPHeaderField: to set the Content-Type to application/x-www-form-urlencoded
Either remove the call to [connection start] or use initWithRequest:delegate:startImmediately: so that you aren't starting the connection twice.
That last one is kind of important. You can get strange results if you try to start a connection twice. :-)
I use the code below to login to the server:
//First Block Code
-(RKObjectManager *)getObjectManager
{
NSURL *baseURL = [NSURL URLWithString:#"http://api.domain.com"];
AFHTTPClient *httpClient = [[AFHTTPClient alloc]initWithBaseURL:baseURL];
RKObjectManager *manager = [[RKObjectManager alloc]initWithHTTPClient:httpClient];
[manager.HTTPClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
[manager setAcceptHeaderWithMIMEType:RKMIMETypeJSON];
[manager.HTTPClient setParameterEncoding:AFJSONParameterEncoding];
[RKMIMETypeSerialization registeredMIMETypes];
return [RKObjectManager sharedManager];
}
- (void)loginUserwithUsername:(NSString *)username andPassword:(NSString *)password requestByNewUser:(BOOL)newRegistration
{
[self getObjectManager];
RKObjectManager *objectManager = [RKObjectManager sharedManager];
[objectManager.HTTPClient setAuthorizationHeaderWithUsername:username password:password];
NSIndexSet *statusCodeSet = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
RKMapping *mapping = [RESTMappingProvider profileMapping];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping
method:RKRequestMethodGET
pathPattern:nil
keyPath:nil statusCodes:statusCodeSet];
NSMutableURLRequest *request = [objectManager.HTTPClient requestWithMethod:#"POST"
path:#"/login"
parameters:#{#"username": username,
#"password": password
}];
RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request
responseDescriptors:#[responseDescriptor]];
[objectManager.HTTPClient registerHTTPOperationClass:[AFHTTPRequestOperation class]];
[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"mappingResults Error %#", error);
}
}];
[operation start];
}
AFTER I login, I try to make a Google Places API request and get an error:
//Second Block of Code
- (void)fetchPlaces:(NSString *)input;
{
NSIndexSet *statusCodeSet = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
RKMapping *mapping = [RESTMappingProvider googleAutoCompleteMapping];
NSString *urlString = [NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/place/json?input=%#&sensor=true&key=%#&location=0.000000,0.000000", input, self.key];
NSString *urlStringEncoded = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:urlStringEncoded];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping
method:RKRequestMethodGET
pathPattern:nil
keyPath:#"predictions" statusCodes:statusCodeSet];
RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request
responseDescriptors:#[responseDescriptor]];
[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
self.responseObjects = mappingResult.array;
[operation start];
}
Error:
2014-04-02 14:11:17.865 App[1247:60b] *** Assertion failure in +[RKPathMatcher pathMatcherWithPattern:], /Users/App
Time/Pods/RestKit/Code/Support/RKPathMatcher.m:74
2014-04-02 14:11:17.868 App[1247:60b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Pattern string must not be empty in order to perform pattern matching.'
However, if I never Login (meaning that I skip the first code in this question) and go straight to call Google API, there is no crash API works great.
I think there is something that I'm doing to RESTKit (perhaps by creating an ObjectManager), by Logging-in that's causing Google's API call to cause a crash.
I tried to run Charles Web Debug Proxy, but the crash seems to happen even before making the API call.
*EDIT *
I found out what is causing the crash:
[[RKObjectManager sharedManager] cancelAllObjectRequestOperationsWithMethod:RKRequestMethodAny matchingPathPattern:nil];
This was an attempt to Cancel all previous requests.
I replaced it with:
[[RKObjectManager sharedManager] cancelAllObjectRequestOperationsWithMethod:RKRequestMethodAny matchingPathPattern:#"maps/api/place/autocomplete"];
and it seems to work.
Question: Does this code cancel any previous request to: https://maps.googleapis.com/maps/api/place/autocomplete/json ?
When you create responseDescriptor this is added to the RKObjectManager you use pathPattern:nil. This is not permitted. You must specify a path pattern as RestKit must lookup the appropriate response descriptor to apply to the received response.
Later, you again use pathPattern:nil, but this is directly with an RKObjectRequestOperation. In this case it is allowed (and thus works) because you have provided an explicit list and no lookup is required.
I am implementing following paypal REST API:
curl -v https://api.sandbox.paypal.com/v1/vault/credit-card \
-H 'Content-Type:application/json' \
-H 'Authorization: Bearer {accessToken}' \
-d '{
"payer_id":"user12345",
"type":"visa",
"number":"4417119669820331",
"expire_month":"11",
"expire_year":"2018",
"first_name":"Joe",
"last_name":"Shopper"
}'
I have successfully implement this api in AFNetworking 1.3.3 with following Code. Where PPWebService is subclass of AFHTTPClient
[[PPWebService sharedClient] setParameterEncoding:AFJSONParameterEncoding];
[[PPWebService sharedClient] setDefaultHeader:#"Content-Type" value:#"application/json"];
[[PPWebService sharedClient] setDefaultHeader:#"Authorization" value:[NSString stringWithFormat:#"Bearer %#", accessToken]];
[[PPWebService sharedClient] postPath:#"vault/credit-card"
parameters:creditCard
success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSDictionary *response = [self JSONToObject:operation.responseString];
creditCardId = response[#"id"];
if(creditCardId)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Credit card" message:#"Saved !!" delegate:nil cancelButtonTitle:#"on" otherButtonTitles:nil];
[alert show];
}
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Credit card" message:error.description delegate:nil cancelButtonTitle:#"on" otherButtonTitles:nil];
[alert show];
}];
I want to use AFNetworking 2.x.x in my project. But I am not able to do it with this new version.
I have subclass AFHTTPRequestOperationManager. I search internet and people suggest me to use AFJSONRequestSerializer. All other code is very similar. But than also I am getting bad request error.
So how can I send raw JSON string in with POST method in AFNetworking 2.x.x?
EDIT
Code for AFNetworking 2.X.X
Error Status : 404 Bad Request
Response :
{"name":"MALFORMED_REQUEST","message":"The request JSON is not well formed.","information_link":"https://developer.paypal.com/docs/api/#MALFORMED_REQUEST","debug_id":"ab3c1dd874a07"}
I am getting proper response by using Postman as shown in following screenshot.
So finally I got answer. I use subclass of AFHTTPSessionManager to implement API in my project. And use it with singleton object. So this is my singleton method.
+ (MASWebService *)APIClient
{
static MASWebService *_sharedClient = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
{
NSURL *baseURL = [NSURL URLWithString:BaseURL];
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
_sharedClient = [[MASWebService alloc] initWithBaseURL:baseURL sessionConfiguration:config];
_sharedClient.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments];
_sharedClient.requestSerializer = [AFJSONRequestSerializer serializer];
[_sharedClient.requestSerializer setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
});
return _sharedClient;
}
The main key line is setting Request Serializer HTTP Header "Content-Type" to "application/json"
If you are not subclassing AFHTTPSessionManager and using AFHTTPRequestOperationManager for single request than also it will work because AFHTTPRequestOperationManager is also conform to AFURLRequestSerialization protocol as property of AFHTTPRequestSerializer. I have not done it but it should look like this.
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = #{#"foo": #"bar"};
manager.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager.requestSerializer setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[manager POST:#"http://example.com/resources.json" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
I hope this will work. Inform me in comment if I am wrong somewhere.
Source : AFNetworking 2.0 POST request working example code snippet
So how can I send raw JSON string in with POST method in AFNetworking 2.x.x?
I had the same issue when trying to use SOAP+XML data with AFHTTPRequestOperationManager. Apparently the request serializer should be subclassed to make provision for your special serialisation needs, but this way seems easier:
NSError *error = nil;
NSData *envelopeData = [NSJSONSerialization dataWithJSONObject:params options:options error:nil];
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:#"POST"
URLString:path
parameters:nil
error:&error];
// In my case, I also needed the following:
// [request setValue:action forHTTPHeaderField:#"SOAPAction"];
[request setHTTPBody:envelopeData];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] init];
operation = [self HTTPRequestOperationWithRequest:request
success:^(AFHTTPRequestOperation *operation, id responseObject)
{
// parse response here
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
// parse response here
}];
It hijacks the request serialiser that is created by AFHTTPRequestOperationManager, inserts the parameter data into the HTTP body, and then passes this new request into the AFHTTPRequestOperation.
I am trying to send JSON data in POST request to server using RestKit but I am getting error
Expected content type {(
"application/x-www-form-urlencoded",
"application/json"
)}, got text/plain
The code I have written is:
NSURL *url=[NSURL URLWithString:[NSString stringWithFormat:#"%#%#",BASE_SERVICE_URL,TASK_SERVICE_URL]];
RKObjectMapping *mapping=[RKObjectMapping mappingForClass:[LoginData class]];
[mapping addAttributeMappingsFromDictionary:#{#"s":#"status",
#"message":#"message"}];
RKResponseDescriptor *descriptor=[RKResponseDescriptor responseDescriptorWithMapping:mapping method:RKRequestMethodPOST pathPattern:nil keyPath:#"" statusCodes:0];
NSMutableURLRequest *request=[[NSMutableURLRequest alloc]initWithURL:url];
[request setHTTPMethod:#"POST"];
[request addValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
NSDictionary *dict=#{#"task":#"storeProfile",
#"fdate":#"01.01.2013",
#"tdate":#"19.08.2013",
#"keyword":#"taxi && cab",
#"AlertHours":#"120",
#"AlertDay":#"0",
#"AlertTimeStart":#"12:00",
#"AlertTimeEnd":#"18:00",
#"topic":#[
#{#"tname":#"Politics"},
#{#"tname":#"Economy"}
],
#"publication":#[
#{#"pname":#"Vijay Times Online"},
#{#"pname":#"Leisure Opportunities"}
]
};
NSError *error=nil;
NSData *jsonData=[NSJSONSerialization dataWithJSONObject:dict options:kNilOptions error:&error];
if (error) {
NSLog(#"%#",error.localizedDescription);
return;
}
[request setHTTPBody:jsonData];
operation=[[RKObjectRequestOperation alloc]initWithRequest:request responseDescriptors:#[descriptor]];
[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
LoginData *data=[mappingResult.dictionary objectForKey:#""];
NSLog(#"%#",data.message);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"ERROR:%#",error.localizedDescription);
}];
[operation start];
Could somebody please help me to figure out what exactly the problem is??
I have tried setting content type as follow also:
[request addValue:#"application/application/x-www-form-urlencoded; charset=UTF-8" forHTTPHeaderField:#"Content-Type"];
Try this
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:BASE_URL]];
[objectManager setRequestSerializationMIMEType:RKMIMETypeJSON];
You have to register the class RKNSJSONSerialization . Please include the below code in your method.
[RKMIMETypeSerialization registerClass:[RKNSJSONSerialization class] forMIMEType:#"text/plain"];