⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bscproxy.cpp

📁 mini http server,可以集成嵌入到程序中,实现简单的web功能
💻 CPP
📖 第 1 页 / 共 3 页
字号:
				{
				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 + -