Обработка перенаправлений правильно с NSURLConnection

Да, это он. Но помните, что 'count ()' делает еще один запрос, например:

Select count(q.*) from (select * from table) q

Это не оптимизируется. Вы можете использовать это:

from sqlalchemy.sql.functions import func
number = session.query(func.count(table.id).label('number').first().number

SQL-запрос будет выглядеть следующим образом:

Select count(table.id) from table
25
задан Steven Fisher 18 September 2009 в 19:58
поделиться

3 ответа

В разделе раздела 10.3.2 RFC 2616 содержится примечание об этом поведении:

Примечание. При автоматическом перенаправлении запроса POST после получения кода состояния 301 некоторые существующие Пользовательские агенты HTTP / 1.0 ошибочно преобразуют его в запрос GET.

Таким образом, это поведение кажется нестандартным, но историческим. Этот запрос GET не является POST, и в нем будет отсутствовать полезная нагрузка.

Интересно, что это тоже в том же разделе:

Если код состояния 301 получен в ответ на запрос, отличный от GET или HEAD, пользовательский агент НЕ ДОЛЖЕН автоматически перенаправлять запрос если это не может быть подтверждено пользователем, поскольку это может изменить условия, при которых был выполнен запрос.

Это довольно ясно и, кажется, указывает на то, что мы не можем это исправить, но я думаю, что игнорирование этого для целей наших собственных клиентов веб-служб для сервисов, которые мы выбираем (или контролируем), является, вероятно, наименее плохой альтернативой.

Так, как мы решаем это?

Вместо willSendResponse: в исходном вопросе я использую это:

- (NSURLRequest *)connection: (NSURLConnection *)connection
             willSendRequest: (NSURLRequest *)request
            redirectResponse: (NSURLResponse *)redirectResponse;
{
    if (redirectResponse) {
        // we don't use the new request built for us, except for the URL
        NSURL *newURL = [request URL];
        // Previously, store the original request in _originalRequest.
        // We rely on that here!
        NSMutableURLRequest *newRequest = [_originalRequest mutableCopy];
        [newRequest setURL: newURL];
        return newRequest;
    } else {
        return request;
    }
}

Идея в том, что вместо клонирования новый запрос и попытка сформировать его так же, как отправляет мне Cocoa Touch, я создаю клон исходного запроса и изменяю только URL, чтобы соответствовать запросу, отправленному мне Cocoa Touch. Этот первоначальный запрос все еще представляет собой POST с прикрепленной полезной нагрузкой.

Если вы управляете сервером, стоит прочитать RFC 2616, раздел 10.3 , чтобы увидеть, есть ли лучший код, который вы можете использовать (при проверке, конечно, что iOS обрабатывает лучший код как это должно).

Вы также можете сделать изменяемую копию перенаправленного запроса и заменить его метод HTTP на метод HTTP исходного запроса. Тот же самый общий принцип, хотя это будет способствовать сохранению вещей из нового запроса, а не из старого. В некоторых обстоятельствах это может работать лучше, но я еще не проверял это.

38
ответ дан Steven Fisher 15 October 2019 в 15:47
поделиться

У меня была такая же проблема с перенаправлением. Спасибо AJSoaks! Я попробовал, как он предложил, и проблема была решена.

Итак, я пытался опубликовать имя пользователя и пароль с помощью метода POST, и я увидел, что сервер перенаправил мой запрос. Как говорит AJSoaks, в случае ошибки 302 вы должны повторить запрос, но на этот раз, используя метод GET вместо предыдущего POST.

... в какой-то момент у вас есть следующие строки: ... он может быть внутри, если ваш метод IBAction (нажата кнопка) или где вы хотите ...

NSMutableString *postString = [[NSMutableString alloc] init];

[postString appendString:@"username=YourUsername&password=YourPassword"];

    //the original URL (https means that it supports SSL protocol)
    //it doesn't change anything, don't worry about it
NSURL *URL = [NSURL URLWithString:@"https://loginWebpageURL"];

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL];

[request setHTTPMethod:@"POST"];    
[request setValue:[NSString stringWithFormat:@"%d", [postString length]] forHTTPHeaderField:@"Content-length"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-type"];
[request setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]];

[NSURLConnection connectionWithRequest:request delegate:self];

[postString release];
[request release];

Чем вы должны также реализовать метод делегата перенаправления NSURLConnection со следующей сигнатурой:

- (NSURLRequest *)connection:(NSURLConnection *)connection
            willSendRequest:(NSURLRequest *)request
           redirectResponse:(NSURLResponse *)redirectResponse

внутри этого метода, в случае, если у вас есть ошибки СЕРВЕРА 302 или 303, вы должны реализовать что-то аналогично приведенному ниже коду, просто скопируйте код, который вы видите, и замените его новым URL (перенаправленным). Новый URL вы можете увидеть в браузере или, если хотите, он будет очень полезен, и в будущем, проверяя его с помощью Firebug (плагин Firefox) или Safari WEB INSPECTOR. Если вы используете Firebug всю информацию, которую вы можете найти в разделе «Сеть»:

if (redirectResponse) {

    NSLog(@"REDIRECT");
    NSMutableURLRequest *requestTmp = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"https://areaclienti.tre.it/selfcare/areaclienti133/4552_infoCosti_ITA_HTML.xsl"]];

    return [requestTmp autorelease];
}

//return original request in case thay there is no redirecting...
else return request;
4
ответ дан Otávio 15 October 2019 в 15:47
поделиться

Вы должны проверить код состояния HTTP-ответа, отправленный сервером, чтобы определить, следует ли отправлять GET или повторить POST. Для 303 (или 302) отправьте запрос GET. Для 307 повторите POST.

13
ответ дан 28 November 2019 в 20:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: