New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(2.2) AFHTTPSessionManager seems to ignore timeoutIntervalForRequest #1897

Closed
loicgardiol opened this Issue Mar 11, 2014 · 9 comments

Comments

Projects
None yet
4 participants
@loicgardiol
Copy link

loicgardiol commented Mar 11, 2014

Assuming that kGetConfigURLString is a URL that cannot be reached, following code executes failure with timeout error after a longer timeout (~20 s) than the 3 seconds of the configuration.

The behavior is normal in 2.1.

I ran test the tests in the iOS Simulator and on an iPhone 5 (both on iOS 7.1).

NSURLSessionConfiguration* config = [NSURLSessionConfiguration defaultSessionConfiguration];
config.timeoutIntervalForRequest = 3.0;

AFHTTPSessionManager* manager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:config];

[manager GET:kGetConfigURLString
      parameters:nil
         success:^(NSURLSessionDataTask *task, NSDictionary* jsonServerConfig) {
             //success
         } failure:^(NSURLSessionDataTask *task, NSError *error) {
             //failure
         }
];
@loicgardiol

This comment has been minimized.

Copy link

loicgardiol commented Mar 11, 2014

After some investigation, in AFURLSessionManager.m:439, dataTask.originalRequest.timeoutInterval is 60, while self.session.configuration.timeoutIntervalForRequest is 3.

@mattt

This comment has been minimized.

Copy link
Contributor

mattt commented Mar 13, 2014

As of 2.2, AFHTTPRequestSerializer sets an explicit default timeoutInterval of 60 seconds.

Apple strongly recommends that timeouts not be any shorter than this.

The timeout interval, in seconds. If during a connection attempt the request remains idle for longer than the timeout interval, the request is considered to have timed out. The default timeout interval is 60 seconds.

Note: In iOS versions prior to iOS 6, the minimum (and default) timeout interval for any request containing a request body was 240 seconds.

As a general rule, you should not use short timeout intervals, and instead, should provide an easy way for the user to cancel a long-running operation. For more information, read “Designing for Real-World Networks”.

@mattt mattt closed this Mar 13, 2014

@ghost

This comment has been minimized.

Copy link

ghost commented Mar 19, 2014

Applications can make requests that have no corresponding UI. They might not need the responses badly enough to wait around for a minute. Why is enforcing this recommendation any of AFNetworking's business?

The insanity of codifying some vague human interface guideline recommendation of Apple's in a networking library aside, why does it pretend accept a session configuration object at all if all it's going to do is override the values we set in it?

@mattt

This comment has been minimized.

Copy link
Contributor

mattt commented Mar 20, 2014

@oncomeme AFNetworking isn't enforcing anything. That's just the default behavior.

And besides, those recommendations are anything but vague. Seriously, read “Designing for Real-World Networks”.

@ghost

This comment has been minimized.

Copy link

ghost commented Mar 20, 2014

Those recommendations are utterly irrelevant in my case as this application's users will never even see the screen it's running on. Their sole purpose in life is to scan a barcode and wait for a confirmation signal to come out of the single-buttoned peripheral. If they do not get that confirmation signal back immediately for any reason whatsoever, then they need to throw it down and revert to a manual input process as any delay on their part is going to hold up the line of people waiting on them. 60 seconds is completely unacceptable. They need a "go or no go" signal back much faster than that.

Will networks go down? Yup. Can I give these people any kind of "cancel" button to interact with. Nope. Is it any networking library's job to tell me that I can't do what I need to? Absolutely not.

@loicgardiol

This comment has been minimized.

Copy link

loicgardiol commented Mar 20, 2014

I can understand @mattt's point. The timeout of a request is there to deal with network reachability issues. In this context, very low values make the request be considered as having failed, while it's likely that it would have succeeded shortly after the timeout, especially in cellular environment.

Now, in my case, the app needs to fetch a configuration at startup (shows a splash screen during the operation). It is ok if it fails as it will simply use the latest one that could be downloaded (during a previous launch), or a bundled one. But a slow connection should not prevent the app from launching, that's why I needed a very small value.

What I ended up doing is to cancel the task if it is still running after the 3 seconds.

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        if (task.state == NSURLSessionTaskStateRunning) {
            [task cancel];
        }
    });
@ghost

This comment has been minimized.

Copy link

ghost commented Mar 21, 2014

I did the exact same thing--that doesn't mean it makes a damn bit of sense for this object to pretend to allow a more conventional and straightforward timeout configuration just so it can ignore it because short timeouts aren't cool this week. The imposition of these ridiculous ideologies might make somebody seem like a hero to people who are building Twitter clients and weather apps, but it does not belong in anything claiming to be a networking library.

@tewha

This comment has been minimized.

Copy link
Contributor

tewha commented Mar 21, 2014

Why are you complaining? The timeout is exposed as a property. Change it.

@colinta

This comment has been minimized.

Copy link

colinta commented Jan 14, 2015

Note to future googlers like myself: Setting timeoutIntervalForRequest did not have the behavior I expected, but the documentation mentions why:

This will cause a timeout if no data is transmitted for the given timeout value, and is reset whenever data is transmitted

The property that works is timeoutIntervalForResource:

This will cause a timeout if a resource is not able to be retrieved within a given timeout

CC @oncomeme @loicgardiol

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment