hi,
Guys i noticed that the proxy server blocks when you try to handle a 
post. I have traced the problem and manged to fix it ( source files are 
attached)

Basicaly it boiled down to the post data not being collected, and posted 
to the destination server correctly.

what i have basicaly done is to get the output stream from 
HttpURLConnection in Proxy.java and write to it. The data has to be 
collected at the request.parse method. Some how it does not seem to work 
in the run method in Proxy.java So i have had to add

     public String postData = new String();

to HttpRequestHdr.java

hope i haven't broken something else in the process.

Appreciate the good work that you guys are doing.


Raditha Dissanayake.

package org.apache.jmeter.protocol.http.proxy;
/******************************************************************
*** File HttpRequestHdr.java
***
***/

import java.io.InputStream;
import java.io.DataInputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

//
// Class:     HttpRequestHdr
// Abstract:  The headers of the client HTTP request.
//

public class HttpRequestHdr
{

    /**
     * Http Request method. Such as get or post.
     */
    public  String method = new String();

    /**
     * The requested url. The universal resource locator that
     * hopefully uniquely describes the object or service the
     * client is requesting.
     */
    public String url   = new String();

    /**
     * Version of http being used. Such as HTTP/1.0
     */
    public String version           = new String();

    /**
     * The client's browser's name.
     */
    public String userAgent         = new String();

    /**
     * The requesting documents that contained the url link.
     */
    public String referer           = new String();

    /**
     * A internet address date of the remote copy.
     */
    public String ifModifiedSince   = new String();

    /**
     * A list of mime types the client can accept.
     */
    public String accept            = new String();

    /**
     * The clients authorization. Don't belive it.
     */

    public String authorization     = new String();
    /**
     * The type of content following the request header.
     * Normally there is no content and this is blank, however
     * the post method usually does have a content and a content
     * length.
     */
    public String contentType       = new String();
    /**
     * The length of the content following the header. Usually
     * blank.
     */
    public int    contentLength     = -1;

    /**
     * The content length of a remote copy of the requested object.
     */
    public int    oldContentLength  = -1;
    /**
     * Anything in the header that was unrecognized by this class.
     */
    public String unrecognized      = new String();
    /**
     * Indicates that no cached versions of the requested object are
     * to be sent. Usually used to tell proxy not to send a cached copy.
     * This may also effect servers that are front end for data bases.
     */
    public boolean pragmaNoCache    = false;

    public String postData = new String();

