jcricket / gwt-syncproxy

Provides Synchronous and Asynchronous access to GWT-RPC servlets from Java and Android
http://www.blueesoteric.com/open-source/gwt-syncproxy
Apache License 2.0
23 stars 14 forks source link

SyncProxy.setBaseURL() need Cookies to retreive file from the server #49

Open sebastienALU opened 9 years ago

sebastienALU commented 9 years ago

Hi,

Let me explain the context.

I have a webApp using GWT-RPC to exchange some data. The user must first performs a user/password authentication before to start using the webApp. The authentication mechanism generates some Cookies that must be used in all HTTP requests with the server, when the cookies are not provided the HTTP requests are redirected to start again the authentication.

My objective is to perform some load testing of the webApp with Jmeter. To make it possible I'm implementing a Jmeter PlugIn (in Java) and to send the GWT-RPC requests I'm using gwt-syncproxy library.

My plugIn works except when the authentication mechanism is enabled on the server. Based on my investigation the issue comes from the SyncProxy.setBaseURL() because it calls the method RpcPolicyFinder.getResposeText() which gets some files from the server but without setting in the HttpURLConnection my Cookies (I can extract the Cookies from Jmeter).

To fix this issue I have done the change below in the method RpcPolicyFinder.getResposeText().

Do you think this change could be integrated? Or maybe the CookieManager should be an optional parameter of the SyncProxy.setBaseURL() (like in SyncProxy.CreateProxy()). I'm setting also the same CookieManager in the ProxySettings when calling the method SyncProxy.createProxy(WQService.class, settings); and it works.

I'm not an expert of SyncProxy & GWT, maybe there's another way to get the same result?

private static String getResposeText(String myurl) throws IOException {
    URL url = new URL(myurl);
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    connection.setDoInput(true);
    connection.setDoOutput(true);
    connection.setInstanceFollowRedirects(true); // follow redirect
    connection.setRequestMethod("GET");

    // =========== Here's the change
    setCookiesFromDefaultCookieManager(connection);

    connection.connect();

    InputStream is = connection.getInputStream();
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    int len;
    while ((len = is.read(buffer)) > 0) {
        baos.write(buffer, 0, len);
    }
    String responseText = baos.toString("UTF8");

    if (myurl.endsWith(GWT_PRC_POLICY_FILE_EXT)) {
        CACHE_POLICY_FILE.put(myurl, responseText);
    }

    return responseText;
}

/***************************** Methods added ***************************************************/
public static void setCookiesFromDefaultCookieManager(HttpURLConnection connection) {
    connection.setRequestProperty("Cookie", getCookiesFromDefaultCookieManager());
}

public static String getCookiesFromDefaultCookieManager() {
    CookieManager msCookieManager = (CookieManager)CookieHandler.getDefault();
    if (msCookieManager == null) {
        return null;
    }
    if(msCookieManager.getCookieStore().getCookies().size() > 0) {
        return StringUtils.join(msCookieManager.getCookieStore().getCookies(), ";");
    } else {
        return "";
    }
}

Sebastien.

jcricket commented 9 years ago

In principal, this change does not seem problematic to me. Can you verify that this code is functional for your scenario or has it not been tested yet?

I have a preference for your suggested option of passing in the CookieManager as an optional parameter to the #setBaseUrl method, so I will likely implement your code using that concept unless your foresee a complication in that usage. Additionally, your request falls in line with issue #46 and the solution proposed there and submitted in pull #47, which is also pending integration.

sebastienALU commented 9 years ago

The code I have provided is working for my need. In my own code to use the suggested modification I'm doing the following:

    CookieManager cookieMgr = getInitializedCookieManager(context, PROTOCOL + getServerIPAddress(context));                     
    CookieHandler.setDefault(cookieMgr);

    SyncProxy.setLoggingLevel(Level.ALL);
    SyncProxy.setBaseURL(PROTOCOL + getServerIPAddress(context) + ":" + getServerPort(context) + BASE_URL);

The method getInitializedCookieManager() just create the CookieManager and put in the cookieStore my cookies.

This change use the default CookieManager but probably it's better to pass the CookieManager as an optional parameter...?