You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Endre Stølsvik <en...@stud.ntnu.no> on 2001/11/12 10:34:25 UTC

[TC4] Sending redirect fails if OutputStream isn't closed ..

I'm using this program called "loadsim" to get a simulation of a bunch of
users using my webapp. This is a java program utilizing the
java.net.HttpConnection to simulate the clients, built using large parts
of a apache loadsimulation system, right?

I just installed the webapp on TC4, and are experiencing some weird
behaviour with the "sendRedirect()" stuff.

If I don't get and close the output stream, the loadsim-clients wont ever
shut down the Connection, and then, after the timeout of 60000 millis, TC4
closes it. It then says 0 bytes received in the loadsim log.

If I on the other hand go in to the server using a normal browser
(Mozilla) during the test, I can browse it happily (The load-clients are
of course still experiencing the same problem)..

Basically, I have to do this to get it working:

        try {
            // Getting encoding
            String encoding = res.getCharacterEncoding();
            // Setting content type
            res.setContentType("text/html; charset=" + encoding);
            // Getting the OutputStream (just to be able to close it)
            OutputStream out = res.getOutputStream();
            // Sending the redirect
            res.sendRedirect(Configuration.getDEFAULT_MAINPAGE());
            // close output stream
            out.close();
        }
        catch (IOException e) {
            throw new ServerException("Got IOException while trying to
redirect user to ["+Configuration.getDEFAULT_MAINPAGE()+"].", e);
        }


Why is that? Why do I have to get the outputstream, and then just close it
to get the sendRedirect away? Why isn't the stream closed on exit of the
doGet/Post method? Or whatever?

-- 
Mvh,
Endre



--
To unsubscribe:   <ma...@jakarta.apache.org>
For additional commands: <ma...@jakarta.apache.org>
Troubles with the list: <ma...@jakarta.apache.org>


Re: [TC4] Sending redirect fails if OutputStream isn't closed ..

Posted by Remy Maucherat <rm...@home.com>.
> On Mon, 12 Nov 2001, Remy Maucherat wrote:
>
> | > I'm using this program called "loadsim" to get a simulation of a bunch
of
> | > users using my webapp. This is a java program utilizing the
> | > java.net.HttpConnection to simulate the clients, built using large
parts
> | > of a apache loadsimulation system, right?
>
> Make that "java.net.HttpURLConnection" (as the client).
>
> | > Why is that? Why do I have to get the outputstream, and then just
close it
> | > to get the sendRedirect away? Why isn't the stream closed on exit of
the
> | > doGet/Post method? Or whatever?
> |
> | The default servlet doesn't use the output stream at all, and appears to
> | behave correctly (verified using a telnet session). This looks like a
> | problem with the HTTP client you're using.
>
> I also mentioned this in the first post (Mozilla behaves properly), but
> why does it then work when I get and close the output stream as described?

I'm not 100% sure. I checked the result of a redirect sent by the default
servlet with a telnet session, and the result was valid.
If you open and close the stream in the servlet, I think you'll end up
sending a zero length document (with an empty response body), while in the
first case, a chunked error report will be sent (which is allowed on a 302
status).

> Here's the code from "loadsim" that does the sampling, just if you don't
> have much other to do today! (It's not that long, actually)..

Remy


--
To unsubscribe:   <ma...@jakarta.apache.org>
For additional commands: <ma...@jakarta.apache.org>
Troubles with the list: <ma...@jakarta.apache.org>


Re: [TC4] Sending redirect fails if OutputStream isn't closed ..

Posted by "Anthony G. Dinio" <di...@100.ph>.
----- Original Message -----
From: "Endre Stølsvik" <En...@Stolsvik.com>
To: "Remy Maucherat" <rm...@home.com>; "Tomcat Users List"
<to...@jakarta.apache.org>
Sent: Tuesday, November 13, 2001 5:01 PM
Subject: Re: [TC4] Sending redirect fails if OutputStream isn't closed ..


> On Mon, 12 Nov 2001, Remy Maucherat wrote:
>
> | > I'm using this program called "loadsim" to get a simulation of a bunch
of
> | > users using my webapp. This is a java program utilizing the
> | > java.net.HttpConnection to simulate the clients, built using large
parts
> | > of a apache loadsimulation system, right?
>
> Make that "java.net.HttpURLConnection" (as the client).
>
> | > Why is that? Why do I have to get the outputstream, and then just
close it
> | > to get the sendRedirect away? Why isn't the stream closed on exit of
the
> | > doGet/Post method? Or whatever?
> |
> | The default servlet doesn't use the output stream at all, and appears to
> | behave correctly (verified using a telnet session). This looks like a
> | problem with the HTTP client you're using.
>
> I also mentioned this in the first post (Mozilla behaves properly), but
> why does it then work when I get and close the output stream as described?
>
> Here's the code from "loadsim" that does the sampling, just if you don't
> have much other to do today! (It's not that long, actually)..
>
> It seems to close both its output to the server, and the input from the
> server..
>   Extra-info: that page which sends the redirects is just a "poster-page";
> this is where the browser does GETs with parameters and POSTs: it just
> takes all the parameters from the browser, and then sends a "blank"
> redirect to the browser. This fools the (most) browsers to not store this
> as a separate history event, and you don't get that reposting stuff on
> "back" and "reload" going.
>
> --------------------------
>
>     /**
>      * Send the link to the webserver using the <code>VirtualUser</code>'s
>      * <code>CookieManager</code>.
>      *
>      * @param  cookieManager  The <code>VirtualUser</code>'s
> <code>CookieManager</code>.
>      * @param  log            The log file to log information/errors to.
>      *
>      * @return The <code>SampleResult</code> object.
>      *
>      * @exception IOException if an error occurs reading from or writing
> to the
>      *            webserver.
>      */
>     public SampleResult sample(CookieManager cookieManager, ILog log)
> throws IOException {
>         long then;
>         URL url = null;
>         HttpURLConnection connection = null;
>         BufferedInputStream input = null;
>         SampleResult sample = null;
>         byte [] buf = null;
>         int bytesread = 0;
>         ByteArrayOutputStream outbuf = null;
>
>         // Init the sample result
>
>         sample = new SampleResult();
>         sample.setLabel(id_);
>
>         // Create the HTTP connection
>         then = System.currentTimeMillis();
>
>         url = new URL(linkStr_);
>         connection = (HttpURLConnection) url.openConnection();
>         connection.setUseCaches(false);
>         connection.setDoInput(true);
>         connection.setInstanceFollowRedirects(false);   //  ***
> frode@coretrek.no: if followredirects is true we miss out on the cookies
> set by the first page!
>
>         // Setup cookies
>
>         if (cookieManager != null) {
>             String cookieHeader =
> cookieManager.getCookieHeaderForURL(url);
>             if (cookieHeader != null) {
>                 connection.setRequestProperty("Cookie", cookieHeader);
>             }
>         }
>
>         if (formDataStr_ == null) {
>             connection.connect();
>             sample.setTTOpen(System.currentTimeMillis() - then);
>             log.log(ILog.INFORMATION, "' url = " + linkStr_);
>         } else {
>             try {
>                 DataOutputStream output = null;
>
>                 connection.setRequestProperty("Content-Type",
> "application/x-www-form-urlencoded");
>                 connection.setDoOutput(true);
>                 connection.setRequestMethod("POST");
>                 connection.connect();
>                 sample.setTTOpen(System.currentTimeMillis() - then);
>
>                 output = new
> DataOutputStream(connection.getOutputStream());
>                 output.writeBytes(formDataStr_);
>                 output.flush();
>                 output.close();
>                 log.log(ILog.INFORMATION, "' url = " + linkStr_ + " POST =
> " + formDataStr_ + " (" +
>                         formDataStr_.length() + ")");
>             } catch (Exception e) {
>                 log.log(ILog.ERROR, "Caught exception: " + e.getMessage()
> + " ignoring sample");
>                 sample.setTTLB(-1);
>                 sample.setTTFB(-1);
>                 sample.setSize(-1);
>                 sample.setLastPage(null);
>                 return sample;
>             }
>         }
>
>         // this is where 'then = currentTime' used to be.
>         sample.setTTReq(System.currentTimeMillis() - then);
>
>         // Check for cookies coming back
>
>         try {
>             if (cookieManager != null) {
>
>                 // check for Set-Cookie headers from server (index 0 is
> the
>                 // HTTP repsonse code), which does not use "header: value"
> format
>
>                 for (int i = 1;; i++) {
>                     try {
>                         if
> (connection.getHeaderFieldKey(i).equals("Set-Cookie")) {
>
> cookieManager.addCookieFromHeader(connection.getHeaderField(i), url);
>                         }
>                     } catch (NullPointerException e) {
>                         break;
>                     }
>                 }
>             }
>
>             // Read the HTML from the webserver
>
>             input = new BufferedInputStream(connection.getInputStream());
>             buf = new byte[BUFF_SIZE];
>             bytesread = input.read(buf);
>             sample.setTTFB(System.currentTimeMillis() - then);
>             outbuf = new ByteArrayOutputStream();
>             while (bytesread != -1) {
>                 outbuf.write(buf, 0, bytesread);
>                 bytesread = input.read(buf);
>             }
>             input.close();
>             sample.setTTLB(System.currentTimeMillis() - then);
>             sample.setSize(outbuf.size());
>             if (connection.getContentType() != null) {
>                 sample.setContentType(connection.getContentType());
>                 if
> (connection.getContentType().toLowerCase().startsWith("text/html")) {
>                     sample.setLastPage(outbuf.toString());
>                 } else {
>                     sample.setLastPage(null);
>                 }
>             }
>         } catch (Exception e) {
>             log.log(ILog.ERROR, "Caught exception: " + e.getMessage() + "
> ignoring sample");
>             sample.setTTLB(-1);
>             sample.setTTFB(-1);
>             sample.setSize(-1);
>             sample.setLastPage(null);
>             return sample;
>         } finally {
>             if (input != null) {
>                 input.close();
>             }
>         }
>
>         if (sample.getLastPage() != null && expectTitle_ != null) {
>             String receivedTitle = getTitle(buf.toString());
>
>             if (!expectTitle_.trim().equals(receivedTitle.trim())) {
>                 log.log(ILog.ERROR, "' Expected title: '" +
>                         expectTitle_ + "' got '" + receivedTitle + "'");
>             }
>         }
>
>         return sample;
>     }
>
> --------------------------
>
>
> --
> Mvh,
> Endre
>
>
>
> --
> To unsubscribe:   <ma...@jakarta.apache.org>
> For additional commands: <ma...@jakarta.apache.org>
> Troubles with the list: <ma...@jakarta.apache.org>
>
>


--
To unsubscribe:   <ma...@jakarta.apache.org>
For additional commands: <ma...@jakarta.apache.org>
Troubles with the list: <ma...@jakarta.apache.org>


Re: [TC4] Sending redirect fails if OutputStream isn't closed ..

Posted by Endre Stølsvik <En...@Stolsvik.com>.
On Mon, 12 Nov 2001, Remy Maucherat wrote:

| > I'm using this program called "loadsim" to get a simulation of a bunch of
| > users using my webapp. This is a java program utilizing the
| > java.net.HttpConnection to simulate the clients, built using large parts
| > of a apache loadsimulation system, right?

Make that "java.net.HttpURLConnection" (as the client).

| > Why is that? Why do I have to get the outputstream, and then just close it
| > to get the sendRedirect away? Why isn't the stream closed on exit of the
| > doGet/Post method? Or whatever?
|
| The default servlet doesn't use the output stream at all, and appears to
| behave correctly (verified using a telnet session). This looks like a
| problem with the HTTP client you're using.

I also mentioned this in the first post (Mozilla behaves properly), but
why does it then work when I get and close the output stream as described?

Here's the code from "loadsim" that does the sampling, just if you don't
have much other to do today! (It's not that long, actually)..

It seems to close both its output to the server, and the input from the
server..
  Extra-info: that page which sends the redirects is just a "poster-page";
this is where the browser does GETs with parameters and POSTs: it just
takes all the parameters from the browser, and then sends a "blank"
redirect to the browser. This fools the (most) browsers to not store this
as a separate history event, and you don't get that reposting stuff on
"back" and "reload" going.

--------------------------

    /**
     * Send the link to the webserver using the <code>VirtualUser</code>'s
     * <code>CookieManager</code>.
     *
     * @param  cookieManager  The <code>VirtualUser</code>'s
<code>CookieManager</code>.
     * @param  log            The log file to log information/errors to.
     *
     * @return The <code>SampleResult</code> object.
     *
     * @exception IOException if an error occurs reading from or writing
to the
     *            webserver.
     */
    public SampleResult sample(CookieManager cookieManager, ILog log)
throws IOException {
        long then;
        URL url = null;
        HttpURLConnection connection = null;
        BufferedInputStream input = null;
        SampleResult sample = null;
        byte [] buf = null;
        int bytesread = 0;
        ByteArrayOutputStream outbuf = null;

        // Init the sample result

        sample = new SampleResult();
        sample.setLabel(id_);

        // Create the HTTP connection
        then = System.currentTimeMillis();

        url = new URL(linkStr_);
        connection = (HttpURLConnection) url.openConnection();
        connection.setUseCaches(false);
        connection.setDoInput(true);
        connection.setInstanceFollowRedirects(false);   //  ***
frode@coretrek.no: if followredirects is true we miss out on the cookies
set by the first page!

        // Setup cookies

        if (cookieManager != null) {
            String cookieHeader =
cookieManager.getCookieHeaderForURL(url);
            if (cookieHeader != null) {
                connection.setRequestProperty("Cookie", cookieHeader);
            }
        }

        if (formDataStr_ == null) {
            connection.connect();
            sample.setTTOpen(System.currentTimeMillis() - then);
            log.log(ILog.INFORMATION, "' url = " + linkStr_);
        } else {
            try {
                DataOutputStream output = null;

                connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
                connection.setDoOutput(true);
                connection.setRequestMethod("POST");
                connection.connect();
                sample.setTTOpen(System.currentTimeMillis() - then);

                output = new
DataOutputStream(connection.getOutputStream());
                output.writeBytes(formDataStr_);
                output.flush();
                output.close();
                log.log(ILog.INFORMATION, "' url = " + linkStr_ + " POST =
" + formDataStr_ + " (" +
                        formDataStr_.length() + ")");
            } catch (Exception e) {
                log.log(ILog.ERROR, "Caught exception: " + e.getMessage()
+ " ignoring sample");
                sample.setTTLB(-1);
                sample.setTTFB(-1);
                sample.setSize(-1);
                sample.setLastPage(null);
                return sample;
            }
        }

        // this is where 'then = currentTime' used to be.
        sample.setTTReq(System.currentTimeMillis() - then);

        // Check for cookies coming back

        try {
            if (cookieManager != null) {

                // check for Set-Cookie headers from server (index 0 is
the
                // HTTP repsonse code), which does not use "header: value"
format

                for (int i = 1;; i++) {
                    try {
                        if
(connection.getHeaderFieldKey(i).equals("Set-Cookie")) {

cookieManager.addCookieFromHeader(connection.getHeaderField(i), url);
                        }
                    } catch (NullPointerException e) {
                        break;
                    }
                }
            }

            // Read the HTML from the webserver

            input = new BufferedInputStream(connection.getInputStream());
            buf = new byte[BUFF_SIZE];
            bytesread = input.read(buf);
            sample.setTTFB(System.currentTimeMillis() - then);
            outbuf = new ByteArrayOutputStream();
            while (bytesread != -1) {
                outbuf.write(buf, 0, bytesread);
                bytesread = input.read(buf);
            }
            input.close();
            sample.setTTLB(System.currentTimeMillis() - then);
            sample.setSize(outbuf.size());
            if (connection.getContentType() != null) {
                sample.setContentType(connection.getContentType());
                if
(connection.getContentType().toLowerCase().startsWith("text/html")) {
                    sample.setLastPage(outbuf.toString());
                } else {
                    sample.setLastPage(null);
                }
            }
        } catch (Exception e) {
            log.log(ILog.ERROR, "Caught exception: " + e.getMessage() + "
ignoring sample");
            sample.setTTLB(-1);
            sample.setTTFB(-1);
            sample.setSize(-1);
            sample.setLastPage(null);
            return sample;
        } finally {
            if (input != null) {
                input.close();
            }
        }

        if (sample.getLastPage() != null && expectTitle_ != null) {
            String receivedTitle = getTitle(buf.toString());

            if (!expectTitle_.trim().equals(receivedTitle.trim())) {
                log.log(ILog.ERROR, "' Expected title: '" +
                        expectTitle_ + "' got '" + receivedTitle + "'");
            }
        }

        return sample;
    }

--------------------------


-- 
Mvh,
Endre



--
To unsubscribe:   <ma...@jakarta.apache.org>
For additional commands: <ma...@jakarta.apache.org>
Troubles with the list: <ma...@jakarta.apache.org>


Re: [TC4] Sending redirect fails if OutputStream isn't closed ..

Posted by Remy Maucherat <rm...@home.com>.
> I'm using this program called "loadsim" to get a simulation of a bunch of
> users using my webapp. This is a java program utilizing the
> java.net.HttpConnection to simulate the clients, built using large parts
> of a apache loadsimulation system, right?
>
> I just installed the webapp on TC4, and are experiencing some weird
> behaviour with the "sendRedirect()" stuff.
>
> If I don't get and close the output stream, the loadsim-clients wont ever
> shut down the Connection, and then, after the timeout of 60000 millis, TC4
> closes it. It then says 0 bytes received in the loadsim log.
>
> If I on the other hand go in to the server using a normal browser
> (Mozilla) during the test, I can browse it happily (The load-clients are
> of course still experiencing the same problem)..
>
> Basically, I have to do this to get it working:
>
>         try {
>             // Getting encoding
>             String encoding = res.getCharacterEncoding();
>             // Setting content type
>             res.setContentType("text/html; charset=" + encoding);
>             // Getting the OutputStream (just to be able to close it)
>             OutputStream out = res.getOutputStream();
>             // Sending the redirect
>             res.sendRedirect(Configuration.getDEFAULT_MAINPAGE());
>             // close output stream
>             out.close();
>         }
>         catch (IOException e) {
>             throw new ServerException("Got IOException while trying to
> redirect user to ["+Configuration.getDEFAULT_MAINPAGE()+"].", e);
>         }
>
>
> Why is that? Why do I have to get the outputstream, and then just close it
> to get the sendRedirect away? Why isn't the stream closed on exit of the
> doGet/Post method? Or whatever?

The default servlet doesn't use the output stream at all, and appears to
behave correctly (verified using a telnet session). This looks like a
problem with the HTTP client you're using.

Remy


--
To unsubscribe:   <ma...@jakarta.apache.org>
For additional commands: <ma...@jakarta.apache.org>
Troubles with the list: <ma...@jakarta.apache.org>