    static String CR ="\r\n";


/**
 * Parses a http header from a stream.
 *
 * @param in  The stream to parse.
 * @return    true if parsing sucsessfull.
 */
public boolean parse(InputStream In)
    {
         String CR ="\r\n";

         /*
          * Read by lines
          */
         BufferedReader lines;
         StringTokenizer tz;
         try
        {
              lines = new BufferedReader(new InputStreamReader(new 
DataInputStream(In)));
              tz = new StringTokenizer(lines.readLine());
         }
        catch (Exception e)
        {
              return false;
         }

         /*
          * HTTP COMMAND LINE < <METHOD==get> <URL> <HTTP_VERSION> >
          */
         method = getToken(tz).toUpperCase();
         url    = getToken(tz);
         version= getToken(tz);

        while (true)
        {
            try
            {
                    tz = new StringTokenizer(lines.readLine());
            }
            catch (Exception e)
            {
                    return false;
            }
              String Token = getToken(tz);

              // look for termination of HTTP command
              if (0 == Token.length())
              {
                        if(method.equals("POST"))
                        {
                                try
                                {
                                        postData  = lines.readLine();
                                }
                                catch (Exception e)
                                {
                                        System.out.println("fucked up trying to read 
post data");
                                        break;
                                }
                        }
                        break;
              }

              if (Token.equalsIgnoreCase("USER-AGENT:")) {
                    // line =<User-Agent: <Agent Description>>
                    userAgent = getRemainder(tz);
              } else if (Token.equalsIgnoreCase("ACCEPT:")) {
                    // line=<Accept: <Type>/<Form>
                    // examp: Accept image/jpeg
                    accept += " " + getRemainder(tz);

              } else if (Token.equalsIgnoreCase("REFERER:")) {
                    // line =<Referer: <URL>>
                    referer = getRemainder(tz);

              } else if (Token.equalsIgnoreCase("PRAGMA:")) {
                    // Pragma: <no-cache>
                    Token = getToken(tz);

                    if (Token.equalsIgnoreCase("NO-CACHE"))
                         pragmaNoCache = true;
                    else
                         unrecognized += "Pragma:" + Token + " "
                              +getRemainder(tz) +"\n";
              } else if (Token.equalsIgnoreCase("AUTHORIZATION:")) {
                    // Authenticate: Basic UUENCODED
                    authorization=  getRemainder(tz);

              } else if (Token.equalsIgnoreCase("IF-MODIFIED-SINCE:")) {
                    // line =<If-Modified-Since: <http date>
                    // *** Conditional GET replaces HEAD method ***
                    String str = getRemainder(tz);
                  int index = str.indexOf(";");
                  if (index == -1) {
                         ifModifiedSince  =str;
                    } else {
                         ifModifiedSince  =str.substring(0,index);

                        index = str.indexOf("=");
                        if (index != -1) {
                             str = str.substring(index+1);
                             oldContentLength =Integer.parseInt(str);
                        }
                  }
              } else if (Token.equalsIgnoreCase("CONTENT-LENGTH:")) {
                    Token = getToken(tz);
                    contentLength =Integer.parseInt(Token);

              } else if (Token.equalsIgnoreCase("CONTENT-TYPE:")) {
                    contentType = getRemainder(tz);
              } else {
                    unrecognized += Token + " " + getRemainder(tz) + CR;
              }
         }
         return true;
    }

    /*
     * Rebuilds the header in a string
     * @returns      The header in a string.
     */
    public String toString(boolean sendUnknowen) {
         String Request;

         if (0 == method.length())
                method = "GET";

         Request = method +" "+ url + " HTTP/1.0" + CR;

         if (0 < userAgent.length())
              Request +="User-Agent:" + userAgent + CR;

         if (0 < referer.length())
              Request+= "Referer:"+ referer  + CR;

         if (pragmaNoCache)
              Request+= "Pragma: no-cache" + CR;

         if (0 < ifModifiedSince.length())
              Request+= "If-Modified-Since: " + ifModifiedSince + CR;

         // ACCEPT TYPES //
         if (0 < accept.length())
              Request += "Accept: " + accept + CR;
         else
              Request += "Accept: */"+"* \r\n";

         if (0 < contentType.length())
              Request += "Content-Type: " + contentType   + CR;

         if (0 < contentLength)
              Request += "Content-Length: " + contentLength + CR;


         if (0 != authorization.length())
              Request += "Authorization: " + authorization + CR;

         if (sendUnknowen) {
              if (0 != unrecognized.length())
                    Request += unrecognized;
         }

         Request += CR;

         return Request;
    }


    /**
     * (Re)builds the header in a string.
     *
     * @returns      The header in a string.
     */
    public String toString() {
         return toString(true);
    }

    /**
     *  Returns the next token in a string
     *
     * @param   tk String that is partially tokenized.
     * @returns The remainder
     */
    String  getToken(StringTokenizer tk){
         String str ="";
         if  (tk.hasMoreTokens())
              str =tk.nextToken();
         return str;
    }

    /**
     *  Returns the remainder of a tokenized string
     *
     * @param   tk String that is partially tokenized.
     * @returns The remainder
     */
    String  getRemainder(StringTokenizer tk){
         String str ="";
         if  (tk.hasMoreTokens())
              str =tk.nextToken();
         while (tk.hasMoreTokens()){
              str +=" " + tk.nextToken();
         }
         return str;
    }

        //
    // Parsing Methods
    //

     /**
      * Find the //server.name from an url.
      *
      * @return Servers internet name
      */
     public String serverName()
    {
          // chop to "server.name:x/thing"
          String str = url;
          int i = str.indexOf("//");
          if (i< 0) return "";
          str = str.substring(i+2);

          // chop to  server.name:xx
          i = str.indexOf("/");
          if (0 < i) str = str.substring(0,i);

          // chop to server.name
          i = str.indexOf(":");
          if (0 < i) str = str.substring(0,i);

          return str;
     }

     /**
      * Find the :PORT form http://server.ect:PORT/some/file.xxx
      *
      * @return Servers internet name
      */
     public int serverPort()
    {
          String str = url;
          // chop to "server.name:x/thing"
          int i = str.indexOf("//");
          if (i< 0) return 80;
          str = str.substring(i+2);

          // chop to  server.name:xx
          i = str.indexOf("/");
          if (0 < i) str = str.substring(0,i);

          // chop XX
          i = str.indexOf(":");
          if (0 < i)
        {
                return Integer.parseInt(str.substring(i+1).trim());
          }

          return 80;
     }

     /**
      * Find the /some/file.xxxx form http://server.ect:PORT/some/file.xxx
      *
      * @return the deproxied url
      */
     public String serverUrl()
    {
          String str = url;
          int i = str.indexOf("//");
          if (i< 0) return str;

          str = str.substring(i+2);
          i = str.indexOf("/");
          if (i< 0) return str;

          return str.substring(i);
     }

}
/*
 * ====================================================================
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in
 * the documentation and/or other materials provided with the
 * distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 * if any, must include the following acknowledgment:
 * "This product includes software developed by the
 * Apache Software Foundation (http://www.apache.org/)."
 * Alternately, this acknowledgment may appear in the software itself,
 * if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Apache" and "Apache Software Foundation" and
 * "Apache JMeter" must not be used to endorse or promote products
 * derived from this software without prior written permission. For
 * written permission, please contact [EMAIL PROTECTED]
 *
 * 5. Products derived from this software may not be called "Apache",
 * "Apache JMeter", nor may "Apache" appear in their name, without
 * prior written permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

package org.apache.jmeter.protocol.http.proxy;

import java.net.*;
import java.io.*;
import java.util.*;
import org.apache.jmeter.protocol.http.config.UrlConfig;
import org.apache.jmeter.save.xml.TagHandler;

//
// Class:     Proxy
// Abstract:  Thread to handle one client request. get the requested
//            object from the web server or from the cache, and delivers
//            the bits to client.
//
/**
 *  Description of the Class
 *
 *@author     mike
 *@created    June 8, 2001
 */
public class Proxy extends Thread
{
        //
        // Member variables
        //
        Socket ClientSocket = null;
        // Socket to client
        Socket SrvrSocket = null;
        // Socket to web server
        Cache cache = null;
        // Static cache manager object
        String localHostName = null;
        // Local machine name
        String localHostIP = null;
        // Local machine IP address
        String adminPath = null;
        // Path of admin applet
        Config config = null;
        // Config object
        UrlConfig urlConfig = null;
        // UrlConfig object for saving test cases
        ProxyControl target;


