PacificNW_Lover
PacificNW_Lover

Reputation: 5374

Trying setting session cookie using HttpClient

Help setting cookie to HttpClient

Created a program which logins to an external web service. However, to obtain vital information from an HTTP GET, I am unable to pass in the cookie (generated from the login).

public class ClientHelper {
    private final static String PROFILE_URL = 
                               "http://externalservice/api/profile.json";
    private final static String LOGIN_URL = "http://externalservice/api/login";

    public static Cookie login(final String username, final String password) {
        DefaultHttpClient client = new DefaultHttpClient();
        HttpPost post = new HttpPost(LOGIN_URL);
        HttpContext localContext = new BasicHttpContext();
        client.getParams().setParameter("http.useragent", "Custom Browser");
        client.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, 
                                        HttpVersion.HTTP_1_1);
        List<Cookie> cookies = null;
        BasicClientCookie cookie = null;

        try {
            List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
            nameValuePairs.add(new BasicNameValuePair("user", username));
            nameValuePairs.add(new BasicNameValuePair("passwd", password));
            UrlEncodedFormEntity entity = 
                    new UrlEncodedFormEntity(nameValuePairs, HTTP.UTF_8);
            entity.setContentType("application/x-www-form-urlencoded");

            post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
            HttpResponse response = client.execute(post, localContext);
            cookies = client.getCookieStore().getCookies();
            System.out.println(cookies.get(1));

            cookie = new BasicClientCookie(cookies.get(1).getName(), cookies.get(1).getValue());
            cookie.setVersion(cookies.get(1).getVersion());
            cookie.setDomain(cookies.get(1).getDomain());
            cookie.setExpiryDate(cookies.get(1).getExpiryDate());
            cookie.setPath(cookies.get(1).getPath());               
            BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));

            String line = "";
            while ((line = rd.readLine()) != null) {
                System.out.println(line);
            }
        } 
        catch (Throwable e) {
            e.printStackTrace();
        }
        return cookie;
   }

   public static void getProfile(Cookie cookie) {
      DefaultHttpClient client = new DefaultHttpClient();
      HttpContext context = new BasicHttpContext();
      CookieStore cookieStore = new BasicCookieStore();
      cookieStore.addCookie(cookie);
      client.setCookieStore(cookieStore);
      context.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
      HttpGet get = new HttpGet(PROFILE_URL);
      HttpResponse response;

      try {
          response = client.execute(get, context);
          BufferedReader rd = 
             new BufferedReader(
                    new InputStreamReader(response.getEntity().getContent()));

          String line = "";
          while ((line = rd.readLine()) != null) {
              System.out.println(line);
          }
       } 
       catch (ClientProtocolException e) {
           e.printStackTrace();
       } 
       catch (IOException e) {
           e.printStackTrace();
       }
   }
}

App.java (class that uses ClientHelper):

public class App {
   private static final String USER = "myusername";
   private static final String PASSWD = "mypassword";

   public static void main(String[] args) {
       Cookie cookie = ClientHelper.login(USER, PASSWD);
       ClientHelper.getProfile(cookie);
   }
}

When I run App, I am able to login (I see the generated JSON) but the getProfile() method returns an empty JSON object:

 {}

From the command line, using curl I am trying to emulate this:

curl -b Cookie.txt http://externalservice/api/profile.json

This actually works but not my Java program.

Upvotes: 1

Views: 4983

Answers (3)

PacificNW_Lover
PacificNW_Lover

Reputation: 5374

I figured it out... I was creating two different HTTP clients instead of using the same one.

@Brian Roach & Raunak Agarwal thank you both very much for the help!

Here's the fix:

public static HttpClient login(final String username, final String password) 
{
    HttpClient client = new DefaultHttpClient();
    HttpPost post = new HttpPost(LOGIN_URL);
    client.getParams().setParameter("http.useragent", "Custom Browser");
    client.getParams().setParameter(
             CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);

    try 
    {
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
        nameValuePairs.add(new BasicNameValuePair("user", username));
        nameValuePairs.add(new BasicNameValuePair("passwd", password));
        UrlEncodedFormEntity entity = 
              new UrlEncodedFormEntity(nameValuePairs, HTTP.UTF_8);
        entity.setContentType("application/x-www-form-urlencoded");

        post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
        HttpResponse response = client.execute(post);

        BufferedReader reader = 
              new BufferedReader(
              new InputStreamReader(response.getEntity().getContent()));

        String line = "";
        while ((line = reader.readLine()) != null) 
        {
            System.out.println(line);
        }
    } 
    catch (Throwable e) { e.printStackTrace(); }
    return client;
}

public static void getProfile(HttpClient client) 
{
    HttpGet get = new HttpGet(PROFILE_URL);
    HttpResponse response;
    try 
    {
        response = client.execute(get);
        BufferedReader reader = 
               new BufferedReader(
               new InputStreamReader(response.getEntity().getContent()));

        String line = "";
        while ((line = reader.readLine()) != null) 
        {
            System.out.println(line);
        }
    } 
    catch (ClientProtocolException e) { e.printStackTrace(); } 
    catch (IOException e) { e.printStackTrace(); }  
}

Upvotes: 1

Brian Roach
Brian Roach

Reputation: 76898

After changing your code to get the cookies after the login request, you actually are getting all the cookies from the request.

I suspect the problem is that whatever Cookie it is at index 1 in the CookieStore isn't the one you need, and obviously since it's not throwing an IndexOutOfBounds exception when you do that, there's at least one other Cookie in there (at index 0). Return the list of cookies and send all of them with your profile request.

Taking your code, changing all those indexes from 1 to 0 and pointing at this simple PHP script shows that it is receiving then sending the cookies:

<?php
    setcookie("TestCookie", "Some value");
    print_r($_COOKIE);        
?>

output:

[version: 0][name: TestCookie][value: Some+value][domain: www.mydomain.org][path: /][expiry: null]
Array
(
)
Array
(
    [TestCookie] => Some value
)

Upvotes: 1

Raunak Agarwal
Raunak Agarwal

Reputation: 7228

Try by executing this part of the code:

List<Cookie> cookies = client.getCookieStore().getCookies();
        for (Cookie cookie : cookies) {
             singleCookie = cookie;
        }

After

 HttpResponse response = client.execute(post, localContext);

Upvotes: 1

Related Questions