📄 bscproxy.cpp
字号:
{
PIString &sTmp = *( (PIString *)iAllowHosts.Current() );
if ( HTTPUtil_regexMatch( sTmp, sTmp.Len(), pHost,
strlen( pHost ) ) )
{
iFound = 1;
break;
};
};
};
if ( !iFound )
{
/* ---
list of allowed hosts was specified but this host did
not match any of them
--- */
tPIHTTP.iStatus = ST_FORBIDDEN;
return HTTPUtil_doHTTPError( &tPIHTTP, ST_FORBIDDEN );
};
/* --- get the method and URL path and Query String --- */
const char *pMethod = (const char *)PIDB_lookup( pQ, PIDBTYPE_STRING,
KEY_HTTP_METHOD, 0 );
int iMethod = (int)PIDB_lookup( pQ, PIDBTYPE_OPAQUE, KEY_HTTP_METHOD,
0 );
const char *pURI = (const char *)PIDB_lookup( pQ, PIDBTYPE_STRING,
KEY_HTTP_URI, 0 );
const char *pQS = (const char *)PIDB_lookup( pQ, PIDBTYPE_STRING,
KEY_HTTP_QUERYSTRING, 0 );
if ( !pMethod || !pURI )
{
HTTPCore_logError( &tPIHTTP, "BasicProxy: Internal error" );
return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
};
/* ---
Generate filename of meta file
--- */
PIString sMetaFileName;
CacheFileName( pHost, pPort, pURI, "met", sMetaFileName );
/* ---
See if the request can be correctly handled by using cached data
--- */
if ( !pQS )
{
switch( HandleFromCachedData( tPIHTTP, sMetaFileName ) )
{
case 1: return PIAPI_COMPLETED;
case 0: break;
default:
tPIHTTP.iStatus = ST_INTERNALERROR;
return PIAPI_COMPLETED;
};
};
/* ---
Get a connection to the server, either by creating a new one or
by reusing an existing connection
--- */
PIObject *pConn = GetProxyConnection( tPIHTTP, pProto, pHost,
iPort );
if ( !pConn )
{
/* --- this is an error --- */
HTTPCore_logError( &tPIHTTP, "BasicProxy: Failed to establish IO \
connection to remote server with location '%s://%s:%d'.", pProto, pHost,
iPort );
return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
};
/* --- make a buffer object --- */
PIIOBuffer *pProxy = PIIOBuffer_new( pConn );
/* ---
Issue the HTTP request
--- */
/* --- place status line in buffer --- */
PIIOBuffer_write( pProxy, pMethod, -1, PIIOBUF_NONE );
PIIOBuffer_write( pProxy, " ", 1, PIIOBUF_NONE );
PIIOBuffer_write( pProxy, pURI, -1, PIIOBUF_NONE );
if ( pQS && *pQS )
{
PIIOBuffer_write( pProxy, "?", 1, PIIOBUF_NONE );
PIIOBuffer_write( pProxy, pQS, -1, PIIOBUF_NONE );
};
PIIOBuffer_write( pProxy, " ", 1, PIIOBUF_NONE );
PIIOBuffer_writeLn( pProxy, "HTTP/1.0", 8, PIIOBUF_NONE );
/* ---
Modify client headers
--- */
/*
** NOTE: Reexamine this later
**
** PIDBIterator *pIter = PIDB_getIterator( pQ, PIDBTYPE_RFC822,
** KEY_HTTP_CONNECTION, 0 );
** if ( pIter )
** {
** while( PIDBIterator_atValidElement( pIter ) )
** { PIDBIterator_removeCurrent( pIter ); };
** PIDBIterator_delete( pIter );
** };
*/
/* --- iterate over all headers, sending them to server --- */
PIDBIterator *pRIter = PIDB_getIterator( pQ, PIDBTYPE_RFC822, 0, 0 );
if ( pRIter )
{
for( ; PIDBIterator_atValidElement( pRIter );
PIDBIterator_next( pRIter ) )
{
const char *pKey;
const char *pValue = (const char *)
PIDBIterator_current( pRIter, &pKey );
if ( pKey && *pKey )
{
PIIOBuffer_write( pProxy, pKey, -1, PIIOBUF_NONE );
PIIOBuffer_write( pProxy, ": ", 2, PIIOBUF_NONE );
PIIOBuffer_writeLn( pProxy, pValue, -1, PIIOBUF_NONE );
};
};
PIDBIterator_delete( pRIter );
};
PIIOBuffer_writeLn( pProxy, "", 0, PIIOBUF_NONE );
/* ---
Send input from client, if any
--- */
const char *pContentLength = (const char *)PIDB_lookup( pQ,
PIDBTYPE_RFC822, KEY_HTTP_CONTENTLENGTH, 0 );
int iStdinLen = pContentLength ? atoi( pContentLength ) : 0;
if ( iStdinLen>0 )
{
if ( WriteBufferToBuffer( *( tPIHTTP.pBuffer ), *pProxy,
iStdinLen )<0 )
{
/* --- this is an error --- */
HTTPCore_logError( &tPIHTTP, "BasicProxy: Premature close \
on proxy connection to location '%s://%s:%d'.", pProto, pHost, iPort );
PIIOBuffer_delete( pProxy );
return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
};
};
/* --- send the whole thing on its way --- */
PIIOBuffer_flush( pProxy );
/* ---
Read the response status line and headers
--- */
int iRet = HTTPCore_readHeaders( pProxy, pR, RH_RESPONSE );
if ( iRet )
{
HTTPCore_logError( &tPIHTTP, "BasicProxy: Error reading \
response headers from remote server. Error code is %d.", iRet );
iRet = -1;
};
/* ---
Check out status line from remote server
--- */
const char *pCLF = 0;
if ( !iRet && ( pCLF = (const char *)
PIDB_lookup( pR, PIDBTYPE_STRING, KEY_HTTP_CLF, 0 ) ) )
{
/* ---
Get response protocol
--- */
/* ?? */
/* ---
Get response content type
--- */
const char *pRContentType = (const char *)PIDB_lookup( pR,
PIDBTYPE_RFC822, KEY_HTTP_CONTENTTYPE, 0 );
/* ---
Get response content length
--- */
const char *pRContentLength = (const char *)PIDB_lookup( pR,
PIDBTYPE_RFC822, KEY_HTTP_CONTENTLENGTH, 0 );
int iRContentLength = pRContentLength ? atoi( pRContentLength ) : 0;
/* ---
Get response pragma
--- */
const char *pRPragma = (const char *)PIDB_lookup( pR,
PIDBTYPE_RFC822, KEY_HTTP_PRAGMA, 0 );
/* ---
Get expires header
--- */
const char *pExpires = (const char *)PIDB_lookup( pR,
PIDBTYPE_RFC822, KEY_HTTP_EXPIRES, 0 );
/* ++++ __________________________ +++ *
Got status line
* ++++ __________________________ +++ */
/* --- grap the status code sent by the CGI --- */
int i=0;
for(; pCLF[i] && !(isspace(pCLF[i])); i++); /* advance to space */
for(; pCLF[i] && (isspace(pCLF[i])); i++); /* advance past space */
tPIHTTP.iStatus = atoi( &(pCLF[i]) );
/* ---
See if we want to cache this response. Most of the cachable
responses will be simple requests for content. Although more
complex requests could be handled correctly, its a better
'quick win' to only handle the simplest of requests which meet the
following criteria and forward the entire response from other
requests back to the client.
--- */
PIString sMessageMedia( "*essage/*" );
PIString sRContentType( pRContentType );
if ( /* method must be 'GET' or 'HEAD' */
( iMethod==MD_GET || iMethod==MD_HEAD ) &&
( !HTTPUtil_regexMatch(
sMessageMedia, sMessageMedia.Len(),
sRContentType, sRContentType.Len()
) ) &&
/* no 'message' types,
including multipart */
iRContentLength>0 && /* sane content length */
!pQS && /* no query string */
/* no 'Pragma: no-cache' */
( !pRPragma || PIUtil_strncmpi( pRPragma, "no-cache", 8 ) ) &&
!pExpires && /* no expires header */
sCacheRoot.Len() )
{
PIString sFileName;
CacheFileName( pHost, pPort, pURI, "dat", sFileName );
PIPLATFORM_FD tFD;
tFD = PIFile_open( sFileName, "w" );
if ( tFD != PIPLATFORM_FD_INVALID )
{
int iLen;
const char *pBuffer = PIIOBuffer_read( pProxy, &iLen );
while( pBuffer && !iRet )
{
if ( PIFile_write( tFD, iLen, pBuffer ) )
{
/* --- error --- */
HTTPCore_logError( &tPIHTTP, "BasicProxy: \
Error writing file to cache." );
iRet = -1;
};
pBuffer = PIIOBuffer_read( pProxy, &iLen );
};
PIFile_close( tFD );
/* ---
Attempt to create cache record
--- */
switch( CreateCacheRecord( tPIHTTP, sMetaFileName,
sFileName ) )
{
case 0:
/* --- fall through --- */
case 1:
/* --- remove response RFC822 headers --- */
{
PIDBIterator *pIter = PIDB_getIterator( pR,
PIDBTYPE_RFC822, 0, 0 );
if ( pIter )
{
while( PIDBIterator_atValidElement( pIter ) )
{ PIDBIterator_removeCurrent( pIter ); };
PIDBIterator_delete( pIter );
};
};
/* --- issue redirect to send cached data --- */
PIIOBuffer_delete( pProxy );
ReleaseProxyConnection( pConn, 0 );
return INT_REDIRECT;
default:
/* --- error --- */
remove( sFileName );
HTTPCore_logError( &tPIHTTP, "BasicProxy: \
Error writing meta file to cache." );
iRet = -1;
};
};
};
if ( iRet )
{
PIIOBuffer_delete( pProxy );
ReleaseProxyConnection( pConn, 0 );
return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
};
/* ---
Right now disable keep alive, because we don't trust the
headers returned from the server (in terms of content length)
--- */
PIDB_replace( tPIHTTP.pConnectionDB, PIDBTYPE_OPAQUE,
KEY_INT_KEEPOPEN, (void *)0, 0 );
/* --- start response --- */
if ( HTTPCore_sendGeneralHeaders( &tPIHTTP ) ||
HTTPCore_sendEntityHeaders( &tPIHTTP, pR ) )
{
iRet = -1;
};
if ( !iRet )
{
/* ---
Send response from server back to client
--- */
if ( WriteBufferToBuffer( *pProxy, *( tPIHTTP.pBuffer ) )<0 )
{
HTTPCore_logError( &tPIHTTP, "BasicProxy: Premature close \
from remote HTTP server '%s://%s:%d'.", pProto, pHost, iPort );
iRet = -1;
};
};
}
else
{
HTTPCore_logError( &tPIHTTP, "BasicProxy: Bad response \
from remote HTTP server '%s://%s:%d'.", pProto, pHost, iPort );
iRet = -1;
};
/* --- send the entire result back to the client --- */
/* --- done --- */
PIIOBuffer_delete( pProxy );
ReleaseProxyConnection( pConn, 0 );
if ( iRet )
{
return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
};
return PIAPI_COMPLETED;
};
/* -------------- +++++++++++++++++++++++++++++++ ------------------ *\
Standard Handle Function
\* -------------- +++++++++++++++++++++++++++++++ ------------------ */
int Handle( int iPhase, PIHTTP &tPIHTTP, PIIOBuffer &/* tBuffer */ )
{
if ( iPhase!=PH_HANDLE )
{ return PIAPI_ERROR; };
return DoProxy( tPIHTTP );
};
};
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
PUBLIC_PIAPI int BasicProxy_constructor( PIObject *pObj,
int iArgc, const char *ppArgv[] )
{
return HandlerBaseHTTP_constructor( pObj, PI_NEW( BasicProxy( pObj,
iArgc, ppArgv ) ) );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -