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

📄 httpcore.cpp

📁 mini http server,可以集成嵌入到程序中,实现简单的web功能
💻 CPP
📖 第 1 页 / 共 5 页
字号:

	/* ---
	Done!
	--- */
	return INT_CONTINUE;
}

/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
int HTTPCore_sendGeneralHeaders( PIHTTP *pPIHTTP )
{
	assert( pPIHTTP );
	PIHTTP &tPIHTTP = *pPIHTTP;

	/* --- 
	Don't do anything for subrequests
	--- */
	if ( tPIHTTP.IsSubRequest() )
		{ return PIAPI_COMPLETED; };

	PIIOBuffer &tB = tPIHTTP.GetIOBuffer();
	PIDB *pQ = tPIHTTP.GetRequestDB();
	PIDB *pR = tPIHTTP.GetResponseDB();

	/* --- get status line and headers --- */
	int iStatus = tPIHTTP.iStatus;
	if ( !iStatus )
		{
		/* ---
		If the status is 0 then silently change it to 200 OK
		--- */
		tPIHTTP.iStatus = ST_OK;
		iStatus = ST_OK;
		};

	int iProtocol = (int)PIDB_lookup( pQ, PIDBTYPE_OPAQUE, pFKProtocolNumber,
		PIDBFLAG_FASTKEY );	

	/* --- send status line and headers if this is not HTTP/0.9 --- */
	if ( iProtocol!=PR_HTTP09 )
		{
		switch( iProtocol )
			{
			case PR_UNKNOWN:
			case PR_HTTP10:
				tB.Write( PR_NAME_HTTP10, sizeof( PR_NAME_HTTP10 )-1 ); break;
			case PR_HTTP11:
				tB.Write( PR_NAME_HTTP11, sizeof( PR_NAME_HTTP11 )-1 ); break;
			default:
				assert( 0 );
				return PIAPI_ERROR;
			};

		switch( iStatus )
			{
#define TMP( pattern ) { \
			tB.WriteLn( (pattern), sizeof( pattern )-1 ); break; }
			/* ---
			HTTP 1.0
			--- */
			case ST_OK:						TMP( " 200 OK" );
			case ST_PERMANENTREDIRECT:		TMP( " 301 Permanent Redirect" );
			case ST_FOUND:				if (iProtocol == PR_HTTP11) {
											TMP( " 302 Found" );
										} else {
											TMP( " 302 Temporary Redirect" );
										};
			case ST_NOTMODIFIED:			TMP( " 304 Not Modified" );
			case ST_BADREQUEST:				TMP( " 400 Bad Request" );
			case ST_UNAUTHORIZED:			TMP( " 401 Unauthorized" );
			case ST_FORBIDDEN:				TMP( " 403 Forbidden" );
			case ST_NOTFOUND:				TMP( " 404 Not Found" );
			case ST_INTERNALERROR:			TMP( " 500 Internal Error" );
			case ST_NOTIMPLEMENTED:			TMP( " 501 Not Implemented" );
			case ST_BADGATEWAY:				TMP( " 502 Bad Gateway" );
			case ST_SERVICEUNAVAILABLE:		TMP( " 503 Service Unavailable" );
			case ST_CREATED:				TMP( " 201 Created" );
			case ST_ACCEPTED:				TMP( " 202 Accepted" );
			case ST_NOCONTENT:				TMP( " 204 No Content" );
			/* ---
			HTTP 1.1 
			--- */
			case ST_CONTINUE:				TMP( " 100 Continue" );
			case ST_SWITCHINGPROTOCOLS:		TMP( " 101" );

			case ST_NONAUTHORITATIVEINFO:	TMP( " 203 None-Authoritative Information" );
			case ST_RESETCONTENT:			TMP( " 205 Reset Content" );
			case ST_PARTIALCONTENT:			TMP( " 206 Partial Content" );

			case ST_MULTIPLECHOICES:		TMP( " 300 Multiple Choices" );
			case ST_SEEOTHER:				TMP( " 303 See Other" );
			case ST_USEPROXY:				TMP( " 305 Use Proxy" );
			case ST_UNUSED:					TMP( " 306 (Unused)" );
			case ST_TEMPORARYREDIRECT:		TMP( " 307 Temporary Redirect" );

			case ST_PAYMENTREQUIRED:		TMP( " 402 Payment Required" );
			case ST_METHODNOTALLOWED:		TMP( " 405 Method Not Allowed" );
			case ST_NOTACCEPTABLE:			TMP( " 406 Not Acceptable" );
			case ST_PROXYAUTHREQUIRED:		TMP( " 407 Proxy Authentication Required" );
			case ST_REQUESTTIMEOUT:			TMP( " 408 Request Timeout" );
			case ST_CONFLICT:				TMP( " 409 Conflict" );
			case ST_GONE:					TMP( " 410 Gone" );
			case ST_LENGTHREQUIRED:			TMP( " 411 Length Required" );
			case ST_PRECONDITIONFAILED:		TMP( " 412 Precondition Failed" );
			case ST_REQUESTENTITYTOOLARGE:	TMP( " 413 Request Entity Too Large" );
			case ST_REQUESTURITOOLONG:		TMP( " 414 Request-URI Too Long" );
			case ST_UNSUPPORTEDMEDIATYPE:	TMP( " 415 Unsupported Media Type" );
			case ST_RANGENOTSATISFIABLE:	TMP( " 416 Request Range Not Satisfiable" );
			case ST_EXPECTATIONFAILED:		TMP( " 417 Expectation Failed" );

			case ST_GATEWAYTIMEOUT:			TMP( " 504 Gateway Timeout" );
			case ST_UNSUPPORTEDVERSION:		TMP( " 505 HTTP Version Not supported" );

			default:
#undef TMP
#if !defined(NDEBUG)
				cerr << iStatus << endl;
#endif
				assert( 0 );
				return PIAPI_ERROR;
			};

		/* ---
		Send general header fields 
		--- */

		/* --- server --- */
		if ( pSG->sServerStamp!=PIString::Empty() )
			{
#define TMP "Server: "
			tB.Write( TMP, sizeof( TMP )-1  );
			tB.WriteLn( pSG->sServerStamp, -1 );
			};
#undef TMP		
		/* --- date --- */
		Internal_SendHeader_Date( tB );
		
		/* --- Connection --- */
		Internal_SendHeader_Connection( tPIHTTP );

		/* --- TransferEncoding --- */
#define TMP "Transfer-Encoding: "
		if (const char *pTE = (const char *)PIDB_lookup( pR, PIDBTYPE_RFC822,
			pFKTransferEnc, PIDBFLAG_FASTKEY ))
			{
			tB.Write( TMP, sizeof( TMP )-1 );
			tB.WriteLn( pTE, -1 );
			};
#undef TMP
		};	

	/* --- 
	Done!
	--- */
	return PIAPI_COMPLETED;
}

/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
int HTTPCore_sendEntityHeaders( PIHTTP *pPIHTTP, PIDB *pR )
{
	assert( pPIHTTP );
	PIHTTP &tPIHTTP = *pPIHTTP;

	/* --- 
	Don't do anything for subrequests
	--- */
	if ( tPIHTTP.IsSubRequest() )
		{ return PIAPI_COMPLETED; };

	PIDB *pQ = tPIHTTP.GetRequestDB();
	PIIOBuffer &tB = tPIHTTP.GetIOBuffer();

	int iProtocol = (int)PIDB_lookup( pQ, PIDBTYPE_OPAQUE, pFKProtocolNumber,
		PIDBFLAG_FASTKEY );	

	if ( iProtocol==PR_HTTP09 )			/* --- no header for HTTP/0.9 --- */
		{ return PIAPI_COMPLETED; };

	/* ----
	Do RFC822 response headers
	--- */
	PIDBIterator *pIter = PIDB_getIterator( pR, PIDBTYPE_RFC822, 0, 0 );
	if ( pIter )
		{
		for(;
				PIDBIterator_atValidElement( pIter );
				PIDBIterator_next( pIter ) )
			{
			const char *pKey;
			const char *pValue = (const char *)
			PIDBIterator_current( pIter,  &pKey );
			if (!PIUtil_stricmp(pKey, KEY_HTTP_SERVER)) { continue; };
			if (!PIUtil_stricmp(pKey, KEY_HTTP_DATE)) { continue; };
			if (!PIUtil_stricmp(pKey, KEY_HTTP_CONNECTION)) { continue; };
			if (!PIUtil_stricmp(pKey, KEY_HTTP_TRANSFERENCODING)) { continue; };
			if (!pValue || !*pValue) { continue; };
			tB.Write( pKey, -1 );
			tB.Write( ": ", 2 );
			tB.WriteLn( pValue, -1 );
			};
		PIDBIterator_delete( pIter );
		};
	tB.WriteLn( "", 0 );

	/* --- 
	Done!
	--- */
	return PIAPI_COMPLETED;
}

