plus.people.get2012-10-25 20:02:40 +0000Request: POST https://www.googleapis.com/rpc?prettyPrint=falseRequest headers:Accept: application/json-rpcAuthorization: Bearer _snip_Cache-Control: no-cacheContent-Type: application/json-rpc; charset=utf-8User-Agent: [com.MY.APP.ID]/2.0.1 google-api-objc-client/2.0 iPhone_Simulator/6.0 (gzip)Request body: (100 bytes){"method" : "plus.people.get","id" : "gtl_5","jsonrpc" : "2.0","params" : {"userId" : "me"},"apiVersion" : "v1"}Response: status 200Response headers:Cache-Control: no-cache, no-store, max-age=0, must-revalidateContent-Encoding: gzipContent-Length: 342Content-Type: application/json; charset=UTF-8Date: Thu, 25 Oct 2012 20:02:39 GMTExpires: Fri, 01 Jan 1990 00:00:00 GMTPragma: no-cacheServer: GSEX-Content-Type-Options: nosniffX-Frame-Options: SAMEORIGINX-XSS-Protection: 1; mode=blockResponse body: (479 bytes){…
}-----------------------------------------------------------
plus.people.get
2012-10-25 20:02:58 +0000
Request: POST https://www.googleapis.com/rpc?prettyPrint=false
Request headers:
Accept: application/json-rpc
Authorization: Bearer _snip_
Cache-Control: no-cache
Content-Type: application/json-rpc; charset=utf-8
User-Agent: [com.MY.APP.ID]/2.0.1 google-api-objc-client/2.0 iPhone_Simulator/6.0 (gzip)
Request body: (100 bytes)
{
"method" : "plus.people.get",
"id" : "gtl_7",
"jsonrpc" : "2.0",
"params" : {
"userId" : "me"
},
"apiVersion" : "v1"
}
Error: Error Domain=NSURLErrorDomain Code=-1003 "A server with the specified hostname could not be found." UserInfo=0x1575eb30 {NSErrorFailingURLStringKey=https://www.googleapis.com/rpc?prettyPrint=false, NSErrorFailingURLKey=https://www.googleapis.com/rpc?prettyPrint=false, NSLocalizedDescription=A server with the specified hostname could not be found., NSUnderlyingError=0x157797f0 "A server with the specified hostname could not be found."}
-----------------------------------------------------------
- (void)fetchUserData{// get number of albumsNSURL *feedURL = [GDataServiceGooglePhotos photoFeedURLForUserID:kGDataServiceDefaultUseralbumID:nilalbumName:nilphotoID:nilkind:nilaccess:nil];GDataServiceTicket *ticket;ticket = [_service fetchFeedWithURL:feedURL completionHandler:^(GDataServiceTicket *ticket, GDataFeedBase *feed, NSError *error) {if ( error ){NSLog( @"Getting user's feed for getting user data, fetch error: %s\n", [[error localizedDescription] UTF8String] );}else{// feed should be all photo albums_numberOfAlbums = [[feed entries] count];}}];// get a user display name and profile pictureGTLQueryPlus *profileQuery = [GTLQueryPlus queryForPeopleGetWithUserId:@"me"];profileQuery.completionBlock = ^(GTLServiceTicket *ticket, id object, NSError *error) {if (error == nil) {...} else {// Error getting user dataNSLog( @"Error getting user data: %@", [error localizedDescription] );}};GTLServiceTicket* plusTicket = [_plusService executeQuery:profileQuerycompletionHandler:^(GTLServiceTicket *ticket, id result, NSError *error) {if ( error != nil ) {NSLog( @"_plusService Error: %@", [error localizedDescription] );}}];}
Thanks Greg, I will follow up with Apple on the networking issue. As a workaround, I am trying to use the retry mechanism. That is, calling:
setIsServiceRetryEnabled:YES
setServiceRetrySelector:@selector(...)
on my GDataServiceGooglePhotos object. This allows me to catch the -1003 error and retry the request, which seems reasonable since the retrying manually seems to work. The retry selector does appear to catch it, but I am now hitting another problem, and I think this time it's actually related to the library ;-).
By calling setShouldCacheResponseData:YES we can tell the GTMHTTPFetcher to catch 304 responses, and use locally cached responses so that I will just see them as 200 responses. I could be wrong, but it appears that the retry mechanism breaks this functionality. In GTMHTTPFetchHistory updateRequest:isHTTPGet:, we check if the request has an ETag corresponding to kGTMIfNoneMatchHeader, and if not, we add one like so:
// We'll only add an ETag if there's no ETag specified in the user's
// request
NSString *specifiedETag = [request valueForHTTPHeaderField:kGTMIfNoneMatchHeader];
if (specifiedETag == nil) {
// No ETag: extract the previous ETag for this request from the
// fetch history, and add it to the request
NSString *cachedETag = [self cachedETagForRequest:request];
if (cachedETag != nil) {
[request addValue:cachedETag forHTTPHeaderField:kGTMIfNoneMatchHeader];
}
} else {
// Has an ETag: remove any stored response in the fetch history
// for this request, as the If-None-Match header could lead to
// a 304 Not Modified, and we want that error delivered to the
// user since they explicitly specified the ETag
[self removeCachedDataForRequest:request];
}
But if there is an ETag, we remove the cached data for the request. Since we're re-using the same request when we retry, we remove the cached data. So I'm not 100% sure, but I think the flow goes something like this:
- I issue a request to GDataServiceGooglePhotos
- request has no ETag, so try getting one from cached responses (as above) and send it along
- the request fails with -1003, but I catch this with my retrySelector, and tell it to retry
- now the request does have an ETag, so the cached data is removed (again as above), and the request is sent out
- the second response now comes back with 304
- we check the cache, there is no cached data for this request (we just cleared it)
- this causes the 304 error to propagate all the way back to me, which I don't want
If I comment out this: [self removeCachedDataForRequest:request];, everything works fine for my particular case, but obviously this is not a valid fix for the general case.
T.