        //
        // Public member methods
        //

        //
        // Constructor
        //
        Proxy(Socket clientSocket, Cache CacheManager, Config 
configObject,ProxyControl target)
        {
                //
                // Initialize member variables
                //
                this.target = target;
                config = configObject;
                ClientSocket = clientSocket;
                cache = CacheManager;
                localHostName = config.getLocalHost();
                localHostIP = config.getLocalIP();
                adminPath = config.getAdminPath();
        }


        //
        // run - Main work is done here:
        //
        /**
         *  Main processing method for the Proxy object
         */
        public void run()
        {
                String serverName = "";
                URL url;

                byte line[];
                HttpRequestHdr request = new HttpRequestHdr();
                HttpReplyHdr reply = new HttpReplyHdr();
                FileInputStream fileInputStream = null;
                FileOutputStream fileOutputStream = null;
                boolean TakenFromCache = false;
                boolean isCachable = false;
                try
                {
                        //
                        // Read HTTP Request from client
                        //
                        request.parse(ClientSocket.getInputStream());
                        createUrlConfig(request);
                        config.increaseFilesCached();
                        url = new URL(request.url);
                        System.out.println("Request = " + url);

                        //
                        // Send Web page with applet to administrator
                        //
                        if (url.getFile().equalsIgnoreCase("/admin") &&
                                        (url.getHost().equalsIgnoreCase(localHostName) 
||
                                        url.getHost().equalsIgnoreCase(localHostIP)))
                        {
                                sendAppletWebPage();
                                return;
                        }

                        //
                        // Send Applet Files to administrator
                        //
                        if ((url.getHost().equalsIgnoreCase(localHostName) ||
                                        url.getHost().equalsIgnoreCase(localHostIP)))
                        {
                                sendAppletClass(url.getFile());
                                return;
                        }

                        //
                        // Check if accessing the URL is allowed by administrator
                        //
                        String[] denied = config.getDeniedHosts();
                        for (int i = 0; i < denied.length; i++)
                        {
                                if (url.toString().indexOf(denied[i]) != -1)
                                {
                                        System.out.println("Access not allowed...");
                                        DataOutputStream out =
                                                        new 
DataOutputStream(ClientSocket.getOutputStream());
                                        out.writeBytes(reply.formNotAllowed());
                                        out.flush();
                                        ClientSocket.close();
                                        return;
                                }
                        }

                        serverName = url.getHost();
                        System.out.println("Miss! Forwarding to server " +
                                        serverName + "...");
                        config.increaseMisses();

                        HttpURLConnection conn = 
(HttpURLConnection)url.openConnection();


                        /*
                        //
                        // Send data to server (needed for post method)
                        //
                        StringBuffer buff = new StringBuffer();
                        int readValue;
                        for (int i = 0; i < request.contentLength; i++)
                        {
                                readValue = ClientSocket.getInputStream().read();
                                buff.append((char)readValue);
                        }
                        */
                        if(request.method.equals("POST"))
                        {
                                conn.setDoOutput(true);
                                conn.setDoInput(true);
                                conn.setRequestMethod("POST");
                                
conn.setRequestProperty("Content-length",String.valueOf(request.contentLength));
                                conn.connect();
                                //nn.setRequestProperty("Content-length",reques);
                                urlConfig.parseArguments(request.postData);

                                OutputStream postOut = conn.getOutputStream();
                                postOut.write(request.postData.getBytes(), 0, 
request.contentLength);
                                System.out.println("post data: " + request.postData);
                        }
                        else
                        {
                                conn.connect();
                        }

                        target.deliverUrlConfig(urlConfig);

                        OutputStream out = ClientSocket.getOutputStream();

                        byte[] buffer = new byte[4096];
                        BufferedInputStream in = new 
BufferedInputStream(conn.getInputStream());

                        int x = 0;
                        while ((x = in.read(buffer)) != -1)
                        {
                                out.write(buffer, 0, x);
                        }
                        in.close();
                        out.flush();
                }

                catch (UnknownHostException uhe)
                {
                        //
                        // Requested Server could not be located
                        //
                        System.out.println("Server Not Found.");

                        try
                        {
                                // Notify client that server not found
                                DataOutputStream out =
                                                new 
DataOutputStream(ClientSocket.getOutputStream());
                                out.writeBytes(reply.formServerNotFound());
                                out.flush();
                        }
                        catch (Exception uhe2)
                        {
                        }
                }

                catch (Exception e)
                {
                        e.printStackTrace();
                        try
                        {
                                if (TakenFromCache)
                                {
                                        fileInputStream.close();
                                }
                                else if (isCachable)
                                {
                                        fileOutputStream.close();
                                }

                                // Notify client that internal error accured in proxy
                                DataOutputStream out =
                                                new 
DataOutputStream(ClientSocket.getOutputStream());
                                out.writeBytes(reply.formTimeout());
                                out.flush();

                        }
                        catch (Exception uhe2)
                        {
                        }
                }

                finally
                {
                        try
                        {
                                ClientSocket.getOutputStream().flush();
                                ClientSocket.close();
                        }
                        catch (Exception e)
                        {
                        }
                }
        }


        //
        // Private methods
        //

        //
        // Send to administrator web page containing reference to applet
        //
        private void sendAppletWebPage()
        {
                System.out.println("Sending the applet...");
                String page = "";
                try
                {
                        File appletHtmlPage = new File(config.getAdminPath() +
                                        File.separator + "Admin.html");
                        BufferedReader in = new BufferedReader(new 
InputStreamReader(new FileInputStream(appletHtmlPage)));

                        String s = null;

                        while ((s = in.readLine()) != null)
                        {
                                page += s;
                        }

                        page = page.substring(0, page.indexOf("PORT")) +
                                        config.getAdminPort() +
                                        page.substring(page.indexOf("PORT") + 4);

                        in.close();
                        DataOutputStream out = new 
DataOutputStream(ClientSocket.getOutputStream());
                        out.writeBytes(page);
                        out.flush();
                        out.close();
                }
                catch (Exception e)
                {
                        System.out.println("Error: can't open applet html page");
                }

        }


        //
        // Send the applet to administrator
        //
        private void sendAppletClass(String className)
        {
                try
                {
                        byte data[] = new byte[2000];
                        int count;
                        HttpReplyHdr reply = new HttpReplyHdr();
                        File appletFile = new File(adminPath + File.separatorChar + 
className);
                        long length = appletFile.length();

                        FileInputStream in = new FileInputStream(appletFile);
                        DataOutputStream out = new 
DataOutputStream(ClientSocket.getOutputStream());

                        out.writeBytes(reply.formOk("application/octet-stream", 
length));

                        while (-1 < (count = in.read(data)))
                        {
                                out.write(data, 0, count);
                        }
                        out.flush();
                        in.close();
                        out.close();
                }
                catch (Exception e)
                {
                }
        }

        private void createUrlConfig(HttpRequestHdr request)
        {
                System.out.println("Everything = " + request.toString(true));
                urlConfig = UrlConfig.createConfig(request.contentType);
                urlConfig.setDomain(request.serverName());
                urlConfig.setMethod(request.method);
                urlConfig.setPath(request.serverUrl());
                urlConfig.setName(urlConfig.getPath());
                urlConfig.setProtocol(request.url.substring(0, 
request.url.indexOf(":")));
                urlConfig.setPort(request.serverPort());
    }
}

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to