/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
int HTTPCore_loadMIMEFile( PIObject *pObject, PIDB *pMIMEDB,
	const char *pMIMEFile )
{
	assert( pMIMEFile );
	if ( !pMIMEFile )
		{ return 0; };

	ifstream ifs( pMIMEFile );
	enum { MIME_LINE_MAX=2047 };
	char szMIMEBuf[MIME_LINE_MAX+1];
	szMIMEBuf[MIME_LINE_MAX]='\0';
	if ( !ifs.good() || ifs.eof() )
		{
		enum { TMP_BUF=2048 };
		char szTmpBuf[TMP_BUF];
		sprintf( szTmpBuf, "HTTP1_0: mime file '%s' \
is empty or does not exist.", pMIMEFile );
		CONFIG_ERR( pObject, szTmpBuf );
		return 0;
		};
	while( ifs.good() )
		{
		ifs.getline( szMIMEBuf, MIME_LINE_MAX );
		char *pszMIMEBuf = szMIMEBuf;
		if ( ifs.eof() )
			{ break; };
		int i=0;

		/*
		** Scan to first non-space 
		*/
		for(; pszMIMEBuf[i] && (isspace(pszMIMEBuf[i])); i++);

		/*
		** Is this line empty
		*/
		if ( !pszMIMEBuf[i] || pszMIMEBuf[i]=='#' )
			{ continue; /* comment line */ };

		/*
		** Make pMIMEType point to start of media definition
		*/
		const char *pMIMEType=&( pszMIMEBuf[i] );

		/*
		** Scan to end of media definition (first whitespace)
		*/
		for(; pszMIMEBuf[i] && !(isspace(pszMIMEBuf[i])); i++);
		int bMoreExtns = 0;
		if ( pszMIMEBuf[i] )
			{
			bMoreExtns = 1;
			pszMIMEBuf[i++] = '\0';
			};
		for(; bMoreExtns;)
			{
			/*
			** Scan past whitespace before extension
			*/
			for(; pszMIMEBuf[i] && (isspace(pszMIMEBuf[i])); i++);

			/* if line is empty, skip it */
			if ( !pszMIMEBuf[i] || pszMIMEBuf[i]=='#' )
				{ break; /* line is empty or comment line */ };

			/*
			** Mark start of extension
			*/
			pszMIMEBuf = &( pszMIMEBuf[i] ); i=0;

			/*
			** Skip to end of extension
			*/
			for(; pszMIMEBuf[i] && !(isspace(pszMIMEBuf[i])); i++);
			if ( pszMIMEBuf[i] )
				{
				bMoreExtns = 1;
				pszMIMEBuf[i++] = '\0';
				};
			PIString sExtn( pszMIMEBuf );
#if WIN32
			/*
			** Silently convert to upper case
			*/
			sExtn.ConvertToUpperCase();
#endif
			const char *pExtn = sExtn;
			const char *pPreviousMIMEType = (const char *)PIDB_lookup(
				pMIMEDB, PIDBTYPE_STRING, pExtn, 0 );
			if ( pPreviousMIMEType )
				{
				enum { TMP_BUF=2048 };
				char szTmpBuf[TMP_BUF];
				sprintf( szTmpBuf, "HTTP1_0: reading mime file '%s' \
extension '%s' is already mapped to MIME type '%s'.", pMIMEFile, pExtn,
				pPreviousMIMEType );
				CONFIG_ERR( pObject, szTmpBuf );
				return 0;
				};
			if (PIDB_add( pMIMEDB, PIDBTYPE_STRING, pExtn,
				(void *)pMIMEType, 0 ))
				{
				CONFIG_ERR( pObject, "HTTP1_0: internal error \
dding MIME-type." );
				return 0;
				};
			};
		};
	return 1;
}

/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
PIFInfo *HTTPCore_getCachedFile( const char *pPath )
{
	return PIFInfo_new( pPath );
} 

/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
void HTTPCore_releaseCachedFile( PIFInfo *pFInfo )
{
	PIFInfo_delete( pFInfo );
} 

/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
int HTTPCore_relativeToAbsolutePath( PIDB *pDB,
    const char *pRelativePath, Pi3String *pResult )
{
    assert( pRelativePath );
    assert( pResult );
    assert( pSG );

    /*
    ** Get the server or Host root from the DB
    */
    const char *pRoot = 0;
    if ( pDB )
        {
        pRoot = (const char *)PIDB_lookup( pDB, PIDBTYPE_STRING,
            pFKHostRoot, PIDBFLAG_FASTKEY | PIDBFLAG_PROPAGATEUP );
        };

    if ( !pRoot )
        {
        pRoot = pSG->sServerRoot;
        };

    return Internal_RelativeToAbsolutePath( pRoot, pRelativePath, *pResult );
}

/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
const char *HTTPCore_getServerStamp()
{
	assert( pSG );
	return pSG->sServerStamp;
}

/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
	Returns the MIME type for a file extension
\*____________________________________________________________________________*/
const char *HTTPCore_getMIMETypeFromExtension( const char *pExtn )
{
	assert( pSG );
	const char *pMIME = 0;
#if WIN32
	/*
	** Everything is upper case
	*/
	PIString sExtn( pExtn );
	sExtn.ConvertToUpperCase();
	const char *pExtension = sExtn;
#else
	const char *pExtension = pExtn;
#endif
	if ( !pExtension ||
		!( pMIME = (const char *)PIDB_lookup( pSG->pMIMEDB, PIDBTYPE_STRING,
		pExtension, 0 ) ) )
		{ return pSG->sDefaultMIMEType; };
	return pMIME;
}

/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
	Returns 0 on success.
\*____________________________________________________________________________*/
int HTTPCore_logError( PIHTTP *pPIHTTP, const char *pFormat, ... )
{
	assert( pSG );
#if TEMP
	PIPLATFORM_FD tError = pSG->tErrorLog;
#else
	FILE *pError = pSG->pErrorLog;
#endif

	va_list tvList;
	
	/* --- get time stamp --- */
	enum { BUF_SIZE=255 };
	char szBuf[BUF_SIZE+1];	

	time_t tT;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -