Automatic custom authentication - java

I want to use Apache HttpClient 4+ to send authenticated requests to an HTTP server (actually, I need this for different server implementations) AND to authenticate (or re-authenticate) automatically ONLY when it is required, when auth token is not present or it is dead.
In order to authenticate I need to send a POST request with JSON containing user credentials.
In case authentication token is not provided in the cookie, one server returns status code 401, another one 500 with AUTH_REQUIRED text in the response body.
I played a lot with different HttpClient versions by setting CredentialsProvider with proper Credentials, trying to implement own AuthScheme and registering it and unregistering the rest of standard ones.
I also tried to set own AuthenticationHandler. When isAuthenticationRequested is called I'm analyzing HttpResponse which is passed as the method argument and decided what to return by analyzing status code and response body. I expected that this (isAuthenticationRequested() == true) is what force the client to authenticate by calling AuthScheme.authenticate (my AuthScheme implementation which is returned by AuthenticationHandler.selectScheme), but instead of AuthScheme.authenticate invocation I can see AuthenticationHandler.getChallenges. I really don't know what I should return by this method, thus I'm just returning new HashMap<>().
Here is debug output I have in result
DEBUG org.apache.http.impl.client.DefaultHttpClient - Authentication required
DEBUG org.apache.http.impl.client.DefaultHttpClient - example.com requested authentication
DEBUG com.test.httpclient.MyAuthenticationHandler - MyAuthenticationHandler.getChallenges()
DEBUG org.apache.http.impl.client.DefaultHttpClient - Response contains no authentication challenges
What should I do next? Am I moving in the right direction?
UPDATE
I've almost achieved what I needed. Unfortunately, I can't provide fully working project sources, because I can't provide public access to my server. Here is my simplified code example:
MyAuthScheme.java
public class MyAuthScheme implements ContextAwareAuthScheme {
public static final String NAME = "myscheme";
#Override
public Header authenticate(Credentials credentials,
HttpRequest request,
HttpContext context) throws AuthenticationException {
HttpClientContext clientContext = ((HttpClientContext) context);
String name = clientContext.getTargetAuthState().getState().name();
// Hack #1:
// I've come to this check. I don't like it, but it allows to authenticate
// first request and don't repeat authentication procedure for further
// requests
if(name.equals("CHALLENGED") && clientContext.getResponse() == null) {
//
// auth procedure must be here but is omitted in current example
//
// Hack #2: first request won't be present with auth token cookie set via cookie store
request.setHeader(new BasicHeader("Cookie", "MYAUTHTOKEN=bru99rshi7r5ucstkj1wei4fshsd"));
// this works for second and subsequent requests
BasicClientCookie authTokenCookie = new BasicClientCookie("MYAUTHTOKEN", "bru99rshi7r5ucstkj1wei4fshsd");
authTokenCookie.setDomain("example.com");
authTokenCookie.setPath("/");
BasicCookieStore cookieStore = (BasicCookieStore) clientContext.getCookieStore();
cookieStore.addCookie(authTokenCookie);
}
// I can't return cookie header here, otherwise it will clear
// other cookies, right?
return null;
}
#Override
public void processChallenge(Header header) throws MalformedChallengeException {
}
#Override
public String getSchemeName() {
return NAME;
}
#Override
public String getParameter(String name) {
return null;
}
#Override
public String getRealm() {
return null;
}
#Override
public boolean isConnectionBased() {
return false;
}
#Override
public boolean isComplete() {
return true;
}
#Override
public Header authenticate(Credentials credentials,
HttpRequest request) throws AuthenticationException {
return null;
}
}
MyAuthStrategy.java
public class MyAuthStrategy implements AuthenticationStrategy {
#Override
public boolean isAuthenticationRequested(HttpHost authhost,
HttpResponse response,
HttpContext context) {
return response.getStatusLine().getStatusCode() == 401;
}
#Override
public Map<String, Header> getChallenges(HttpHost authhost,
HttpResponse response,
HttpContext context) throws MalformedChallengeException {
Map<String, Header> challenges = new HashMap<>();
challenges.put(MyAuthScheme.NAME, new BasicHeader(
"WWW-Authentication",
"Myscheme realm=\"My SOAP authentication\""));
return challenges;
}
#Override
public Queue<AuthOption> select(Map<String, Header> challenges,
HttpHost authhost,
HttpResponse response,
HttpContext context) throws MalformedChallengeException {
Credentials credentials = ((HttpClientContext) context)
.getCredentialsProvider()
.getCredentials(new AuthScope(authhost));
Queue<AuthOption> authOptions = new LinkedList<>();
authOptions.add(new AuthOption(new MyAuthScheme(), credentials));
return authOptions;
}
#Override
public void authSucceeded(HttpHost authhost, AuthScheme authScheme, HttpContext context) {}
#Override
public void authFailed(HttpHost authhost, AuthScheme authScheme, HttpContext context) {}
}
MyApp.java
public class MyApp {
public static void main(String[] args) throws IOException {
CredentialsProvider credsProvider = new BasicCredentialsProvider();
Credentials credentials = new UsernamePasswordCredentials("user#example.com", "secret");
credsProvider.setCredentials(AuthScope.ANY, credentials);
HttpClientContext context = HttpClientContext.create();
context.setCookieStore(new BasicCookieStore());
context.setCredentialsProvider(credsProvider);
CloseableHttpClient client = HttpClientBuilder.create()
// my server requires this header otherwise it returns response with code 500
.setDefaultHeaders(Collections.singleton(new BasicHeader("x-requested-with", "XMLHttpRequest")))
.setTargetAuthenticationStrategy(new MyAuthStrategy())
.build();
String url = "https://example.com/some/resource";
String url2 = "https://example.com/another/resource";
// ======= REQUEST 1 =======
HttpGet request = new HttpGet(url);
HttpResponse response = client.execute(request, context);
String responseText = EntityUtils.toString(response.getEntity());
request.reset();
// ======= REQUEST 2 =======
HttpGet request2 = new HttpGet(url);
HttpResponse response2 = client.execute(request2, context);
String responseText2 = EntityUtils.toString(response2.getEntity());
request2.reset();
// ======= REQUEST 3 =======
HttpGet request3 = new HttpGet(url2);
HttpResponse response3 = client.execute(request3, context);
String responseText3 = EntityUtils.toString(response3.getEntity());
request3.reset();
client.close();
}
}
Versions
httpcore: 4.4.6
httpclient: 4.5.3
Probably this is not the best code but at least it works.
Please look at my comments in MyAuthScheme.authenticate() method.

This works as expected for me with Apache HttpClient 4.2
NOTE. Though it is compiled and executed with httpclient 4.5, its execution falls into forever loop.
MyAuthScheme.java
public class MyAuthScheme implements ContextAwareAuthScheme {
public static final String NAME = "myscheme";
private static final String REQUEST_BODY = "{\"login\":\"%s\",\"password\":\"%s\"}";
private final URI loginUri;
public MyAuthScheme(URI uri) {
loginUri = uri;
}
#Override
public Header authenticate(Credentials credentials,
HttpRequest request,
HttpContext context) throws AuthenticationException {
BasicCookieStore cookieStore = (BasicCookieStore) context.getAttribute(ClientContext.COOKIE_STORE);
DefaultHttpClient client = new DefaultHttpClient();
// authentication cookie is set automatically when
// login response arrived
client.setCookieStore(cookieStore);
HttpPost loginRequest = new HttpPost(loginUri);
String requestBody = String.format(
REQUEST_BODY,
credentials.getUserPrincipal().getName(),
credentials.getPassword());
loginRequest.setHeader("Content-Type", "application/json");
try {
loginRequest.setEntity(new StringEntity(requestBody));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
try {
HttpResponse response = client.execute(loginRequest);
int code = response.getStatusLine().getStatusCode();
EntityUtils.consume(response.getEntity());
if(code != 200) {
throw new IllegalStateException("Authentication problem");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
loginRequest.reset();
}
return null;
}
#Override
public void processChallenge(Header header) throws MalformedChallengeException {}
#Override
public String getSchemeName() {
return NAME;
}
#Override
public String getParameter(String name) {
return null;
}
#Override
public String getRealm() {
return null;
}
#Override
public boolean isConnectionBased() {
return false;
}
#Override
public boolean isComplete() {
return false;
}
#Override
public Header authenticate(Credentials credentials,
HttpRequest request) throws AuthenticationException {
// not implemented
return null;
}
}
MyAuthSchemeFactory.java
public class MyAuthSchemeFactory implements AuthSchemeFactory {
private final URI loginUri;
public MyAuthSchemeFactory(URI uri) {
this.loginUri = uri;
}
#Override
public AuthScheme newInstance(HttpParams params) {
return new MyAuthScheme(loginUri);
}
}
MyAuthStrategy.java
public class MyAuthStrategy implements AuthenticationStrategy {
#Override
public boolean isAuthenticationRequested(HttpHost authhost,
HttpResponse response,
HttpContext context) {
return response.getStatusLine().getStatusCode() == 401;
}
#Override
public Map<String, Header> getChallenges(HttpHost authhost,
HttpResponse response,
HttpContext context) throws MalformedChallengeException {
Map<String, Header> challenges = new HashMap<>();
challenges.put("myscheme", new BasicHeader("WWW-Authenticate", "myscheme"));
return challenges;
}
#Override
public Queue<AuthOption> select(Map<String, Header> challenges,
HttpHost authhost,
HttpResponse response,
HttpContext context) throws MalformedChallengeException {
AuthSchemeRegistry registry = (AuthSchemeRegistry) context.getAttribute(ClientContext.AUTHSCHEME_REGISTRY);
AuthScheme authScheme = registry.getAuthScheme(MyAuthScheme.NAME, new BasicHttpParams());
CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(ClientContext.CREDS_PROVIDER);
Credentials credentials = credsProvider.getCredentials(new AuthScope(authhost));
Queue<AuthOption> options = new LinkedList<>();
options.add(new AuthOption(authScheme, credentials));
return options;
}
#Override
public void authSucceeded(HttpHost authhost, AuthScheme authScheme, HttpContext context) {}
#Override
public void authFailed(HttpHost authhost, AuthScheme authScheme, HttpContext context) {}
}
App.java
public class App {
public static void main(String[] args) throws IOException, URISyntaxException {
URI loginUri = new URI("https://example.com/api/v3/users/login");
AuthSchemeRegistry schemeRegistry = new AuthSchemeRegistry();
schemeRegistry.register(MyAuthScheme.NAME, new MyAuthSchemeFactory(loginUri));
BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(
new AuthScope("example.com", 8065),
new UsernamePasswordCredentials("user1#example.com", "secret"));
DefaultHttpClient client = new DefaultHttpClient();
client.setCredentialsProvider(credentialsProvider);
client.setTargetAuthenticationStrategy(new MyAuthStrategy());
client.setAuthSchemes(schemeRegistry);
client.setCookieStore(new BasicCookieStore());
String getResourcesUrl = "https://example.com:8065/api/v3/myresources/";
HttpGet getResourcesRequest = new HttpGet(getResourcesUrl);
getResourcesRequest.setHeader("x-requested-with", "XMLHttpRequest");
try {
HttpResponse response = client.execute(getResourcesRequest);
// consume response
} finally {
getResourcesRequest.reset();
}
// further requests won't call MyAuthScheme.authenticate()
HttpGet getResourcesRequest2 = new HttpGet(getResourcesUrl);
getResourcesRequest2.setHeader("x-requested-with", "XMLHttpRequest");
try {
HttpResponse response2 = client.execute(getResourcesRequest);
// consume response
} finally {
getResourcesRequest2.reset();
}
HttpGet getResourcesRequest3 = new HttpGet(getResourcesUrl);
getResourcesRequest3.setHeader("x-requested-with", "XMLHttpRequest");
try {
HttpResponse response3 = client.execute(getResourcesRequest);
// consume response
} finally {
getResourcesRequest3.reset();
}
}
}

Related

okHttp 3.x authenticator is not getting called

I need to make a request through a proxy that needs authentication.
public class WebClient {
private final OkHttpClient httpClient;
private static WebClient webClient;
private WebClient() {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
if (Configurator.getInstance().useProxy()) {
builder.proxySelector(new CustomProxySelector());
builder.authenticator((Route route, Response response) -> {
String credential = Credentials.basic("MYUSER", "MYPSW");
return response.request().newBuilder().header("Authorization", credential).build();
});
} else
builder.proxy(Proxy.NO_PROXY);
httpClient = builder
.connectTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.build();
}
}
But using a debugger i see that the authenticator method never gets called and i receive 407 as response for any request.
However, when i use HttpURLConnection with Authenticator.setDefault, it works just fine and i can use my proxy authentication:
public boolean hasInternetConnection() throws IOException {
Request httpRequest = new Request.Builder().url("http://www.google.com/").build();
// This fails with 407
Response httpResponse = httpClient.newCall(httpRequest).execute();
java.net.Authenticator authenticator = new java.net.Authenticator() {
public PasswordAuthentication getPasswordAuthentication() {
return (new PasswordAuthentication("MYUSER", "MYPSW".toCharArray()));
}
};
java.net.Authenticator.setDefault(authenticator);
URL obj = new URL("http://www.google.com/");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
// This works with 200
int responseCode = con.getResponseCode();
return false;
}
So i think the question is: why OkHttpClient.Builder.authenticator method is not getting called?
As Gimby pointed, one of the issues was that i was calling the wrong method. What confused me was that sometimes the proxyAuthenticator was not getting called and i was trying to figure why.
The application i develop needs to access resources inside and outside my job network. Therefore, when i need external access, i must use a proxy with authentication. It works like this:
A request to an internet host is made;
The ProxySelector decides that the HTTP client should use the proxy for this
request, since it is an internet host;
Since the proxy is set, the ProxyAuthenticator gets called to send
the authorization header in the request.
However, when a request is made to an internal host, the ProxySelector decides that there is no need to use a proxy. Therefore, the ProxyAuthenticator does not get called, since there is no active proxy.
Here is my implementation to anyone interested:
WebClient.java
public class WebClient {
private final OkHttpClient httpClient;
private static WebClient webClient;
private WebClient() {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
if (Configurator.getInstance().useProxy()) {
CodeUtils.setProxy();
builder.proxySelector(new CustomProxySelector());
builder.proxyAuthenticator(new CustomProxyAuthenticator());
} else {
builder.proxy(Proxy.NO_PROXY);
CodeUtils.removeProxy();
}
httpClient = builder
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.build();
}
public static WebClient getInstance() {
return webClient != null ? webClient : (webClient = new WebClient());
}
public static void reload() {
webClient = null;
}
public String doGet(String url) throws IOException {
Request httpRequest = new Request.Builder().url(url).build();
Response httpResponse = httpClient.newCall(httpRequest).execute();
if (httpResponse.code() != 200) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("success", false);
jsonObject.put("msg", httpResponse.body().string());
jsonObject.put("httpCode", httpResponse.code());
return jsonObject.toString();
}
return httpResponse.body().string();
}
public String doPost(String url, JSONObject body) throws IOException {
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), body.toString());
Request request = new Request.Builder()
.header("Accept", "application/json")
.header("Content-type", "application/json; charset=UTF-8")
.url(url)
.post(requestBody).build();
Response response = httpClient.newCall(request).execute();
return response.body().string();
}
}
CustomProxyAuthenticator.java
public class CustomProxyAuthenticator implements Authenticator {
#Override
public Request authenticate(Route route, Response response) throws IOException {
String username = Configurator.getInstance().getProxyUser();
String password = Configurator.getInstance().getProxyPassword();
String credential = Credentials.basic(username, password);
return response.request().newBuilder()
.header("Proxy-Authorization", credential)
.build();
}
}
CustomProxySelector.java
public class CustomProxySelector extends ProxySelector {
private Configurator configurator = Configurator.getInstance();
private List<String> nonProxyHosts = Arrays.asList(configurator.getNonProxyHosts().split("\\|"));
private String proxyHost = configurator.getProxyHost();
private int proxyPort = configurator.getProxyPort();
#Override
public List<Proxy> select(URI uri) {
final List<Proxy> proxyList = new ArrayList<>(1);
String host = uri.getHost();
if (host.startsWith("127.0.0.1") || nonProxyHosts.contains(host))
proxyList.add(Proxy.NO_PROXY);
else
proxyList.add(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)));
return proxyList;
}
#Override
public void connectFailed(URI arg0, SocketAddress arg1, IOException arg2) {
}
}

Android: from DefaultHttpClient to Retrofit

I am struggling in finding a replacement for the deprecated DefaultHttpClient and connected classes liken HttpPost etc.
In a first attempt, I tried using the volley library, but nothing seemed to work, so after a bit research I am trying now with Retrofit 1.9.
In my app, I connect to a own restful client. Here is the old code (example POST), which works perfectly well:
private static DefaultHttpClient httpClient = new DefaultHttpClient();
public static String executePOST(Map<String, String> postParams, int connTO, int sockTO, String uri){
String res, message;
HttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams, connTO);
HttpConnectionParams.setSoTimeout(httpParams, sockTO);
HttpConnectionParams.setTcpNoDelay(httpParams, true);
httpClient.setParams(httpParams);
HttpPost httppost = new HttpPost(uri);
JSONObject json = new JSONObject();
try {
Iterator<Entry<String, String>> iterator = postParams.entrySet().iterator();
while(iterator.hasNext()){
Map.Entry<String, String> pair = (Map.Entry<String, String>)iterator.next();
json.put(pair.getKey(), pair.getValue());
}
message = json.toString();
httppost.setEntity(new StringEntity(message, "UTF8"));
httppost.setHeader("Accept", "application/json");
httppost.setHeader("Content-type", "application/json");
HttpResponse response = httpClient.execute(httppost);
HttpEntity entity = response.getEntity();
res = EntityUtils.toString(entity).trim();
} catch (ClientProtocolException e) {
res = "Client Protocol Exception";
} catch (IOException e) {
res = e.getLocalizedMessage();
} catch (JSONException e){
res = e.getLocalizedMessage();
}
return res;
}
I send the request like this from my Activity
Map<String, String> arguments = new HashMap<String, String>();
arguments.put("email", username);
new HttpClient(arguments, new LoginActivityCommunicationListener(this, LoginOperation.EMAIL_CHECK), URI_ROOT + "/kunde", 0).execute();
The listener in the arguments handles the response callback, the 0 means POST.
this results in a JSON response, having the fields id and person
So I tried to implement a Retrofit variant of above like this
MyApi.java
public interface MyDosAPI {
#FormUrlEncoded
#POST("/kunde")
public void checkEmail(#Field("email") String email, Callback<EmailCheck> response);
}
EmailCheck.java
public class EmailCheck {
#SerializedName("id")
private String id;
#SerializedName("person")
private String person;
public void setId(String id){
this.id = id;
}
public void setPerson(String person){
this.person = person;
}
public String getId(){
return id;
}
public String getPerson(){
return person;
}
}
and in the activity
RestAdapter adapter = new RestAdapter.Builder()
.setEndpoint(URI_ROOT)
.build();
MyDosAPI api = adapter.create(MyDosAPI.class);
api.checkEmail(username, new Callback<EmailCheck>() {
#Override
public void success(EmailCheck emailChecks, Response response) {
Log.i("MyCount", "success");
}
#Override
public void failure(RetrofitError error) {
Log.i("MyCount", error.getMessage());
}
});
result
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $
obviously there is something essential that I am missing. Is there - apart of Retrofit or Volley - another solution where I can define the requests like I did before?
Change to:
public interface MyDosAPI {
#POST("/kunde")
public void checkEmail(#Body String email, Callback<EmailCheck> response);
}

Android: How to replace deprecated HttpRequestExecutor

I am trying to remove the HttpClient api from my Android project and to transition to using HttpURLConnection.
In the old API, I made use of HttpRequestExecutor, to change some icon in the notification bar when the app is downloading vs uploading
this.httpclient = new DefaultHttpClient(httpParameters){
#Override
protected HttpRequestExecutor createRequestExecutor() {
return new HttpRequestExecutor(){
#Override
protected HttpResponse doSendRequest(HttpRequest request,
HttpClientConnection conn, HttpContext http_context)
throws IOException, HttpException {
EventsBroadcaster.broadcastConnectionUploading(context);
return super.doSendRequest(request, conn, http_context);
}
#Override
protected HttpResponse doReceiveResponse(
HttpRequest request, HttpClientConnection conn,
HttpContext http_context) throws HttpException,
IOException {
EventsBroadcaster.broadcastConnectionDownloading(context);
return super.doReceiveResponse(request, conn, http_context);
}
};
}
};
How can I do the same with HttpURLConnection?
`OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
RequestBody body = RequestBody.create(mediaType, "Your Body");
Request request = new Request.Builder()
.url("Your url")
.post(body)
.addHeader("add as many add headers as u want")
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(#NotNull Call call, #NotNull IOException e) {
//What should happen if failed
}
#Override
public void onResponse(#NotNull Call call, #NotNull Response response) throws IOException {
//what should happen if it is successful
}
}); `

How to send cookies with AsyncTask?

I have a web server, where i log in in my android Application, after that loging i recive as an XML the user who logged with a field named token.
This token is used to keep open the session during next calls to webService, and it works sendidnt the token as a cookie named "acrsession" but it seems not working because everytime i tried to check if im logged in (using a get call named currentUser) it returns me forbidden, so i think it isnt working good.
Here is my AsyncTask class who do the calls to server.
public String getFileName() {
return FileName;
}
public void setFileName(String fileName) {
FileName = fileName;
}
private String Response;
private URI uriInfo;
private String FileName;
public WebServiceTask(int taskType, Context mContext, String processMessage,String token) {
this.taskType = taskType;
this.mContext = mContext;
this.processMessage = processMessage;
this.token=token;
}
public void addNameValuePair(String name, String value) {
params.add(new BasicNameValuePair(name, value));
}
public void showProgressDialog() {
pDlg = new ProgressDialog(mContext);
pDlg.setMessage(processMessage);
pDlg.setProgressDrawable(mContext.getWallpaper());
pDlg.setProgressStyle(ProgressDialog.STYLE_SPINNER);
pDlg.setCancelable(false);
pDlg.show();
}
#Override
protected void onPreExecute() {
//hideKeyboard();
showProgressDialog();
}
protected String doInBackground(String... urls) {
String url = urls[0];
String result = "";
HttpResponse response = doResponse(url);
if (response == null) {
return result;
} else {
try {
result = inputStreamToString(response.getEntity().getContent());
} catch (IllegalStateException e) {
Log.e(TAG, e.getLocalizedMessage(), e);
} catch (IOException e) {
Log.e(TAG, e.getLocalizedMessage(), e);
}
}
return result;
}
#Override
protected void onPostExecute(String response) {
this.Response=response;
pDlg.dismiss();
}
// Establish connection and socket (data retrieval) timeouts
private HttpParams getHttpParams() {
HttpParams htpp = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(htpp, CONN_TIMEOUT);
HttpConnectionParams.setSoTimeout(htpp, SOCKET_TIMEOUT);
return htpp;
}
private HttpResponse doResponse(String url) {
// Use our connection and data timeouts as parameters for our
// DefaultHttpClient
HttpClient httpclient = new DefaultHttpClient(getHttpParams());
int responseCode=0;
// Create a local instance of cookie store
//CookieStore cookieStore = new BasicCookieStore();
// Create local HTTP context
//HttpContext localContext = new BasicHttpContext();
// Bind custom cookie store to the local context
//localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
//CookieManager cookieManager= CookieManager.getInstance();
this.getLocalContext();
this.cookieStore.addCookie(new BasicClientCookie("acrsession", this.token));
HttpResponse response = null;
try {
switch (taskType) {
case POST_TASK:
HttpPost httppost = new HttpPost(url);
// Add parameters
httppost.setEntity(new UrlEncodedFormEntity(params));
int executeCount = 0;
do
{
pDlg.setMessage("Logging in.. ("+(executeCount+1)+"/5)");
// Execute HTTP Post Request
executeCount++;
response = httpclient.execute(httppost,localContext);
responseCode = response.getStatusLine().getStatusCode();
// If you want to see the response code, you can Log it
// out here by calling:
// Log.d("256 Design", "statusCode: " + responseCode)
} while (executeCount < 5 && responseCode == 408);
uriInfo = httppost.getURI();
break;
case GET_TASK:
HttpGet httpget = new HttpGet(url);
response = httpclient.execute(httpget,localContext);
responseCode = response.getStatusLine().getStatusCode();
httpget.getRequestLine();
uriInfo = httpget.getURI();
break;
case PUT_TASK:
HttpPut httpput = new HttpPut(url);
File file = new File(this.FileName);
InputStreamEntity reqEntity = new InputStreamEntity(new FileInputStream(file), -1);
reqEntity.setContentType("binary/octet-stream");
reqEntity.setChunked(true); // Send in multiple parts if needed
httpput.setEntity(reqEntity);
response = httpclient.execute(httpput,localContext);
responseCode = response.getStatusLine().getStatusCode();
httpput.getRequestLine();
uriInfo = httpput.getURI();
break;
}
} catch (Exception e) {
Log.e(TAG, e.getLocalizedMessage(), e);
}
return response;
}
private String inputStreamToString(InputStream is) {
String line = "";
StringBuilder total = new StringBuilder();
// Wrap a BufferedReader around the InputStream
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
try {
// Read response until the end
while ((line = rd.readLine()) != null) {
total.append(line);
}
} catch (IOException e) {
Log.e(TAG, e.getLocalizedMessage(), e);
}
// Return full string
this.Response=total.toString();
return total.toString();
}
public String getResponse(){
return this.Response;
}
public HttpContext getLocalContext()
{
if (localContext == null)
{
localContext = new BasicHttpContext();
cookieStore = new BasicCookieStore();
localContext.setAttribute(ClientContext.COOKIE_ORIGIN, cookieStore);
localContext.setAttribute(ClientContext.COOKIE_SPEC, cookieStore);
localContext.setAttribute(ClientContext.COOKIESPEC_REGISTRY, cookieStore);
localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);// to make sure that cookies provided by the server can be reused
}
return localContext;
}
Plesae tell me what im doing bad.
Thanks in advance.
Well, finally i found the solution, everything was ok but i fortgot to set cookie Domain and path, so onced i putted it it worked.
Now cookie creation looks like this:
this.localContext=this.getLocalContext();
BasicClientCookie cookie = new BasicClientCookie("acrsession", this.token);
cookie.setDomain(this.Domain);
cookie.setPath(this.path);
this.cookieStore.addCookie(cookie);
localContext.setAttribute(ClientContext.COOKIE_STORE, this.cookieStore);
Hope it will help someone else.

Which is the best way to implement timeout for HTTP request in Android?

That my sample!
private void onGet( String command, int requestType ){
HttpGet getRequest = new HttpGet("http://" + getHost() + ":" + getPort() + getServerCgiPath() + command);
Client.sendRequest(getRequest, requestType, getCallBack() );
}
... Right there i have created my HttpClient
public class Client {
public static void sendRequest(final HttpUriRequest request,
int RequestType,
ResponseListener callback ) {
(new AsynchronousSender(new DefaultHttpClient(), request, RequestType,
new Handler(), new CallbackWrapper(callback))).start();
}
}
...
public class AsynchronousSender extends Thread {
private DefaultHttpClient httpClient;
private HttpUriRequest request;
private Handler handler;
private CallbackWrapper wrapper;
private int requestType;
protected AsynchronousSender( DefaultHttpClient httpClient, HttpUriRequest request,
int requestType, Handler handler, CallbackWrapper wrapper ) {
setRequest (request);
setHandler (handler);
setWrapper (wrapper);
setClient (httpClient);
setRequestType (requestType);
}
public void run() {
try {
final HttpResponse response;
final HttpParams httpParams = getClient().getParams();
HttpConnectionParams.setConnectionTimeout ( httpParams, 5000 );
HttpConnectionParams.setSoTimeout ( httpParams, 5000 );
Log.d("Ehome", "before execute reauest");
response = getClient().execute( getRequest() );
Log.d("Ehome", "post execute reauest");
int status = response.getStatusLine().getStatusCode();
switch( status ){
case HttpStatus.SC_OK:
getWrapper().setResponse(response);
getWrapper().setRequestType(getRequestType());
getHandler().post(getWrapper());
break;
default:
break;
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private HttpClient getClient() {
return httpClient;
}
...
HttpConnectionParams is the class to use:
Example code (as uncompleted as yours :-))
HttpClient httpClient = new DefaultHttpClient();
final HttpParams httpParams = httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(httpParams, 5000);
HttpConnectionParams.setSoTimeout(httpParams, 5000);
So you have to do it something like this (without checking your code deeply):
public class Client {
public static void sendRequest(final HttpUriRequest request,
int RequestType,
ResponseListener callback) {
HttpClient httpClient = new DefaultHttpClient();
final HttpParams httpParams = httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(httpParams, 5000);
HttpConnectionParams.setSoTimeout(httpParams, 5000);
(new AsynchronousSender(httpClient, request, RequestType,
new Handler(), new CallbackWrapper(callback))).start();
}

Categories

Resources