ASIFormDataRequest- POST файла продолжается, кажется, продолжается после сбоя аутентификации

Я отправляю некоторые данные на http-аутентифицированный URL-адрес с помощью ASIFormDataRequest.

Когда аутентификация завершается неудачно и вызывается делегат диалога аутентификации, кажется, что процесс загрузки все еще продолжается полностью.

Итак, в этих случаях:

1) Учетные данные пользователя еще не сохранены в цепочке для ключей 2) Учетные данные пользователя, которые хранятся в цепочке для ключей, не проходят аутентификацию (истек срок действия и т. д.)

Я вижу такое поведение:

  • Я вижу, что запрос пришел на мой сервер, а клиенту возвращена ошибка 401.
  • Делегат uploadFailed не вызывается.
  • Делегат индикатора выполнения медленно заполняется, поскольку кажется, что файл все еще выталкивается по сетевому соединению. Он завершается за время, соответствующее количеству времени, необходимому для полной загрузки.
  • Появится встроенный модальный диалог аутентификации.
  • Пользователь вводит правильные учетные данные
  • Сброс делегата индикатора выполнения
  • Загрузка начинается снова — индикатор выполнения заполняется по мере поступления данных на сервер
  • Готовый метод делегата вызывается, как и ожидалось.
  • Все загрузилось просто отлично со второй попытки

Здесь я настраиваю свою операцию:

[self setRequest:[ASIFormDataRequest requestWithURL:uploadURL]];

[request setDelegate:self];
[request setDidFailSelector:@selector(uploadFailed:)];
[request setDidFinishSelector:@selector(uploadFinished:)];

[request setUseKeychainPersistence:TRUE];
[request setShouldPresentAuthenticationDialog:TRUE];
[request setShouldPresentCredentialsBeforeChallenge:TRUE];

[request setPostValue:captionTextField.text forKey:@"caption"];
[request setPostValue:[siteID stringValue] forKey:@"site_id"];
[request setFile:fileToUpload forKey:@"site_photo"];

[request setUploadProgressDelegate:progressView];
[request startAsynchronous];

Я думаю, что мне нужно выдать [запрос на отмену] после сбоя аутентификации, но я не уверен, где я должен это делать.

Ожидается ли такое поведение, что POST все равно будет отклоняться даже после того, как сервер вернет 401?

Ценим любые рекомендации или указатели на существующие вопросы, касающиеся этого.


person Nick    schedule 11.08.2010    source источник


Ответы (2)


Это довольно распространенное поведение для HTTP-клиентов — они не пытаются прочитать ответ с сервера, пока полностью не отправят запрос, включая вложенный файл.

Клиент обычно упреждающе отправляет аутентификацию, если у него уже есть запрос с того же сервера, отклоненный с ошибкой 401 в том же сеансе. Я не уверен, делает ли это ASIHTTPRequest, но если это произойдет, одно решение будет сделать запрос GET на сервер перед выполнением POST. Если GET успешно аутентифицирован, то кэшированные учетные данные должны быть отправлены для публикации, и, следовательно, ошибки 401 не будет.

Единственный другой вариант, который я могу придумать, - это перейти на аутентификацию на основе файлов cookie, если вы контролируете сервер, или использовать аутентификацию в пользовательском заголовке http. Но я думаю, что мое предложение сначала выполнить запрос GET может быть лучшим подходом.

person JosephH    schedule 12.08.2010
comment
Спасибо - я перешел к выполнению начального GET до POST. В других ситуациях я использовал механизм аутентификации на основе файлов cookie, но по ряду причин в этой конкретной ситуации необходим базовый HTTP. - person Nick; 17.08.2010

«Ошибка» 401 — это код состояния HTTP, а не ошибка запроса. Ваш запрос прошел нормально, и вы получили ответ, который оказался уведомлением об ошибке аутентификации. Вы несете ответственность за обработку ответа, каким бы он ни был.

Существует много возможных кодов состояния, которые можно получить из успешного запроса, кроме 401. Как кроме того, вы можете подумать о том, как обрабатывать такие ответы, в зависимости от того, что делает конечный пользователь и какие ответы являются подходящими.

Как правило, метод -uploadFinished: не должен ждать, пока данные будут полностью загружены, прежде чем вы увидите какие-либо операторы NSLog или другое уведомление о завершении запроса.

Поэтому нужно изменить имена методов -uploadFailed: и -uploadFinished: на -requestFailed: и -requestFinished:, чтобы более точно отразить то, что происходит в логике вашего приложения.

В методе -requestFinished: вашего делегата проверьте свойство responseStatusCode request и введите соответствующие команды:

- (void) requestFinished:(ASIHTTPRequest *)request {
    if ([request responseStatusCode] == 401) {
        //
        // cancel the current request and/or trigger a new, 
        // separate authentication request, passing along a 
        // reference to the request's body data, etc. 
        //
    }
}
person Alex Reynolds    schedule 11.08.2010
comment
Оценка, полученная по запросу, по сравнению с именами загрузки и ошибками по сравнению с кодами состояния. Как правило, я считаю, что люди обычно называют ошибкой все, что находится в диапазоне 4xx, но вы правы, и я ценю обратную связь. Я ищу этот код состояния в готовом делегате, но делегат не вызывается до тех пор, пока все данные не будут переданы - я думаю, я ошибочно полагал, что ответ 401 будет возвращен, а делегат вызывается перед всеми данными в составной форме. было отправлено. Я предполагаю, что мне нужно подтвердить, что я аутентифицирован, прежде чем пытаться отправить POST, или посмотреть, получу ли я 401 раньше с didRecieveData. - person Nick; 12.08.2010