Как получить ответ 401 без обработки с помощью try/catch в android
Я использую HttpUrlConnection
для создания сетевых запросов от моего приложения для Android. Все работает отлично, за исключением одного, 401. Когда сервер возвращает ответ со статусом 401, мое приложение бросает IOException
с сообщением, "no authentication challenge found"
. После его поиска я не нашел ни одного решения, но только обходное решение (обрабатывая его с помощью try/catch, предполагая его ответ 401).
вот фрагмент кода:
public Bundle request(String action, Bundle params, String cookie) throws FileNotFoundException, MalformedURLException, SocketTimeoutException,
IOException {
OutputStream os;
String url = baseUrl + action;
Log.d(TAG, url);
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
conn.setConnectTimeout(30 * 1000);
conn.setReadTimeout(30 * 1000);
conn.setRequestProperty("User-Agent", System.getProperties().getProperty("http.agent") + "AndroidNative");
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setDoOutput(true);
conn.setDoInput(true);
if (cookie != null) {
conn.setRequestProperty("Cookie", cookie);
}
if (params != null) {
os = conn.getOutputStream();
os.write(("--" + boundary + endLine).getBytes());
os.write((encodePostBody(params, boundary)).getBytes());
os.write((endLine + "--" + boundary + endLine).getBytes());
uploadFile(params, os);
os.flush();
os.close();
}
conn.connect();
Bundle response = new Bundle();
try {
response.putInt("response_code", conn.getResponseCode());
Log.d(TAG, conn.getResponseCode() + "");
response.putString("json_response", read(conn.getInputStream()));
List<String> responseCookie = conn.getHeaderFields().get("set-cookie");
// Log.d(TAG, responseCookie.get(responseCookie.size() - 1));
response.putString("cookie", responseCookie.get(responseCookie.size() - 1));
} catch (SocketTimeoutException e) {
throw new SocketTimeoutException(e.getLocalizedMessage());
} catch (FileNotFoundException e) {
throw new FileNotFoundException(e.getLocalizedMessage());
} catch (IOException e) {
e.printStackTrace();
response.putInt("response_code", HttpURLConnection.HTTP_UNAUTHORIZED);
response.putString("json_response", read(conn.getErrorStream()));
}
// debug
Map<String, List<String>> map = conn.getHeaderFields();
for (String key : map.keySet()) {
List<String> values = map.get(key);
for (String value : values) {
Log.d(key, value);
}
}
conn.disconnect();
return response;
}
Я действительно хочу знать, почему это исключение выбрано? Что означает проверка подлинности? Как обеспечить проверку подлинности? какое изменение я должен внести в свой код, чтобы преодолеть эту ситуацию?
Прошу просветить меня..:)
Ответы
Ответ 1
IOException - довольно общее исключение, и вы не можете безопасно принимать код статуса 401 каждый раз, когда он бросается.
Если в первый раз, когда вы запрашиваете код состояния, он содержит 401, HttpURLConnection будет вызывать исключение IOException. На этом этапе внутренний статус соединения изменится, и теперь он сможет дать вам код состояния без каких-либо ошибок.
int status = 0;
try {
status = conn.getResponseCode();
} catch (IOException e) {
// HttpUrlConnection will throw an IOException if any 4XX
// response is sent. If we request the status again, this
// time the internal status will be properly set, and we'll be
// able to retrieve it.
status = conn.getResponseCode();
}
if (status == 401) {
// ...
}
Для более подробной информации http://www.tbray.org/ongoing/When/201x/2012/01/17/HttpURLConnection
Ответ 2
попробуйте использовать HttpClient
private void setCredentials(String login, String password) {
if (login != null && password != null)
httpClient.getCredentialsProvider().setCredentials(
new AuthScope(URL_HOST, 80), new UsernamePasswordCredentials(login, password));
}
private InputStream execute(String url, String login, String password) {
setCredentials(login, password);
HttpGet get = new HttpGet(url);
try {
HttpResponse response = httpClient.execute(get);
int code = response.getStatusLine().getStatusCode();
if (code == HttpURLConnection.HTTP_OK) {
InputStream stream = response.getEntity().getContent();
return stream;
} else {
Log.e("TAG", "Wrong response code " + code + " for request " + get.getRequestLine().toString());
return null;
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}