Używam HttpUrlConnection
do wysyłania żądań sieciowych z mojej aplikacji Android. Wszystko działa dobrze, z wyjątkiem jednego, 401. Kiedy serwer zwraca odpowiedź z kodem stanu 401, moja aplikacja wyrzuca IOException
z komunikatem: "no authentication challenge found"
. Po przeszukaniu go, nie znalazłem żadnego rozwiązania, ale tylko obejście (posługiwanie się nim przy użyciu try/catch, przy założeniu, że jest to odpowiedź 401).Jak uzyskać odpowiedź 401 bez posługiwania się nią przy użyciu funkcji prób/catch w Androidzie
oto fragment kodu:
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;
}
naprawdę chcę wiedzieć, dlaczego to jest wyjątek? Co oznacza wyzwanie uwierzytelniania? Jak zapewnić wyzwanie uwierzytelnienia? jaka zmiana muszę wprowadzić w moim kodzie, aby przezwyciężyć tę sytuację?
Proszę mnie oświecić .. :)
Przypuszczam, oznacza to, że serwer odpowiedział kodem błędu 401, ale pominięto 'nagłówek WWW-Authenticate' który opisuje wyzwania uwierzytelnienia. – Jens
Serwer ma nagłówek 'WWW-Authenticate', ale wciąż dostaję ten błąd. – jtanveer
Po prostu wpadłem na to, a także nie mogę wymyślić, jak uzyskać ten kod odpowiedzi z powrotem bez konieczności założenia, że jest to 401 po złapaniu wyjątku IOException (ponieważ 'getResponseCode()' sam rzuci ten sam wyjątek IOException co 'connect()/getInputStream()/getOutputStream() '). Z pliku stacktrace wydaje się, że 'org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.processAuthHeader (HttpURLConnectionImpl.java:1153)' jest odpowiedzialny za wyrzucenie wyjątku w górę łańcucha (chociaż nie mogłem zanurkować dalej). –