You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by bi...@apache.org on 2003/12/03 06:37:42 UTC

cvs commit: jakarta-tomcat-connectors/jk/java/org/apache/jk/common HandlerRequest.java

billbarker    2003/12/02 21:37:42

  Modified:    jk/java/org/apache/jk/common HandlerRequest.java
  Log:
  Fix JkCoyote to properly handle the distinction between localName/Port and serverName/Port.
  
  As always with mod_jk, you can lose strict Servlet-Spec compliance by playing with your Apache settings.  However if ConnonicalName=on or DNS, then this is correct.  If it's not, then you obviously don't want this to be correct ;-).  It also seems to be the value that IIS is sending.
  
  Thanks to Remy for his great parseHost routine (which I had to modify slightly, because of design differences in JkCoyote and HTTP11Coyote).
  
  Revision  Changes    Path
  1.29      +144 -60   jakarta-tomcat-connectors/jk/java/org/apache/jk/common/HandlerRequest.java
  
  Index: HandlerRequest.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-connectors/jk/java/org/apache/jk/common/HandlerRequest.java,v
  retrieving revision 1.28
  retrieving revision 1.29
  diff -u -r1.28 -r1.29
  --- HandlerRequest.java	16 Oct 2003 07:37:32 -0000	1.28
  +++ HandlerRequest.java	3 Dec 2003 05:37:42 -0000	1.29
  @@ -62,6 +62,7 @@
   import java.io.File;
   import java.io.FileOutputStream;
   import java.io.IOException;
  +import java.io.CharConversionException;
   import java.net.InetAddress;
   import java.util.Properties;
   
  @@ -75,6 +76,8 @@
   import org.apache.jk.core.MsgContext;
   import org.apache.jk.core.WorkerEnv;
   import org.apache.tomcat.util.buf.ByteChunk;
  +import org.apache.tomcat.util.buf.CharChunk;
  +import org.apache.tomcat.util.buf.HexUtils;
   import org.apache.tomcat.util.buf.MessageBytes;
   import org.apache.tomcat.util.http.MimeHeaders;
   import org.apache.tomcat.util.net.SSLSupport;
  @@ -109,16 +112,16 @@
       
       // Prefix codes for message types from server to container
       public static final byte JK_AJP13_FORWARD_REQUEST   = 2;
  -	public static final byte JK_AJP13_SHUTDOWN          = 7;
  -	public static final byte JK_AJP13_PING_REQUEST      = 8;
  -	public static final byte JK_AJP13_CPING_REQUEST     = 10;
  +        public static final byte JK_AJP13_SHUTDOWN          = 7;
  +        public static final byte JK_AJP13_PING_REQUEST      = 8;
  +        public static final byte JK_AJP13_CPING_REQUEST     = 10;
   
       // Prefix codes for message types from container to server
       public static final byte JK_AJP13_SEND_BODY_CHUNK   = 3;
       public static final byte JK_AJP13_SEND_HEADERS      = 4;
       public static final byte JK_AJP13_END_RESPONSE      = 5;
  -	public static final byte JK_AJP13_GET_BODY_CHUNK    = 6;
  -	public static final byte JK_AJP13_CPONG_REPLY       = 9;
  +        public static final byte JK_AJP13_GET_BODY_CHUNK    = 6;
  +        public static final byte JK_AJP13_CPONG_REPLY       = 9;
       
       // Integer codes for common response header strings
       public static final int SC_RESP_CONTENT_TYPE        = 0xA001;
  @@ -132,7 +135,7 @@
       public static final int SC_RESP_SERVLET_ENGINE      = 0xA009;
       public static final int SC_RESP_STATUS              = 0xA00A;
       public static final int SC_RESP_WWW_AUTHENTICATE    = 0xA00B;
  -	
  +        
       // Integer codes for common (optional) request attribute names
       public static final byte SC_A_CONTEXT       = 1;  // XXX Unused
       public static final byte SC_A_SERVLET_PATH  = 2;  // XXX Unused
  @@ -219,6 +222,11 @@
           "user-agent"
       };
   
  +    /*
  +     * Note for Host parsing.
  +     */
  +    public static final int HOSTBUFFER = 10;
  +
       HandlerDispatch dispatch;
       String ajpidDir="conf";
       
  @@ -239,9 +247,9 @@
                                             "JK_AJP13_SHUTDOWN",
                                             this, null); // 7
               
  -			dispatch.registerMessageType( JK_AJP13_CPING_REQUEST,
  -										  "JK_AJP13_CPING_REQUEST",
  -										  this, null); // 10
  +                        dispatch.registerMessageType( JK_AJP13_CPING_REQUEST,
  +                                                                                  "JK_AJP13_CPING_REQUEST",
  +                                                                                  this, null); // 10
               
               // register outgoing messages handler
               dispatch.registerMessageType( JK_AJP13_SEND_BODY_CHUNK, // 3
  @@ -272,7 +280,7 @@
       }
   
       public void setDecodedUri( boolean b ) {
  -	decoded=b;
  +        decoded=b;
       }
   
       public boolean isTomcatAuthentication() {
  @@ -422,21 +430,21 @@
               log.info("Exiting");
               System.exit(0);
               
  -	    return OK;
  +            return OK;
   
  -		// We got a PING REQUEST, quickly respond with a PONG
  -		case JK_AJP13_CPING_REQUEST:
  -			msg.reset();
  -			msg.appendByte(JK_AJP13_CPONG_REPLY);
  -			ep.setType( JkHandler.HANDLE_SEND_PACKET );
  -			ep.getSource().invoke( msg, ep );
  -			
  -			return OK;
  +                // We got a PING REQUEST, quickly respond with a PONG
  +                case JK_AJP13_CPING_REQUEST:
  +                        msg.reset();
  +                        msg.appendByte(JK_AJP13_CPONG_REPLY);
  +                        ep.setType( JkHandler.HANDLE_SEND_PACKET );
  +                        ep.getSource().invoke( msg, ep );
  +                        
  +                        return OK;
   
           default:
               System.err.println("Unknown message " + type );
               msg.dump("Unknown message" );
  -	}
  +        }
   
           return OK;
       }
  @@ -500,8 +508,8 @@
   
           msg.getBytes(req.remoteAddr());
           msg.getBytes(req.remoteHost());
  -        msg.getBytes(req.serverName());
  -        req.setServerPort(msg.getInt());
  +        msg.getBytes(req.localName());
  +        req.setLocalPort(msg.getInt());
   
           boolean isSSL = msg.getByte() != 0;
           if( isSSL ) {
  @@ -516,17 +524,18 @@
   //         if(req.getSecure() ) {
   //             req.setScheme(req.SCHEME_HTTPS);
   //         }
  -
  +        MessageBytes valueMB = req.getMimeHeaders().getValue("host");
  +        parseHost(valueMB, req);
           // set cookies on request now that we have all headers
           req.getCookies().setHeaders(req.getMimeHeaders());
   
  -	// Check to see if there should be a body packet coming along
  -	// immediately after
  +        // Check to see if there should be a body packet coming along
  +        // immediately after
           int cl=req.getContentLength();
  -    	if(cl > 0) {
  +        if(cl > 0) {
               jkBody.setContentLength( cl );
               jkBody.receive();
  -    	}
  +        }
       
           if (log.isTraceEnabled()) {
               log.trace(req.toString());
  @@ -548,9 +557,9 @@
                */
               if( attributeCode == SC_A_SSL_KEY_SIZE ) {
                   // Bug 1326: it's an Integer.
  -		req.setAttribute(SSLSupport.KEY_SIZE_KEY,
  +                req.setAttribute(SSLSupport.KEY_SIZE_KEY,
                                    new Integer( msg.getInt()));
  -	       //Integer.toString(msg.getInt()));
  +               //Integer.toString(msg.getInt()));
               }
   
               if( attributeCode == SC_A_REQ_ATTRIBUTE ) {
  @@ -559,23 +568,23 @@
                   String n=tmpMB.toString();
                   msg.getBytes( tmpMB );
                   String v=tmpMB.toString();
  -		req.setAttribute(n, v );
  +                req.setAttribute(n, v );
               }
   
   
               // 1 string attributes
               switch(attributeCode) {
  -	    case SC_A_CONTEXT      :
  +            case SC_A_CONTEXT      :
                   msg.getBytes( tmpMB );
                   // nothing
                   break;
  -		
  -	    case SC_A_SERVLET_PATH :
  +                
  +            case SC_A_SERVLET_PATH :
                   msg.getBytes( tmpMB );
                   // nothing 
                   break;
  -		
  -	    case SC_A_REMOTE_USER  :
  +                
  +            case SC_A_REMOTE_USER  :
                   if( tomcatAuthentication ) {
                       // ignore server
                       msg.getBytes( tmpMB );
  @@ -583,19 +592,19 @@
                       msg.getBytes(req.getRemoteUser());
                   }
                   break;
  -		
  -	    case SC_A_AUTH_TYPE    :
  +                
  +            case SC_A_AUTH_TYPE    :
                   msg.getBytes(req.getAuthType());
                   break;
  -		
  -	    case SC_A_QUERY_STRING :
  -		msg.getBytes(req.queryString());
  +                
  +            case SC_A_QUERY_STRING :
  +                msg.getBytes(req.queryString());
                   break;
  -		
  -	    case SC_A_JVM_ROUTE    :
  +                
  +            case SC_A_JVM_ROUTE    :
                   msg.getBytes(req.instanceId());
                   break;
  -		
  +                
               case SC_A_SSL_CERT     :
                   req.scheme().setString( "https" );
                   // Transform the string into certificate.
  @@ -609,29 +618,29 @@
                   break;
                   
               case SC_A_SSL_CIPHER   :
  -		req.scheme().setString( "https" );
  +                req.scheme().setString( "https" );
                   msg.getBytes(tmpMB);
  -		req.setAttribute(SSLSupport.CIPHER_SUITE_KEY,
  -				 tmpMB.toString());
  +                req.setAttribute(SSLSupport.CIPHER_SUITE_KEY,
  +                                 tmpMB.toString());
                   break;
  -		
  -	    case SC_A_SSL_SESSION  :
  -		req.scheme().setString( "https" );
  +                
  +            case SC_A_SSL_SESSION  :
  +                req.scheme().setString( "https" );
                   msg.getBytes(tmpMB);
  -		req.setAttribute(SSLSupport.SESSION_ID_KEY, 
  -				  tmpMB.toString());
  +                req.setAttribute(SSLSupport.SESSION_ID_KEY, 
  +                                  tmpMB.toString());
                   break;
                   
  -	    case SC_A_SECRET  :
  +            case SC_A_SECRET  :
                   msg.getBytes(tmpMB);
                   String secret=tmpMB.toString();
                   log.info("Secret: " + secret );
                   // endpoint note
                   ep.setNote( secretNote, secret );
                   break;
  -	    default:
  -		break; // ignore, we don't know about it - backward compat
  -	    }
  +            default:
  +                break; // ignore, we don't know about it - backward compat
  +            }
           }
           return 200;
       }
  @@ -641,17 +650,17 @@
           // Decode headers
           MimeHeaders headers = req.getMimeHeaders();
   
  -	int hCount = msg.getInt();
  +        int hCount = msg.getInt();
           for(int i = 0 ; i < hCount ; i++) {
               String hName = null;
   
  -	    // Header names are encoded as either an integer code starting
  -	    // with 0xA0, or as a normal string (in which case the first
  -	    // two bytes are the length).
  +            // Header names are encoded as either an integer code starting
  +            // with 0xA0, or as a normal string (in which case the first
  +            // two bytes are the length).
               int isc = msg.peekInt();
               int hId = isc & 0xFF;
   
  -	    MessageBytes vMB=null;
  +            MessageBytes vMB=null;
               isc &= 0xFF00;
               if(0xA000 == isc) {
                   msg.getInt(); // To advance the read position
  @@ -689,6 +698,81 @@
                                              bchunk.getLength());
               }
           }
  +    }
  +
  +    /**
  +     * Parse host.
  +     */
  +    private void parseHost(MessageBytes valueMB, Request request) 
  +        throws IOException {
  +
  +        if (valueMB == null || valueMB.isNull()) {
  +            // HTTP/1.0
  +            // Default is what the socket tells us. Overriden if a host is 
  +            // found/parsed
  +            request.setServerPort(request.getLocalPort());
  +            request.serverName().duplicate(request.localName());
  +            return;
  +        }
  +
  +        ByteChunk valueBC = valueMB.getByteChunk();
  +        byte[] valueB = valueBC.getBytes();
  +        int valueL = valueBC.getLength();
  +        int valueS = valueBC.getStart();
  +        int colonPos = -1;
  +        CharChunk hostNameC = (CharChunk)request.getNote(HOSTBUFFER);
  +        if(hostNameC == null) {
  +            hostNameC = new CharChunk(valueL);
  +            request.setNote(HOSTBUFFER, hostNameC);
  +        }
  +        hostNameC.recycle();
  +
  +        boolean ipv6 = (valueB[valueS] == '[');
  +        boolean bracketClosed = false;
  +        for (int i = 0; i < valueL; i++) {
  +            char b = (char) valueB[i + valueS];
  +            hostNameC.append(b);
  +            if (b == ']') {
  +                bracketClosed = true;
  +            } else if (b == ':') {
  +                if (!ipv6 || bracketClosed) {
  +                    colonPos = i;
  +                    break;
  +                }
  +            }
  +        }
  +
  +        if (colonPos < 0) {
  +            if (request.scheme().equalsIgnoreCase("https")) {
  +                // 80 - Default HTTTP port
  +                request.setServerPort(443);
  +            } else {
  +                // 443 - Default HTTPS port
  +                request.setServerPort(80);
  +            }
  +            request.serverName().setChars(hostNameC.getChars(), 
  +                                          hostNameC.getStart(), 
  +                                          hostNameC.getLength());
  +        } else {
  +
  +            request.serverName().setChars(hostNameC.getChars(), 
  +                                          hostNameC.getStart(), colonPos);
  +
  +            int port = 0;
  +            int mult = 1;
  +            for (int i = valueL - 1; i > colonPos; i--) {
  +                int charValue = HexUtils.DEC[(int) valueB[i + valueS]];
  +                if (charValue == -1) {
  +                    // Invalid character
  +                    throw new CharConversionException("Invalid char in port: " + valueB[i + valueS]); 
  +                }
  +                port = port + (charValue * mult);
  +                mult = 10 * mult;
  +            }
  +            request.setServerPort(port);
  +
  +        }
  +
       }
   
   }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-dev-help@jakarta.apache.org