📄 httprequest.java
字号:
// HttpRequest.java - Class that represents HTTP requests.
//
// Copyright (C) 1999-2002 Smart Software Consulting
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// Smart Software Consulting
// 1688 Silverwood Court
// Danville, CA 94526-3079
// USA
//
// http://www.smartsc.com
//
package com.smartsc.http;
import java.io.BufferedReader;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.InputStreamReader;
import java.io.InterruptedIOException;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Locale;
import java.util.StringTokenizer;
import java.util.Vector;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletInputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpServletRequest;
import com.smartsc.util.Base64;
import com.smartsc.util.CaselessHashtable;
import com.smartsc.util.NVPairParser;
public class
HttpRequest
implements HttpStatusCodes, HttpReasonPhrases,
HttpHeaders, HttpServletRequest
{
protected
HttpRequest( HttpServer server, Socket socket)
throws IOException
{
this.server = server;
this.socket = socket;
is = new BufferedInputStream(
socket.getInputStream(), server.getBufferSize() );
}
protected
void
parseRequest()
throws HttpException
{
try
{
// Parse first line
String s = readLine();
StringTokenizer st = new StringTokenizer( s);
method = st.nextToken();
verbatimRequestPath = st.nextToken();
protocol = st.nextToken();
parseRequestPath( verbatimRequestPath );
// Don't accept proxy requests (i.e. "GET http://host/uri ...")
if( !requestPath.startsWith( "/" )
|| st.hasMoreTokens() )
{
throw new HttpException( SC_BAD_REQUEST, RP_BAD_REQUEST);
}
// Parse headers
s = readLine();
while( !"".equals( s))
{
int idx = s.indexOf( ":");
if( idx < 0)
{
server.log( "Bad Header: '" + s + "'");
throw new HttpException( SC_BAD_REQUEST, RP_BAD_REQUEST);
}
String name = s.substring( 0, idx);
String value = "";
if( idx < s.length()-1)
{
value = s.substring( idx+1).trim();
}
setHeader( name, value);
s = readLine();
}
// Look for authorization
String auth = getHeader( AUTHORIZATION);
if( auth != null)
{
st = new StringTokenizer( auth);
if( st.hasMoreTokens())
authType = st.nextToken();
if( st.hasMoreTokens())
{
String credentials = Base64.decode( st.nextToken());
int colon = credentials.indexOf( ':');
if( colon != -1)
remoteUser = credentials.substring( 0, colon);
}
}
// Look for session
sessionName = server.getSessionName();
Cookie sessionCookie = getCookie( sessionName);
if( sessionCookie != null)
{
reqSessionId = sessionCookie.getValue();
if( reqSessionId != null)
{
reqSessionIdFromCookie = true;
}
}
else
{
// Can't call getParameter( sessionName ) because
// that would/could cause POST data to be parsed!
Vector v = (Vector)parameters.get( sessionName);
if( v != null)
{
reqSessionId = (String)v.firstElement();
if( reqSessionId != null)
{
reqSessionIdFromURL = true;
}
}
}
// Specific SessionId requested
if( reqSessionId != null)
{
// Look for session, but don't create
session = getSession( reqSessionId);
// If found
if( session != null)
{
session.setLastAccessedTime();
// Requested sessionId valid
reqSessionIdValid = true;
}
}
}
catch( HttpException he)
{
throw he;
}
catch( InterruptedIOException iioe)
{
throw new HttpException( SC_REQUEST_TIMEOUT, RP_REQUEST_TIMEOUT);
}
catch( Exception e)
{
server.log( "Exception parsing request: ", e );
throw new HttpException( SC_BAD_REQUEST, RP_BAD_REQUEST);
}
}
protected void parsePostData()
throws IOException
{
if( !postDataParsed && HttpMethods.POST.equals( getMethod() ))
{
postDataParsed = true;
// Get content type and length
String contentType = getHeader( CONTENT_TYPE);
int contentLength = getIntHeader( CONTENT_LENGTH);
if( FORM_URLENCODED.equalsIgnoreCase( contentType)
&& contentLength > 0 )
// TODO Limit max length?
{
// Get form data
byte[] content = new byte[contentLength];
int totalBytesRead = 0;
while( totalBytesRead < contentLength )
{
int bytesRead = is.read( content,
totalBytesRead, contentLength - totalBytesRead);
if( bytesRead == -1 ) throw new IOException( "Short read" );
totalBytesRead += bytesRead;
}
String s = new String( content);
StringBuffer sb = new StringBuffer( s);
// Change '+' to ' '
for( int i = 0; i < sb.length(); ++i)
{
if( sb.charAt( i) == '+')
sb.setCharAt( i, ' ');
}
s = sb.toString();
new NVPairParser( s, "&", "=")
{
public void forEachNVPair( String name, String value)
{
setParameter(
httpDecode( name), httpDecode( value) );
}
}.parse();
}
}
}
protected final String readLine()
throws IOException
{
StringBuffer sb = new StringBuffer();
int ch = is.read();
while( ch != '\r' && ch != '\n' && ch != -1)
{
sb.append( (char)ch);
ch = is.read();
}
// If CR, handle CRLF
if( ch == '\r')
{
is.mark( 1);
ch = is.read();
if( ch != '\n')
{
// put it back
is.reset();
}
}
return sb.toString();
}
protected
void
setHeader( String name, String value)
{
headers.put( name, value);
// If cookies
if( name.equalsIgnoreCase( "Cookie"))
{
setCookies( value);
}
}
public
Cookie
getCookie( String name)
{
return (Cookie)cookies.get( httpDecode( name));
}
protected
void
setCookies( String cookieString)
{
new NVPairParser( cookieString, ";", "=")
{
public void forEachNVPair( String name, String value)
{
setCookie( name, value);
}
}.parse();
}
protected
void
setCookie( String name, String value)
{
cookies.put( httpDecode( name),
new Cookie( httpDecode(name), httpDecode(value)) );
}
protected
void
pushParameter( String name, String value)
{
setParameter( name, value, true );
}
protected
void
popParameter( String name )
{
Vector v = (Vector)parameters.get( name);
if( v != null )
{
v.removeElementAt( 0 );
if( v.size() == 0 )
{
parameters.remove( name );
}
}
}
protected
void
setParameter( String name, String value)
{
setParameter( name, value, false );
}
protected
void
setParameter( String name, String value, boolean putInFront )
{
Vector v = (Vector)parameters.get( name);
if( v == null)
{
v = new Vector();
parameters.put( name, v);
}
if( putInFront )
{
v.insertElementAt( value, 0 );
}
else
{
v.addElement( value);
}
}
protected
void
createSession()
{
session =
new com.smartsc.http.HttpSession( server.getSessionTimeout());
sessions.put( session.getId(), session);
}
protected
com.smartsc.http.HttpSession
getSession( String sessionId)
{
return (com.smartsc.http.HttpSession)sessions.get( sessionId);
}
protected
void
close()
throws IOException
{
if( ir != null)
{
ir.close();
}
is.close();
}
protected static
void
removeSession( String id)
{
sessions.remove( id);
}
public static
String
httpDecode( String encoded)
{
if( encoded == null)
return null;
StringBuffer decoded = new StringBuffer();
StringTokenizer st = new StringTokenizer( encoded, "%+", true);
while( st.hasMoreTokens())
{
String token = st.nextToken();
if( "%".equals( token) && st.hasMoreTokens())
{
String nextChunk = st.nextToken();
// If Unicode encoding
if( nextChunk.charAt( 0 ) == 'u' )
{
// Find first non-digit in the next four characters
int nonDigitIdx = 5;
int max = Math.min( 5, nextChunk.length() );
for( int i = 1; i < max; ++i )
{
char ch = nextChunk.charAt( i );
if( (ch < '0' || '9' < ch)
&& (ch < 'a' || 'f' < ch)
&& (ch < 'A' || 'F' < ch) )
{
nonDigitIdx = i;
break;
}
}
// Make sure we have at least one digit
if( nonDigitIdx == 1 )
{
throw new NumberFormatException(
"Bad Unicode encoding: %" + nextChunk );
}
decoded.append( (char)
Integer.parseInt( nextChunk.substring( 1, nonDigitIdx), 16));
decoded.append( nextChunk.substring( nonDigitIdx));
}
else
{
decoded.append( (char)
Integer.parseInt( nextChunk.substring( 0, 2), 16));
decoded.append( nextChunk.substring( 2));
}
}
else if( "+".equals( token))
{
decoded.append( " ");
}
else
{
decoded.append( token);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -