Jay
Jay

Reputation: 1119

HttpServletRequest object change and Session drops after redirect

I've been working on implementing Punchout in my eCommerce Application. My implementation works as follows.

enter image description here

Everything was working fine till yesterday, then the session started to getting dropped when the redirection to store front took place.

My Observation:

The HttpServletRequest object is RequestFacade before the redirection takes place, but after I redirect, it becomes ApplicationHttpRequest. I can find the RequestFacade wrapped in ApplicationHttpRequest but I cannot find the object I put in the session. Below is the function I am using to put the object in session.

/**
 * Creates an object of {@link PunchoutSessionDTO} and puts it in
 * the session, making it a punchout session.
 * 
 * @param punchoutTransaction
 *          The {@link PunchoutTransaction} object passed from the 
 *          {@link PunchoutStoreEntryController}.
 * @param session
 *          The {@link HttpSession}.
 */
public void createPunchoutSession(PunchoutTransaction punchoutTransaction, HttpSession session) {

    // Create a PunchoutSessionDTO object.
    PunchoutSessionDTO state = new PunchoutSessionDTO();

    // Initialize it with the variables from the PunchoutTransaction
    // object passed to it.
    state.setBrowserFormPost(punchoutTransaction.getCallbackURL());
    state.setBuyerCookie(punchoutTransaction.getBuyerCookie());
    state.setFromId(punchoutTransaction.getFromId());
    state.setToId(punchoutTransaction.getToId());
    state.setPoTransId(punchoutTransaction.getTransactionId());
    state.setOciPunchout(punchoutTransaction.getTransactionType() == PunchoutTransaction.TYPE_OCI);

    // And put it in the session, so that the session could be
    // identified as a punchout session.
    session.setAttribute("PunchoutState", state);

    // Set the max inactive interval of the session to the value
    // provided in the store property. If such store property is
    // not found, a default of 5 minutes is used.
    /*String vid = punchoutTransaction.getVendorId();
    Integer timeout = PunchoutStorePropertyFactory.getTimeoutPeriod(vid);
    session.setMaxInactiveInterval( (timeout == null ? 5 : timeout) * 60); */

    logger.info("Punchout Session Created for " + punchoutTransaction.getBuyerCookie());
}

Everything was working fine till I decided that I should set a timeout value for the session. After this point, problem started to occur. At first, I thought that I am messing it up by passing the incorrect value for setMaxInactiveInterval(), so I commented it. To my surprise, the session was getting dropped anyway.

Please Note:

Server version: Apache Tomcat/7.0.54
Server built:   May 19 2014 10:26:15
Server number:  7.0.54.0
OS Name:        Windows 8
OS Version:     6.2
Architecture:   amd64
JVM Version:    1.7.0_51-b13
JVM Vendor:     Oracle Corporation

Google Searches:

  1. Why does HttpServletRequest object changes.

  2. HttpServletRequest changes to ApplicationHttpRequest

  3. HttpServletRequest to ApplicationHttpRequest

  4. Spring ServletRequest object changing

  5. HttpServletRequest changes after redirection

This silly mistake is pissing us off since last 3 days. Any help would be appreciated! Please point out any silly mistake I have made, and some good tips related to session handling/management are the most welcome ones. If you think that I have not included enough information, please point it out as well. Thanks :)

Upvotes: 1

Views: 3125

Answers (2)

Nilesh
Nilesh

Reputation: 177

This is how it works, It first checks whether relative redirect available or not then it else construct absolute path.

  // Generate a temporary redirect to the specified location
    try {
        String locationUri;
        // Relative redirects require HTTP/1.1
        if (getRequest().getCoyoteRequest().getSupportsRelativeRedirects() &&
                getContext().getUseRelativeRedirects()) {
            locationUri = location;
        } else {
            locationUri = toAbsolute(location);
        }
        setStatus(status);
        setHeader("Location", locationUri);
        if (getContext().getSendRedirectBody()) {
            PrintWriter writer = getWriter();
            writer.print(sm.getString("coyoteResponse.sendRedirect.note",
                    Escape.htmlElementContent(locationUri)));
            flushBuffer();
        }
    } catch (IllegalArgumentException e) {
        log.warn(sm.getString("response.sendRedirectFail", location), e);
        setStatus(SC_NOT_FOUND);
    }

Upvotes: 1

Jay
Jay

Reputation: 1119

Yes, I am answering my own question. I wish to go in details so that future comers may find their answers.

Turns out I am an idiot who is redirecting to absolute path.

Redirection is the key.

No matter whether the servlet you are redirecting to resides on the same application server, is within the same application or it even shares the same servlet. Any request redirected to absolute paths has their own context! So the request object created for them are completely new and has their separate sessions. A session is only maintained if the redirection is being sent on the same port, host and webapp. If redirection is done within the same application, use relative paths using relative paths is the best practice.

Redirecting from https://localhost/servlet1.html to http://localhost/servlet2.html are very different, even though the URLs map to the same servlet (Please notice the difference).

Redirecting from https://localhost/servlet1.html to https://192.168.x.x/servlet2.html or https://127.0.0.1/servlet2.html would bear the same results.

The best practice here would be redirecting to paths relative to your application. This would share the session object in the most efficient way. Using response.sendRedirect("servlet2.html"); is best thing do here (in my opinion).

Understanding the Cookies

A session is identified by the JSESSIONID cookie. If the browser forwards this cookie, then the session is forwarded to the other servlet or controller (or whatever). HTTP and HTTPs are different protocols and hence, different cookies are used. Similarly, localhost and IP addresses are different hosts for a browser, hence different cookies are used. The JSESSIONID cookie is forwarded if the protocol, host and webapp context remains the same, which however, has the same meaning as using relative paths in the redirection. Redirecting to the relative addresses could be thought of as a safe way to redirect on the same host, protocol and application context. It is the browser that decides if it is going to forward your JSESSIONID cookie or not

Upvotes: 3

Related Questions