POST with AFNetworking, error code -1001 - ios

I want to POST a json message to send to a server. I don't have access to the server itself but I know it is working and set up to return a success/failure message when a message gets through. The server requires an app id and password to connect
I am using AFNetworking for this. Here is the code I'm using:
NSURL* pushServerURL = [NSURL URLWithString: #"http://myserverurl.com/"];
AFHTTPClient* networkInstance = [[AFHTTPClient alloc] initWithBaseURL: pushServerURL];
NSDictionary *parameters =[NSDictionary dictionaryWithObjectsAndKeys:
#"myappid", #"app_id", #"mypassword", #"password", nil];
NSDictionary *params =[NSDictionary dictionaryWithObjectsAndKeys:
parameters, #"user", nil];
[networkInstance postPath: #"users/login.json"
parameters: params
success:^
(AFHTTPRequestOperation *operation, id jsonResponse)
{
NSLog (#"SUCCESS");
}
failure:^
(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"FAILED");
}];
It always fails with the error code -1001.
The NSError has 4 keys in the user info
NSErrorFailingURLStringKey with value #"http://myserverurl.com/,
NSErrorFailingURLKey with value <not an Objective-C object>,
NSLocalizedDescription with value "The request timed out"
NSUnderlyingError and the value has no string.
Any idea what I might be doing wrong?

Try this line of code. You can easily find what is the response coming from server or else, where the actual problem is?
[networkInstance postPath: #"users/login.json"
parameters: params
success:^(AFHTTPRequestOperation *operation, id jsonResponse) {
NSLog (#"SUCCESS");
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#" Error - Statistics file upload failed: \"%#\"", [request error]);
}];

Related

iOS and RestKit: How to get a text/html response right?

I have tried several StackOverflow questions, and I caanot find the correct answer on this. I am using the POSTMAN plugin for Chrome to check my REST calls and I cannot figure out why I cannot read the response. In the comments you will see all the different attempts I have made to get the response.
NSDictionary* session_params = #{SESSION_USERNAME_KEY:SESSION_USERNAME_VALUE, SESSION_PASSWORD_KEY:SESSION_PASSWORD_VALUE};
NSURL* url = [NSURL URLWithString:SESSION_URL];
RKObjectManager* objectManager = [RKObjectManager managerWithBaseURL:url];
//GET THE **** THING TO INTERPRET A TEXT response
//[RKMIMETypeSerialization registerClass:[RKXMLReaderSerialization class] forMIMEType:RKMIMETypeTextXML];
//[objectManager setAcceptHeaderWithMIMEType:#"text/html"];
//[objectManager setAcceptHeaderWithMIMEType:RKMIMETypeTextXML];
//[RKMIMETypeSerialization registerClass:[RKXMLReaderSerialization class] forMIMEType:#"text/html"];
//[RKMIMETypeSerialization registerClass:[RKNSJSONSerialization class] forMIMEType:#"text/html"];
//[objectManager setRequestSerializationMIMEType:#"text/html"];
//END
NSMutableURLRequest* request = [objectManager requestWithObject:nil method:RKRequestMethodPOST path:SESSION_URL parameters:session_params];
RKObjectRequestOperation* operation = [objectManager
objectRequestOperationWithRequest:request success:^(RKObjectRequestOperation* operation, RKMappingResult* result)
{
NSLog(#"RESULT [%#]", result);
}
failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"ERROR [%#]", error);
}];
[operation start];
I think the most irritating thing is that the stuff I need is contained in the NSLocalizedRecoverySuggestion value. It is a session key I require.
OUTPUT:
E restkit.network:RKObjectRequestOperation.m:547 Object request failed: Underlying HTTP request operation failed with error: Error Domain=org.restkit.RestKit.ErrorDomain Code=-1016 "Expected content type {(
"application/x-www-form-urlencoded",
"application/json"
)}, got text/html" UserInfo=0x1c52aed0 {NSLocalizedRecoverySuggestion=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJCbG8uUmVnQWxlcnQuQnJva2VyIiwiYXVkIjoiaHR0cDovL2xvY2FsaG9zdC9CbG8uUmVnQWxlcnQuQVBJL2FwaSIsIm5iZiI6MTM5MjY0MTY2MSwiZXhwIjoxMzkyNjQ1MjYxLCJ1bmlxdWVfbmFtZSI6IkJ1dHRvbnMiLCJyb2xlIjoiUmVnQWxlcnRDb25zdW1lciJ9.JCTMGJRKlOxEtNrcGodpce-tqsRS4zlApNisKQW6iSw, AFNetworkingOperationFailingURLRequestErrorKey=, NSErrorFailingURLKey=http://..., NSLocalizedDescription=Expected content type {(
"application/x-www-form-urlencoded",
"application/json"
)}, got text/html, AFNetworkingOperationFailingURLResponseErrorKey=}
2014-02-17 14:54:20.808 AppName[5600:6403] E restkit.network:RKObjectRequestOperation.m:213 POST 'http://...' (200 OK / 0 objects) [request=0.0000s mapping=0.0000s total=0.1925s]: Error Domain=org.restkit.RestKit.ErrorDomain Code=-1016 "Expected content type {(
"application/x-www-form-urlencoded",
"application/json"
)}, got text/html" UserInfo=0x1c52aed0 {NSLocalizedRecoverySuggestion=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJCbG8uUmVnQWxlcnQuQnJva2VyIiwiYXVkIjoiaHR0cDovL2xvY2FsaG9zdC9CbG8uUmVnQWxlcnQuQVBJL2FwaSIsIm5iZiI6MTM5MjY0MTY2MSwiZXhwIjoxMzkyNjQ1MjYxLCJ1bmlxdWVfbmFtZSI6IkJ1dHRvbnMiLCJyb2xlIjoiUmVnQWxlcnRDb25zdW1lciJ9.JCTMGJRKlOxEtNrcGodpce-tqsRS4zlApNisKQW6iSw, AFNetworkingOperationFailingURLRequestErrorKey=, NSErrorFailingURLKey=http://..., NSLocalizedDescription=Expected content type {(
"application/x-www-form-urlencoded",
"application/json"
)}, got text/html, AFNetworkingOperationFailingURLResponseErrorKey=}
CODE THAT WORKED
Thanks to Wain for pointing me on the correct path there. I am a little disappointed that RestKit cannot handle such a simple request, and I need RestKit because this is just a session token to calling the other methods, but whatever works I guess:
NSDictionary* session_params = #{SESSION_USERNAME_KEY:SESSION_USERNAME_VALUE, SESSION_PASSWORD_KEY:SESSION_PASSWORD_VALUE};
NSURL* url = [NSURL URLWithString:SESSION_URL];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
NSMutableURLRequest *request = [httpClient requestWithMethod:#"POST" path:SESSION_URL parameters:session_params];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString* response = [operation responseString];
NSLog(#"response: %#",response);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"error: %#", [operation error]);
}];
[operation start];
This bit:
"Expected content type {( "application/x-www-form-urlencoded", "application/json" )}, got text/html"
tells you that you have told RestKit to expect form-urlencoded or json, but that the server is returning html.
You would probably want to use setAcceptHeaderWithMIMEType with JSON mime type to tell the server what you want back. But, in this case you probably just shouldn't be using RestKit.
RestKit is for mapping arbitrary JSON / XML data into your data model. You just have a key coming back. No mapping is required. So, don't use RestKit, use AFNetworking instead (which you have full access to because RestKit uses it internally.
Thanks to Wain and Quintin, this was quite useful to me :)
I think some names changed in more recent versions of Restkit or AFNetworking. I used AFNetworking as explained in other answers since the server did not return json but empty plain/text instead. This was only on a particular endpoint where I was looking for a token in the headers of the response.
Sharing my piece of code here too:
-(void) find_some_token_with_success:(void (^)(AFRKHTTPRequestOperation *operation, id responseObject))success failure:(void (^)(AFRKHTTPRequestOperation *operation, NSError *error))failure {
NSURL *baseURL = [NSURL URLWithString:#"https://example.com"];
AFRKHTTPClient *client = [AFRKHTTPClient clientWithBaseURL:baseURL];
[client setDefaultHeader:#"Accept" value:RKMIMETypeJSON];
[client setDefaultHeader:#"some_custom_header" value:#"some_custom_value"];
NSMutableURLRequest *request = [client requestWithMethod:#"GET" path:#"/api/v1/some_non_json_endpoint" parameters:nil];
AFRKHTTPRequestOperation *operation = [[AFRKHTTPRequestOperation alloc] initWithRequest:request];
[operation setCompletionBlockWithSuccess:success failure:failure];
[operation start];
}
Then I used something like this to get the header I was looking for:
-(void) get_the_token:(void (^)(NSString *token))withTokenCallback failure:(void (^)(AFRKHTTPRequestOperation *operation, NSError *error))failure {
[self xsrftoken_with_success:^(AFRKHTTPRequestOperation *operation, id responseObject) {
NSString *token = [self get_the_token_from_response:[operation response]];
withTokenCallback(token);
} failure:failure];
}
-(NSString *) get_the_token_from_response: (NSHTTPURLResponse *) response;
{
NSDictionary *headerDictionary = response.allHeaderFields;
NSString *token = [headerDictionary objectForKey:#"SOME-TOKEN-KEY"];
return token;
}
So all of this can simply be used like this:
- (void)testGetSometokenInARequest
{
XCTestExpectation *expectation = [self expectationWithDescription:#"Query timed out."];
[[SomeRequestWithoutJsonResponse alloc]
get_the_token:^(NSString *token) {
[expectation fulfill];
NSLog(#"token: %#", token);
// this token should be 100 characters long
XCTAssertTrue([token length] == 100);
}
failure:^(AFRKHTTPRequestOperation *operation, NSError *error) {
NSLog(#"error: %#", [operation error]);
}];
[self waitForExpectationsWithTimeout:10.0 handler:nil];
}
In other words, get_the_token takes a callback with the desired token and a failure callback.
Make sure you still include <RestKit/RestKit> so you have access to Restkit's AFNetowkring :)
Alternative working solution using restkit:
RestKit: How to handle empty response.body?
And you register a serializer for that kind of Mimetype like this:
[RKMIMETypeSerialization registerClass:[RKNSJSONSerialization class] forMIMEType:#"text/plain"];

"Expected status code in (200-299), got 404"

This is my code:
NSURL *url = [NSURL URLWithString:#"http://wspublisherv2.skygiraffe.com/WSpublisherV2.svc/Authenticate"];
AFHTTPClient *client = [[AFHTTPClient alloc]initWithBaseURL:url];
NSDictionary *parameters = [NSDictionary dictionaryWithObjectsAndKeys:#"john#sgdemo.com", #"UserName", #"123", #"Password", nil];
NSLog(#"%#", parameters);
[client postPath:nil parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"success: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"failure: %#", error);
}];
It always triggers the failure block and I get the "Expected status code in (200-299), got 404" message.
When I try it through Fiddler it works.
You need more information. Use a proxy like Charles Proxy to watch the traffic between your device and the server. That'll let you see the actual request. You can compare that to a request that works, and the difference should give a pretty good idea of what's wrong. At the very least, it'll make your question much more specific.

AFNetworking returning NSCFData; issue with registerHTTPOperationClass [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I am new to AFNetworking and am making a call to a simple login api that returns json like:
{"status":"success","data":{"auth_token":"12jt34"}}
I'm doing it via the following but it is returning __NSCFData rather than something that I can manipuate.
NSURL *baseURL = [NSURL URLWithString:#"http://localhost:3000/arc/v1/api/"];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:baseURL];
[httpClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
[httpClient defaultValueForHeader:#"Accept"];
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
uname,#"email", pwd, #"password",
nil];
[httpClient postPath:#"login-mobile" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *className = NSStringFromClass([responseObject class]);
NSLog(#"val: %#",className);
}failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error retrieving data: %#", error);
}];
and it outputs:
2013-03-21 14:52:51.290 FbTabbed[21505:11303] val: __NSCFData
but I'd like it for it to be a dictionary that I can manipulate which is how I think it is supposed to work? What am I doing wrong?
[httpClient defaultValueForHeader:#"Accept"];
should be:
[httpClient setDefaultHeader:#"Accept" value:#"application/json"];
Yes, responseObject is a NSData. You can then parse it into a dictionary or array using NSJSONSerialization method JSONObjectWithData:
NSURL *baseURL = [NSURL URLWithString:#"http://localhost:3000/arc/v1/api/"];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:baseURL];
[httpClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
[httpClient defaultValueForHeader:#"Accept"];
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
uname,#"email", pwd, #"password",
nil];
[httpClient postPath:#"login-mobile" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSAssert([responseObject isKindOfClass:[NSData class]], #"responseObject is supposed to be a NSData"); // it should be a NSData class
NSError *error;
self.results = [NSJSONSerialization JSONObjectWithData:responseObject
options:0
error:&error];
if (error != nil)
{
// handle the error
// an example of the sort of error that could result in a parse error
// is if common issue is that certain server errors can result in an
// HTML error page (e.g. you have the URL wrong, your server will
// deliver a HTML 404 page not found page). If you want to look at the
// contents of the `responseObject`, you would:
//
// NSLog(#"responseObject=%#", [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]);
}
}failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error retrieving data: %#", error);
}];
Obviously, your results object would be a NSDictionary or NSArray, depending upon the type of response you get from your API.
What am I doing wrong?
NSStringFromClass() returns the name of the class you pass in as an NSString object.
If you want to make a dictionary out of the returned JSON string, then you have to parse it, for example using the NSJSONSerialization class.

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: Can't get the response string from AFHTTPRequestOperation

Anyone?): I'm having a problem that has made me scratch my head for the last 2 hours, and it most likely a very simple stupid thing I'm missing. I Keep getting a building error when I Call the response string from the operation # AFNetworking... Like there is NO SUCH PROPERTY....
Please Take a look at my code and Explain me what did I Mess up This time :p.. THanks :)
NSDictionary* paramDict = [NSDictionary dictionaryWithObjectsAndKeys:WebServicemd5Value, WebSermd5Variable, nil]
;
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:webServiceURL]];
[httpClient defaultValueForHeader:#"Accept"];
[httpClient postPath:#"method" parameters:paramDict success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Response data: %#", responseObject);
NSLog(#"Reponse String: %#", operation);
// Printing operation will show me the operation Dictionary, including the reponse field, // but when I Directly call operation.response, the Compiler won't Build, stating that // "Property not found for AFHTTPRequestOperation".... WEIRDEST THING EVER, right?
NSString* responseString = [NSString stringWithUTF8String:[responseObject bytes]];
//.. Rest o f my Code....
}failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error retrieving data: %#", error);
}];
Hernan, if you expect an NSDictionary from a JSON response you should consider using AFJSONRequestOperation, because you get a JSON dictionary in your success callback. Anyway, if you want to get a dictionary from your responseObject, try to use the following code:
NSError *error = nil;
NSDictionary *JSON = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingAllowFragments error:&error];
if (error) {
NSLog(#"Error serializing %#", error);
}
NSLog(#"Dictionary %#", JSON);
I believe the response string is inside the "operation" object, so something like:
...
}failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error retrieving data: %#", operation.responseString);
}];
While attempting to retrieve content from meetup.com api using AFNetworking (kudos to Mattt T. for a great framework, btw), ran into the same error - "The operation couldn't be completed. (Cocoa error 3840)". Realized that the issue I was having was with the response data containing a Swedish character 'Ø', resulting in the parsing error. The solution was to include the header 'Accept-Charset: utf-8' in the initialization of the AFNetworking client. Fixed!
- (id)initWithBaseURL:(NSURL *)url {
self = [super initWithBaseURL:url];
if (!self) {
return nil;
}
[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"];
[self setDefaultHeader:#"Accept-Charset" value:#"utf-8"];
return self;
}

Resources