GWT Preventing Set-Cookie HTTP Header from Actually Setting Cookie?
I am a GWT noob but am working with someone else who is more advanced than I, and we cannot figure out why a cookie being returned by the server as a Set-Cookie HTTP header is not actually being set in the browser.
I wrote a server using Tomcat that has an authentication call. I wrote a dummy website all in HTML that uses web forms to send a request to the server with the authentication information and receives a response that contains a Set-Cookie header. This all works. It then has a second button in a different form on the same page that sends a different request to my server with some form data, and the browser automatically injects the cookie into the header as expected. Therefore, the server, for the second call, can pull the cookie header out of the request and authenticate the request. This all works and is great.
Now, for the test GWT application we have developed, I have used the code that is automatically generated when a new GWT application is developed (no AppEngine) and modified it in the following ways on the client side's EntryPoint class. I removed the TextBox for entering my name and the GWT RPC calls. I modified MyHandler so that it no longer implemented KeyPressedListener or whatever and does implement RequestCallback. I edited the contents of the onClick to create a new RequestBuilder that sends a POST with the authentication information. So far, this all works as I can watch the logs on my server and it receives the request, processes it, and places the authentication cookie in the response. Using Firebug, I can see that the response contains the Set-Cookie header with the necessary cookie information. However, the browser never actually saves this information. Unsurprisingly, a subsequent call to the server doesn't include the cookie.
GWT is just compiled into JavaScript when deployed, correct? And JavaScript can't inject itself between the HTTP response and the browser can it? I have checked the Response object that is a parameter to the onResponseReceived() call from the RequestCallback interface, and it doesn't contain any method to get access to the cookie except through the getHeaders() call. I have dumped the results of this call, though, and it doesn't exist there. Anyway, the browser should at least be getting access to the HTTP header before the code and should be grabbing and setting the cookie values before handing the code to GWT. Not only am I new to GWT, I am new to most HTTP client-side development, but am I really that far off track?
Thank you,
John
Edit:
Here is the code I ended up with. I didn't change anything else in the project.
public void onModuleLoad() {
final Button loginButton = new Button("Login");
final Button requestBuilderButton = new Button("Campaign Read");
final Label errorLabel = new Label();
// Add the nameField and sendButton to the RootPanel
// Use RootPanel.get() to get the entire body element
RootPanel.get("sendButtonContainer").add(loginButton);
RootPanel.get("sendButtonContainer").add(requestBuilderButton);
RootPanel.get("errorLabelContainer").add(errorLabel);
// Create the popup dialog box
final DialogBox dialogBox = new DialogBox();
dialogBox.setText("Remote Procedure Call");
dialogBox.setAnimationEnabled(true);
final Button closeButton = new Button("Close");
// We can set the id of a widget by accessing its Element
closeButton.getElement().setId("closeButton");
开发者_运维问答 final Label textToServerLabel = new Label();
final HTML serverResponseLabel = new HTML();
VerticalPanel dialogVPanel = new VerticalPanel();
dialogVPanel.addStyleName("dialogVPanel");
dialogVPanel.add(new HTML("<b>Sending name to the server:</b>"));
dialogVPanel.add(textToServerLabel);
dialogVPanel.add(new HTML("<br><b>Server replies:</b>"));
dialogVPanel.add(serverResponseLabel);
dialogVPanel.setHorizontalAlignment(VerticalPanel.ALIGN_RIGHT);
dialogVPanel.add(closeButton);
dialogBox.setWidget(dialogVPanel);
// Add a handler to close the DialogBox
closeButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
dialogBox.hide();
}
});
// Create a handler for the sendButton and nameField
class LoginHandler implements ClickHandler, RequestCallback {
/**
* Fired when the user clicks on the sendButton.
*/
public void onClick(ClickEvent event) {
dialogBox.show();
serverResponseLabel.setText(Cookies.getCookie("auth_token"));
final String url = "http://localhost:8080/app/user/auth_token";
RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, URL.encode(url));
builder.setHeader("Content-Type", "application/x-www-form-urlencoded");
StringBuilder parameters = new StringBuilder();
parameters.append("user=username&password=password&client=gwt");
try {
builder.sendRequest(URL.encode(parameters.toString()), this);
}
catch(RequestException e) {
serverResponseLabel.setText(e.toString());
}
}
public void onError(Request request, Throwable exception) {
serverResponseLabel.setText("Failure.");
}
public void onResponseReceived(Request request, Response response) {
textToServerLabel.setText(Integer.toString(response.getStatusCode()));
serverResponseLabel.setText(serverResponseLabel.getText() + Cookies.getCookie("auth_token"));
}
};
class CampaignReadHandler implements ClickHandler, RequestCallback {
public void onClick(ClickEvent event) {
dialogBox.show();
final String url = "http://localhost:8080/app/campaign/read";
RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, URL.encode(url));
builder.setHeader("Content-Type", "application/x-www-form-urlencoded");
StringBuilder parameters = new StringBuilder();
parameters.append("output_format=short&client=gwt&campaign_urn_list=urn:andwellness:nih");
try {
builder.sendRequest(URL.encode(parameters.toString()), this);
}
catch(RequestException e) {
serverResponseLabel.setText(e.toString());
}
}
public void onError(Request request, Throwable exception) {
serverResponseLabel.setText("Failure.");
}
public void onResponseReceived(Request request, Response response) {
textToServerLabel.setText(Integer.toString(response.getStatusCode()));
serverResponseLabel.setText(response.getText());
}
};
// Add a handler to send the name to the server
LoginHandler loginHandler = new LoginHandler();
loginButton.addClickHandler(loginHandler);
CampaignReadHandler campaignReadHandler = new CampaignReadHandler();
requestBuilderButton.addClickHandler(campaignReadHandler);
}
This is the expected behavior of browsers: http://www.w3.org/TR/XMLHttpRequest/#the-getallresponseheaders-method (GWT's Response#getHeaders
simply calls getAllResponseHeaders
and parses the string).
If you want to get cookies, you have to use the cookies
object (Cookies
class in GWT); which obviously filters out httponly
cookies.
If you are using RequestBuilder to contact the RPC servlet that may be the problem. Especially if you are using a different host in your request, than what you have in your browser.
Say navigating to http://localhost/app
But your RequestBuilder builds a request for http://machinename/app/servlet.
If you are just using RPC without RequestBuilder you shouldn't have these problems.
As well if you are using RequestBuilder you may have to manually provide the cookies via setting that particular header
In browser client development cookies are handled on a host name basis.
精彩评论