📄 mhttpdata.java
字号:
package net.jumperz.net;
import java.io.*;
import java.text.ParsePosition;
import java.util.*;
import java.net.*;
import net.jumperz.util.*;
import net.jumperz.net.exception.*;
import net.jumperz.io.*;
public abstract class MHttpData
{
protected List headerList;
//protected InputStream netInputStream;
protected BufferedInputStream bufferedInputStream;
protected int headerLength = 0;
protected int pos;
protected MBuffer bodyBuffer;
protected boolean hasBodyFlag = false;
//protected byte[] body;
protected static final int HEADER_BUFSIZE = 1024;
protected static final int BODY_BUFSIZE = 4096;
private static final int MAX_HEADER_COUNT = 200;
protected static final byte[] CRLF = { (byte)0x0D, (byte)0x0A };
protected static boolean strictDelimiter = true;
public abstract byte[] getHeader();
protected abstract void recvBodyUntilDisconnected() throws IOException;
//-------------------------------------------------------------------------------------------
public MHttpData()
{
headerList = new ArrayList();
}
//-------------------------------------------------------------------------------------------
public final void addHeaderValue( String name, String value )
{
headerList.add( name + ": " + value );
}
//-------------------------------------------------------------------------------------------
public synchronized final void setHeaderValue( String name, String value )
{
int index = -1;
// get index
int count = headerList.size();
for( int i = 0; i < count; ++i )
{
String header = ( String )headerList.get( i );
if( header.toUpperCase().indexOf( name.toUpperCase() + ":" ) == 0 )
{
index = i;
break;
}
}
if( index > -1 )
{
removeHeaderValue( name );
headerList.add( index, name + ": " + value );
}
else
{
headerList.add( name + ": " + value );
}
/*
removeHeaderValue( name );
headerList.add( name + ": " + value );
*/
}
// --------------------------------------------------------------------------------
public static void setStrictDelimiter( boolean b )
{
strictDelimiter = b;
}
// --------------------------------------------------------------------------------
protected MLineReader getLineReader()
{
if( strictDelimiter )
{
return new MCRLFLineReader();
}
else
{
return new MAdvancedLineReader();
}
}
//-------------------------------------------------------------------------------------------
public final String getHeaderValue( String name )
{
int count = headerList.size();
for( int i = 0; i < count; ++i )
{
String header = ( String )headerList.get( i );
if( header.toUpperCase().indexOf( name.toUpperCase() + ":" ) == 0 )
{
String value = MRegEx.getMatch( "[ ]*(.*)$", header.substring( name.length() + 1 ) );
return value;
}
}
return null;
}
// --------------------------------------------------------------------------------
public final List getHeaderValueList( String name )
{
List l = new ArrayList();
int count = headerList.size();
for( int i = 0; i < count; ++i )
{
String header = ( String )headerList.get( i );
if( header.toUpperCase().indexOf( name.toUpperCase() + ":" ) == 0 )
{
String value = MRegEx.getMatch( "[ ]*(.*)$", header.substring( name.length() + 1 ) );
l.add( value );
}
}
return l;
}
//-------------------------------------------------------------------------------------------
public synchronized final void removeHeaderValue( String name )
{
int count = headerList.size();
for( int i = 0; i < count; ++i )
{
String header = ( String )headerList.get( i );
if( header.toUpperCase().indexOf( name.toUpperCase() + ":" ) == 0 )
{
headerList.remove( i );
--count;
--i;
}
}
}
//-------------------------------------------------------------------------------------------
public final boolean headerExists( String name )
{
int count = headerList.size();
for( int i = 0; i < count; ++i )
{
String header = ( String )headerList.get( i );
if( header.toUpperCase().indexOf( name.toUpperCase() + ":" ) == 0 )
{
return true;
}
}
return false;
}
//-------------------------------------------------------------------------------------------
protected final void readHeaderFields( MLineReader reader )
throws IOException
{
StringBuffer headerStrBuf = new StringBuffer( HEADER_BUFSIZE );
String line;
// read all header fields
for( int i = 0;; ++i )
{
line = reader.readLine();
if( line == null )
{
throw new IOException( "Invalid HTTP data" );
}
headerLength += line.length() + reader.getLastDelimiterSize();
if( line.equals( "" ) )
{
bufferedInputStream.reset();
bufferedInputStream.skip( headerLength );
bufferedInputStream.mark( Integer.MAX_VALUE );
break;
}
else
{
headerStrBuf.append( line );
headerStrBuf.append( "\r\n" );
}
// for DoS attack
if( i > MHttpData.MAX_HEADER_COUNT )
{
throw new IOException( "Too many header fields." );
}
}
String headerStr = headerStrBuf.toString();
if( headerStr.equals( "" ) )
{
// no header fields
return;
}
String[] headerArray = headerStr.split( "\r\n" );
for( int i = 0; i < headerArray.length; ++i )
{
if( headerArray[ i ].indexOf( ":" ) == -1 )
{
//System.err.println( headerArray[ i ] );
throw new IOException( "Invalid HTTP header ( multiple line header field is not allowed )" );
}
headerList.add( headerArray[ i ] );
}
/* old code =)
headerStr = headerStr.replaceAll( "\r\n ", "\r " );
headerStr = headerStr.replaceAll( "\r\n\t", "\r\t" );
String[] headerArray = headerStr.split( "\r\n" );
for( int i = 0; i < headerArray.length; ++i )
{
String workStr = headerArray[ i ].replaceAll( "\r\t" , "\r\n\t" );
workStr = workStr.replaceAll( "\r ", "\r\n " );
if( workStr.indexOf( ":" ) == -1 )
{
System.err.println( workStr );
throw new IOException( "Invalid HTTP data" );
}
headerList.add( workStr );
}
*/
}
//-------------------------------------------------------------------------------------------
protected final void recvBody()
throws IOException
{
try
{
if( headerExists( "Transfer-Encoding" ) )
{
String transferEncoding = getHeaderValue( "Transfer-Encoding" );
if( transferEncoding.equals( "chunked" ) )
{
recvChunkedBody();
}
else
{
throw new IOException( "Unsupported Transfer-Encoding :" + transferEncoding );
}
}
else if( headerExists( "Content-length" ) )
{
recvBodyByContentLength();
}
else
{
// recv data until disconnected by server
recvBodyUntilDisconnected();
}
}
catch( OutOfMemoryError e )
{
e.printStackTrace();
throw new MHttpException( 413, "Request entity too large" );
}
}
// --------------------------------------------------------------------------------
protected int getContentLength()
throws MHttpIOException
{
int contentLength = -1;
if( headerExists( "Content-Length" ) )
{
String value = getHeaderValue( "Content-Length" );
value = value.trim(); // thanks anonymous!
try
{
contentLength = Integer.parseInt( value );
if( contentLength < 0 )
{
throw new MHttpIOException( "Invalid Content-Length" );
}
}
catch( NumberFormatException e )
{
throw new MHttpIOException( "Invalid Content-Length" );
}
}
return contentLength;
}
//-------------------------------------------------------------------------------------------
protected final void recvBodyByContentLength()
throws IOException
{
bodyBuffer = new MBuffer();
int received;
int remain = getContentLength();
int canRead = BODY_BUFSIZE;
byte[] buffer = new byte[ BODY_BUFSIZE ];
if( remain == 0 )
{
hasBodyFlag = false;
return;
}
while( remain > 0 )
{
if( remain < BODY_BUFSIZE )
{
canRead = remain;
}
bufferedInputStream.mark( canRead );
received = bufferedInputStream.read( buffer, 0, canRead );
if( received <= 0 )
{
// HEAD, etc
break;
}
remain -= received;
bufferedInputStream.reset();
bufferedInputStream.skip( received );
bodyBuffer.write( buffer, received );
}
bufferedInputStream.mark( Integer.MAX_VALUE );
}
// --------------------------------------------------------------------------------
public final void chunkToNormal()
throws IOException
{
if( !headerExists( "Transfer-Encoding" ) )
{
return;
}
if( !getHeaderValue( "Transfer-Encoding" ).equals( "chunked" ) )
{
return;
}
if( headerExists( "Content-Length" ) )
{
return;
}
if( !hasBody() )
{
return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -