Strongloop iOS User Creation Error - ios

I'm trying to create and save a test user in server with this code:
LBRESTAdapter *adapter = ((AppDelegate *)[[UIApplication sharedApplication] delegate]).adapter;
if (adapter) {
TeacherRepository *repo = (TeacherRepository *)[adapter repositoryWithClass:[TeacherRepository class]];
if (repo) {
Teacher *st = (Teacher *)[repo createUserWithEmail:#"test#test.com" password:#"test"];
if (st) {
[st saveWithSuccess:^{
NSLog(#"Saved in server!");
} failure:^(NSError *error) {
NSLog(#"Error: %#", error.description);
}];
}
}
}
but I keep on getting this error response:
Error Domain=AFNetworkingErrorDomain Code=-1011 "Expected status code in (200-299), got 404"
I have searched for this error and similar others, but couldn't find anything that would solve my problem, so what could be causing this?

The HTTP Status Code of 404 means that the resource was not found:
404 Not Found
The server has not found anything matching the Request-URI. No indication is given of whether the condition is temporary or permanent. The 410 (Gone) status code SHOULD be used if the server knows, through some internally configurable mechanism, that an old resource is permanently unavailable and has no forwarding address. This status code is commonly used when the server does not wish to reveal exactly why the request has been refused, or when no other response is applicable.
It would appear that there is an error in the building of the URL in your AFNetworking code. You haven't shared that portion of code, so it's hard to comment on the specifics. I think if you log the entire error object (not just error.description) it will show you what URL it attempted to use unsuccessfully.

Related

"Server Rejected Request" (15/2001); "Request failed with http status code 500"

fetchUserRecordIDWithCompletionHandler returns:
<CKError 0x14daad30: "Server Rejected Request" (15/2001); "Request failed with http status code 500">
I have never seen this error with CloudKit. Do you think it is associated that some iCloud service was down nowadays?
defaultContainer.fetchUserRecordIDWithCompletionHandler({ _userRecordID, error in
if error == nil {
userRecordID = _userRecordID
loggedInUserRecordName = _userRecordID.recordName
dispatch_async(dispatch_get_main_queue(), {
self.progressView.setProgress(2 / self.steps, animated: true)
})
} else {
Utility.log("error 1231: \(error.localizedDescription)")
}
dispatch_semaphore_signal(self.sema)
})
Strange that fetchUserRecordIDWithCompletionHandler works in one of my other project with an other container, but usually does not work with this project with this container.
Any idea way?
Probably a server issue at the other end. 500 error code is unexpected internal error at server.
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
This can happen when you are using wrong container. In my project I was using custom container that did not match default app container. Switching to correct one with custom identifier solved the issue.
Check the id of the CKContainer in Capabilities and your CKContainer's initialization make ensure that they are the same. In my case, I make this mistake, and the error?.localizedDescription is Optional("Request failed with http status code 500")

Twitter oauth/access_token 401 Error

I've been working on an all that uses the full OAuth app flow, and I have been running into an issue where I only get back a 401 = "Invalid or expired token" error. I've checked my request with the documentation, and everything looks correct, and I'm stumped. Below is the details of my request.
URL
https://api.twitter.com/1.1/oauth/access_token
HTTP Method
POST
Headers
Content-Type: application/x-www-form-urlencoded
Authorization: OAuth oauth_consumer_key="CONSUMER_API_KEY", oauth_nonce="B4D43B0C-A348-4EB6-9C0B-8B0F4FE8", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1397724299", oauth_version="1.0", oauth_token="TOKEN_FROM_REQUEST_TOKEN_API", oauth_signature="ulYIzTacwC%2FeGUdoCPYsrFEqg4A%3D"
HTTP Body
oauth_verifier=OAUTH_VERIFIER_FROM_REQUEST_TOKEN_API
I have no issues getting the oauth/request_token API to work, and I have appropriately set the permissions in Twitter's app settings. Does anyone have any idea what's going on with this?
Thanks for any help you all may be able to offer.
-- UPDATE --
Another thing to note is that I'm using the STTwitter library to make the requests. It did not have a built-in method to handle the oauth/authorize or oath/authenticate API methods so I'm using the code below.
// get request token, and present login screen
STTwitterAPI *twitter = [STTwitterAPI twitterAPIWithOAuthConsumerKey:twitterApiKey consumerSecret:twitterApiSecret];
[twitter postTokenRequest:^(NSURL *url, NSString *oauthToken)
{
authWebViewController = [[TWAuthWebViewController alloc] init];
authWebViewController.url = [NSURL URLWithString:[NSString stringWithFormat:#"https://api.twitter.com/oauth/authorize?oauth_token=%#", oauthToken]];
authWebViewController.completion = ^(TWAuthWebViewController *authViewController, NSURL *oauthCallbackURL)
{
// get the request token and verifier from the URL
NSString *oauthToken = [TWLoginBusiness getOAuthTokenFromURL:oauthCallbackURL];
NSString *oauthVerifier = [TWLoginBusiness getOAuthVerifierFromURL:oauthCallbackURL];
// get user data with the oauth token
[twitter postResource:#"oauth/access_token"
baseURLString:#"https://api.twitter.com/1.1"
parameters:#{#"oauth_verifier" : oauthVerifier}
uploadProgressBlock:nil
downloadProgressBlock:nil
successBlock:^(NSDictionary *rateLimits, id response)
{
NSLog(#"Reponse: %#", response);
completion(nil, nil);
} errorBlock:^(NSError *error)
{
NSLog(#"Error: %#", error);
completion(nil, error);
}];
};
presentAuthController(authWebViewController);
} oauthCallback:twitterApiCallback errorBlock:^(NSError *error)
{
completion(nil, error);
}];
One last note. The part that actually displays the web view controller is not listed here. I wanted to keep the code snippet here focused on the actual API methods, and not the UI logic. Just be assured that the line right after authWebViewController.url.... displays the web view, and then the completion block is called after the user completes the authentication on the Twitter web page. Also the two methods getOauthTokenFromURL and getOauthVerifierFromUrl do in fact return the correct token and verifier. The STTwitter library actually saves out the token it's self, so that is why it's not manually passed into the logic below. The logic generates the request above.
Thanks
The full OAuth flow is already implemented in STTwitter library.
Check out iOS demo for a working example of web-based authentication through Safari.
What you are trying to do here is a web-based authentication inside the application.
Although it is totally feasible, I did not include this workflow in the demo project because it is considered a bad practice.
Indeed, the point of OAuth is that the user does not want to enter her Twitter credentials in your own application, but asks Twitter to send your app dedicated OAuth tokens instead.
Let me know if you need more help with STTwitter.

AFNetworking with Unreliable wifi - Detecting / Retrying connections when they timeout

I'm using AFNetworking in my app to connect / download data from a web service. This app is deployed via Enterprise deployment to users at various locations. At one of the locations where people use our app, the wifi network seems to randomly go down / come back up in a few seconds. In these cases, the requirement was to retry a request thrice before giving up and failing. I've got the retry part of it working fine, but have some problems detecting a network failure. Some code:
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setCompletionBlockWithSuccess:
^(AFHTTPRequestOperation *operation, id responseObject) {
[self parseResponse:operation.responseString];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[self messageFailureWithCode:error.code
reason:[NSString stringWithFormat:#"%#", error]];
}
];
The error code I'm retrying on is NSURLErrorTimedOut. But I just got another log file which indicated a failure with the following error: -1003 "A server with the specified hostname could not be found."
I could add this code to my list too, but I wanted to be sure that I'm capturing all the errors and not just handling them as they appear. I was looking through the NSURLError.h file and found the following error codes that vaguely look like they could be caused by a network failure.
Can someone help me figuring out under what conditions each error is triggered and if I'm missing any error codes? The list is below:
NSURLErrorCannotFindHost
NSURLErrorTimedOut
NSURLErrorCannotConnectToHost
NSURLErrorNetworkConnectionLost
NSURLErrorDNSLookupFailed
NSURLErrorResourceUnavailable
NSURLErrorNotConnectedToInternet
Thanks,
Teja.
It sounds like you could safely just retry every failure with an error domain of NSURLErrorDomain (exempting the case where an operation was cancelled). That should cover all of those cases.

How to tell if TWRequest performRequestWithHandler failed or succeeded

I am posting a request and checking for errors like so:
// Send request out on a background thread
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
[postRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
if ([urlResponse statusCode] == 200) {
NSLog(#"Tweet Successful");
}else {
NSLog(#"Tweet Failed");
if (responseData) {
// Use the NSJSONSerialization class to parse the returned JSON
NSError *jsonError;
NSArray *requestResponse =
[NSJSONSerialization JSONObjectWithData:responseData
options:NSJSONReadingMutableLeaves
error:&jsonError];
if (requestResponse) {
NSLog(#"%#",requestResponse);
} else {
NSLog(#"%#",jsonError);
}
}
}
}];
});
It seems to work fine, so far as the request is concerned. My intention was to queue the request on failure and try again at a later date, or not depending on the error and how many attempts had failed thus far.
The problem I have is that I find it frequently appears to fail, with error 34 "Page not Found" where in fact the request did succeed, was posted as intended and can be seen clear as day in twitter stream.
Now, if I can't trust the error code returned then I can't really go on and keep retrying. How do I know for sure if it succeeds or fails?
RECENT OBSERVATIONS:
Recently, I tried to post a photo from Apple photo app directly and it sent me an alert that read "Tweet may not have been successful". That is funny, because that is basically what I was coming to as my only option in this case. This makes me think that even Apple had to acknowledge that there is not way to tell for sure that post failed when the return does not confirm it.
according to every example found in researching this problem, none of which use any other API than what you are using, and including this example from twitter's own documentation for posting a photo to the API, none of them check the urlResponse code first.
the most that ever seems to be done is this example from twitter's documentation where a GET is performed and then the response is processed. notice that it checks the responseData first, and if it exists, it is simply treated like success. only if there is no responseData is there an attempt to bother looking at the error. the example does not bother with the urlResponse … and neither does any other example i saw in 10 minutes of googling.
(finally, i doubt this matters, or it may be because you cleaned up the example for the display, but you're processing the error on the main-queue when you are not performing any UI. you could do the processing in the handler immediately, and pass along whatever post-processing you do to whatever UI you are trying to display it with. i doubt post-processing the response in the main-queue as opposed to the queue of the handler (as shown in both examples cited here and all other examples i've seen) is really causing a problem, but i wonder if it might cut down on the incidence of false negatives you are seeing. at the very least, it will make your response and any UI display of the response cleaner and more efficient.)

How to make webservice pass errors through NSURLConnection's connection:didFailWithError:?

What does a web service need to do to cause NSURLConnection's delegate to receive the connection:didFailWithError: message?
For example:
iOS app passes a token to the web service, web service looks up the token, and then the web service needs to respond with an error saying "invalid token" or something of the like.
Currently, the data is received, and in "connectionDidFinishLoading:" is parsed for error messages. This means I'm error checking in two places, which I am trying to avoid.
I have both the iOS app and web service completely under my control.
In my experience (the three most dangerous words in programming), -connection:didFailWithError: is only called if the HTTP exchange failed. This is usually a network error or maybe an authentication error (I don't use authentication). If the HTTP message succeeds, no matter the response code, -connectionDidFinishLoading: is called.
My solution: call -connection:didFailWithError: when I detected an error. That way all my error handling code is in one place.
At the top of my -connectionDidFinishLoading:, I have:
NSError *error;
NSDictionary *result = [self parseResultWithData:self.connectionData error:&error];
if (!result) {
[self connection:connection didFailWithError:error];
return;
}
There are many conditions on which the delegate connection:didFailWithError: of NSUrlConnection may invoke.Here's a list of those errors or constants.I think an alertview would be better to show http errors in connection:didFailWithError:.
-(void) connection:(NSURLConnection *)connection didFailWithError: (NSError *)error
{
UIAlertView *errorAlert= [[UIAlertView alloc] initWithTitle: [error localizedDescription] message: [error localizedFailureReason] delegate:nil cancelButtonTitle:#"Done" otherButtonTitles:nil];
[errorAlert show];
[errorAlert release];
NSLog (#"Connection Failed");
}
While not directly related to your question, I would encourage you to move to a more high level library. I can heartily recommend AFNetworking, it is production ready and I have used it in many projects. This will allow you to inspect the response code of each request in the failure block. This project also abstracts away a lot of the low level handling that you would otherwise be required to write for network communication; I'm speaking here about parsing and creating XML / JSON strings to communicate with a service.
To give you a more focused answer to your question, I would call the cancel method of your NSURLConnection once you have noticed an error in connectionDidFinishLoading:. This will automatically cancel the request and call the failure method of the delegate object.
The documentation for NSURLConnection is pretty dry, and the failure method of the delegate does not specifically document the failure cases. You may be able to find more information in the URL Loading System Programming Guide.
I couldn't see the forrest for the trees.
I needed to step back from connection:didFailWithError: and look at a different delegate method connection:didReceiveResponse:!!
With the web service fully under my control, the endpoint could respond with a 500 status code, which gets picked up in connection:didReceiveResponse, and pass along some JSON further explaining the situation, which gets picked up and processed in connection:didReceiveData:.
The NSURLConnection delegate hangs onto a couple more bits of state throughout the process, but it has the best code smell I've found so far.
Jeffery's answer was by far most correct: the connection:didFailWithError: callback is only in relation to the network failing, any response from the web service means the connection didn't fail!

Resources