diff options
Diffstat (limited to 'gcsdk/http.cpp')
| -rw-r--r-- | gcsdk/http.cpp | 710 |
1 files changed, 710 insertions, 0 deletions
diff --git a/gcsdk/http.cpp b/gcsdk/http.cpp new file mode 100644 index 0000000..29f4e67 --- /dev/null +++ b/gcsdk/http.cpp @@ -0,0 +1,710 @@ +//====== Copyright � 1996-2010, Valve Corporation, All rights reserved. ======= +// +// Purpose: HTTP related enums and objects, stuff that both clients and server use should go here +// +//============================================================================= + +#include "stdafx.h" +#include <time.h> + +#include "msgprotobuf.h" +#include "rtime.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +using namespace GCSDK; + +//----------------------------------------------------------------------------- +// Purpose: Check if the given status code is one that by spec allows a body, or is +// one that "MUST NOT" include an entity body +//----------------------------------------------------------------------------- +bool CHTTPUtil::BStatusCodeAllowsBody( EHTTPStatusCode eHTTPStatus ) +{ + switch( eHTTPStatus ) + { + case k_EHTTPStatusCode100Continue: + case k_EHTTPStatusCode101SwitchingProtocols: + case k_EHTTPStatusCode204NoContent: + case k_EHTTPStatusCode205ResetContent: + case k_EHTTPStatusCode304NotModified: + return false; + + default: + break; + } + + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Wrapper to ease use of Steam Web APIs +//----------------------------------------------------------------------------- +CSteamAPIRequest::CSteamAPIRequest( EHTTPMethod eMethod, const char *pchInterface, const char *pchMethod, int nVersion ) : + CHTTPRequest( eMethod, "api.steampowered.com", CFmtStr( "/%s/%s/v%04d/", pchInterface, pchMethod, nVersion ) ) +{ + if ( k_EHTTPMethodPOST == eMethod ) + { + SetPOSTParamString( "format", "vdf" ); + SetPOSTParamString( "key", GGCBase()->GetSteamAPIKey() ); + } + else + { + SetGETParamString( "format", "vdf" ); + SetGETParamString( "key", GGCBase()->GetSteamAPIKey() ); + } + + EUniverse universe = GGCHost()->GetUniverse(); + if ( universe == k_EUniverseBeta ) + { + SetHostname( "api-beta.steampowered.com" ); + } + else if ( universe == k_EUniverseDev ) + { + // Set this to your dev universe API endpoint if not local + SetHostname( "localhost:8282" ); + } +} + +CHTTPRequest::CHTTPRequest( CMsgHttpRequest* pProto ) +{ + Init( pProto ); +} + +//----------------------------------------------------------------------------- +// Purpose: Construct a request object, it's invalid until data is setup +//----------------------------------------------------------------------------- +CHTTPRequest::CHTTPRequest() +{ + Init( NULL ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Common init code +//----------------------------------------------------------------------------- +void CHTTPRequest::Init( CMsgHttpRequest* pProto ) +{ + //see if we are wrapping a proto that already exists + if( pProto ) + { + m_pProto = pProto; + m_bOwnProto = false; + } + else + { + m_pProto = new CMsgHttpRequest; + m_bOwnProto = true; + + SetEHTTPMethod( k_EHTTPMethodInvalid ); + // Default URL + SetURL( "/" ); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +CHTTPRequest::CHTTPRequest( EHTTPMethod eMethod, const char *pchHost, const char *pchRelativeURL ) +{ + Init( NULL ); + + SetEHTTPMethod( eMethod ); + SetHostname( pchHost ); + SetURL( pchRelativeURL ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +CHTTPRequest::CHTTPRequest( EHTTPMethod eMethod, const char *pchAbsoluteURL ) +{ + Init( NULL ); + + SetEHTTPMethod( eMethod ); + + // We need to break the URL down into host + relativeURL + const char *pchHost = Q_strstr( pchAbsoluteURL, "://" ); + if ( pchHost ) + { + // Skip past protocol + pchHost += 3; + + // Find the next /, that is the beginning of the actual URL + const char *pchURL = Q_strstr( pchHost, "/"); + if ( !pchURL ) + { + // No URL specified after host? just default to / then. + SetURL( "/" ); + } + else + { + // Ok, now we must remove the query string + const char *pchQueryString = Q_strstr( pchURL, "?" ); + if ( !pchQueryString ) + { + // No query string, full thing is the URL + SetURL( pchURL ); + } + else + { + // URL is everything before query string + SetURLDirect( pchURL, pchQueryString - pchURL ); + + Assert( *pchQueryString == '?' ); + pchQueryString++; + if( *pchQueryString ) + { + m_pProto->mutable_get_params()->Clear(); + CUtlVector<CMsgHttpRequest_QueryParam> vecParams; + RetrieveURLEncodedData( pchQueryString, Q_strlen( pchQueryString ), vecParams ); + FOR_EACH_VEC( vecParams, i ) + { + *m_pProto->add_get_params() = vecParams[i]; + } + } + } + } + + // Is there a userinfo separator in the hostname portion? We don't support + // username/password authentication in the URL, but we must still skip it. + const char *pchUserinfoSep = strchr( pchHost, '@' ); + if ( pchUserinfoSep && ( !pchURL || pchUserinfoSep < pchURL ) ) + { + pchHost = pchUserinfoSep + 1; + } + + // If we found a URL only set upto that, otherwise set everything as host + if ( pchURL ) + SetHostnameDirect( pchHost, pchURL-pchHost ); + else + SetHostname( pchHost ); + } + else + { + AssertMsg( false, "Bad absolute URL to CHTTPRequest constructor, must start with protocol://" ); + EmitError( SPEW_GC, "Bad absolute URL to CHTTPRequest constructor, must start with protocol://" ); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Destructor +//----------------------------------------------------------------------------- +CHTTPRequest::~CHTTPRequest() +{ + if( m_bOwnProto ) + delete m_pProto; +} + + +//----------------------------------------------------------------------------- +// Purpose: Get the value of a GET parameter, this is case-insensitive by default. +//----------------------------------------------------------------------------- +const CMsgHttpRequest_QueryParam *CHTTPRequest::GetGETParam( const char *pchGetParamName, bool bMatchCase ) const +{ + const uint32 nNumParams = m_pProto->get_params_size(); + for( uint32 nParam = 0; nParam < nNumParams; nParam++ ) + { + const CMsgHttpRequest_QueryParam& param = m_pProto->get_params( nParam ); + if ( bMatchCase ) + { + if ( Q_strcmp( param.name().c_str(), pchGetParamName ) == 0 ) + return ¶m; + } + else + { + if ( Q_stricmp( param.name().c_str(), pchGetParamName ) == 0 ) + return ¶m; + } + } + + return NULL; +} + + +//----------------------------------------------------------------------------- +// Purpose: Get the value of a GET parameter, this is case-insensitive by default. +//----------------------------------------------------------------------------- +const char *CHTTPRequest::GetGETParamString( const char *pchGetParamName, const char *pchDefault, bool bMatchCase ) const +{ + const CMsgHttpRequest_QueryParam *pParam = GetGETParam( pchGetParamName, bMatchCase ); + if ( !pParam ) + return pchDefault; + + return pParam->value().c_str(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Get the value of a GET parameter, this is case-insensitive by default. +//----------------------------------------------------------------------------- +bool CHTTPRequest::GetGETParamBool( const char *pchGetParamName, bool bDefault, bool bMatchCase ) const +{ + const CMsgHttpRequest_QueryParam *pParam = GetGETParam( pchGetParamName, bMatchCase ); + if ( !pParam ) + return bDefault; + + return ( Q_atoi( pParam->value().c_str() ) != 0); +} + + +//----------------------------------------------------------------------------- +// Purpose: Get the value of a GET parameter, this is case-insensitive by default. +//----------------------------------------------------------------------------- +int32 CHTTPRequest::GetGETParamInt32( const char *pchGetParamName, int32 nDefault, bool bMatchCase ) const +{ + const CMsgHttpRequest_QueryParam *pParam = GetGETParam( pchGetParamName, bMatchCase ); + if ( !pParam ) + return nDefault; + + return Q_atoi( pParam->value().c_str() ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Get the value of a GET parameter, this is case-insensitive by default. +//----------------------------------------------------------------------------- +uint32 CHTTPRequest::GetGETParamUInt32( const char *pchGetParamName, uint32 unDefault, bool bMatchCase ) const +{ + const CMsgHttpRequest_QueryParam *pParam = GetGETParam( pchGetParamName, bMatchCase ); + if ( !pParam ) + return unDefault; + + return (uint32)V_atoui64( pParam->value().c_str() ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Get the value of a GET parameter, this is case-insensitive by default. +//----------------------------------------------------------------------------- +int64 CHTTPRequest::GetGETParamInt64( const char *pchGetParamName, int64 nDefault, bool bMatchCase ) const +{ + const CMsgHttpRequest_QueryParam *pParam = GetGETParam( pchGetParamName, bMatchCase ); + if ( !pParam ) + return nDefault; + + return V_atoi64( pParam->value().c_str() ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Get the value of a GET parameter, this is case-insensitive by default. +//----------------------------------------------------------------------------- +uint64 CHTTPRequest::GetGETParamUInt64( const char *pchGetParamName, uint64 unDefault, bool bMatchCase ) const +{ + const CMsgHttpRequest_QueryParam *pParam = GetGETParam( pchGetParamName, bMatchCase ); + if ( !pParam ) + return unDefault; + + return V_atoui64( pParam->value().c_str() ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Get the value of a GET parameter, this is case-insensitive by default. +//----------------------------------------------------------------------------- +float CHTTPRequest::GetGETParamFloat( const char *pchGetParamName, float fDefault, bool bMatchCase ) const +{ + const CMsgHttpRequest_QueryParam *pParam = GetGETParam( pchGetParamName, bMatchCase ); + if ( !pParam ) + return fDefault; + + return Q_atof( pParam->value().c_str() ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Get the value of a POST parameter, this is case-insensitive by default. +//----------------------------------------------------------------------------- +const CMsgHttpRequest_QueryParam *CHTTPRequest::GetPOSTParam( const char *pchPostParamName, bool bMatchCase ) const +{ + const uint32 nNumParams = m_pProto->post_params_size(); + for( uint32 nParam = 0; nParam < nNumParams; nParam++ ) + { + const CMsgHttpRequest_QueryParam& param = m_pProto->post_params( nParam ); + if ( bMatchCase ) + { + if ( Q_strcmp( param.name().c_str(), pchPostParamName ) == 0 ) + return ¶m; + } + else + { + if ( Q_stricmp( param.name().c_str(), pchPostParamName ) == 0 ) + return ¶m; + } + } + + return NULL; +} + + +//----------------------------------------------------------------------------- +// Purpose: Get the value of a POST parameter, this is case-insensitive by default. +//----------------------------------------------------------------------------- +const char *CHTTPRequest::GetPOSTParamString( const char *pchGetParamName, const char *pchDefault, bool bMatchCase ) const +{ + const CMsgHttpRequest_QueryParam *pParam = GetPOSTParam( pchGetParamName, bMatchCase ); + if ( !pParam ) + return pchDefault; + + return pParam->value().c_str(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Get the value of a POST parameter, this is case-insensitive by default. +//----------------------------------------------------------------------------- +bool CHTTPRequest::GetPOSTParamBool( const char *pchGetParamName, bool bDefault, bool bMatchCase ) const +{ + const CMsgHttpRequest_QueryParam *pParam = GetPOSTParam( pchGetParamName, bMatchCase ); + if ( !pParam ) + return bDefault; + + return ( Q_atoi( pParam->value().c_str() ) != 0); +} + + +//----------------------------------------------------------------------------- +// Purpose: Get the value of a POST parameter, this is case-insensitive by default. +//----------------------------------------------------------------------------- +int32 CHTTPRequest::GetPOSTParamInt32( const char *pchGetParamName, int32 nDefault, bool bMatchCase ) const +{ + const CMsgHttpRequest_QueryParam *pParam = GetPOSTParam( pchGetParamName, bMatchCase ); + if ( !pParam ) + return nDefault; + + return Q_atoi( pParam->value().c_str() ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Get the value of a POST parameter, this is case-insensitive by default. +//----------------------------------------------------------------------------- +uint32 CHTTPRequest::GetPOSTParamUInt32( const char *pchGetParamName, uint32 unDefault, bool bMatchCase ) const +{ + const CMsgHttpRequest_QueryParam *pParam = GetPOSTParam( pchGetParamName, bMatchCase ); + if ( !pParam ) + return unDefault; + + return (uint32)V_atoui64( pParam->value().c_str() ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Get the value of a POST parameter, this is case-insensitive by default. +//----------------------------------------------------------------------------- +int64 CHTTPRequest::GetPOSTParamInt64( const char *pchGetParamName, int64 nDefault, bool bMatchCase ) const +{ + const CMsgHttpRequest_QueryParam *pParam = GetPOSTParam( pchGetParamName, bMatchCase ); + if ( !pParam ) + return nDefault; + + return V_atoi64( pParam->value().c_str() ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Get the value of a POST parameter, this is case-insensitive by default. +//----------------------------------------------------------------------------- +uint64 CHTTPRequest::GetPOSTParamUInt64( const char *pchGetParamName, uint64 unDefault, bool bMatchCase ) const +{ + const CMsgHttpRequest_QueryParam *pParam = GetPOSTParam( pchGetParamName, bMatchCase ); + if ( !pParam ) + return unDefault; + + return V_atoui64( pParam->value().c_str() ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Get the value of a POST parameter, this is case-insensitive by default. +//----------------------------------------------------------------------------- +float CHTTPRequest::GetPOSTParamFloat( const char *pchGetParamName, float fDefault, bool bMatchCase ) const +{ + const CMsgHttpRequest_QueryParam *pParam = GetPOSTParam( pchGetParamName, bMatchCase ); + if ( !pParam ) + return fDefault; + + return Q_atof( pParam->value().c_str() ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Add a GET param to the request +//----------------------------------------------------------------------------- +void CHTTPRequest::SetGETParamRaw( const char *pchGetParamName, uint8 *pData, uint32 cubDataLen ) +{ + // See if it already exists, and overwrite then (case sensitive!) + CMsgHttpRequest_QueryParam *pParam = const_cast< CMsgHttpRequest_QueryParam* >( GetGETParam( pchGetParamName, true ) ); + if ( !pParam ) + { + // Add a new one then + pParam = m_pProto->add_get_params(); + pParam->set_name( pchGetParamName ); + } + + pParam->set_value( pData, cubDataLen ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Add a POST param to the request given a string for the name and value +//----------------------------------------------------------------------------- +void CHTTPRequest::SetPOSTParamRaw( const char *pchPostParamName, uint8 *pData, uint32 cubDataLen ) +{ + // See if it already exists, and overwrite then (case sensitive!) + CMsgHttpRequest_QueryParam *pParam = const_cast< CMsgHttpRequest_QueryParam* >( GetPOSTParam( pchPostParamName, true ) ); + if ( !pParam ) + { + // Add a new one then + pParam = m_pProto->add_post_params(); + pParam->set_name( pchPostParamName ); + } + + pParam->set_value( pData, cubDataLen ); +} + + +//----------------------------------------------------------------------------- +// Fetch a request headers value by header name +//----------------------------------------------------------------------------- +const char * CHTTPRequest::GetRequestHeaderValue( const char *pchRequestHeaderName, const char *pchDefault ) const +{ + const uint32 nNumHeaders = m_pProto->headers_size(); + for( uint32 nHeader = 0; nHeader < nNumHeaders; nHeader++ ) + { + const CMsgHttpRequest_RequestHeader& header = m_pProto->headers( nHeader ); + if( Q_stricmp( header.name().c_str(), pchRequestHeaderName ) == 0 ) + { + return header.value().c_str(); + } + } + + return pchDefault; +} + +//----------------------------------------------------------------------------- +// Set a header field for the request +//----------------------------------------------------------------------------- +void CHTTPRequest::SetRequestHeaderValue( const char *pchHeaderName, const char *pchHeaderString ) +{ + const uint32 nNumHeaders = m_pProto->headers_size(); + for( uint32 nHeader = 0; nHeader < nNumHeaders; nHeader++ ) + { + CMsgHttpRequest_RequestHeader* pHeader = m_pProto->mutable_headers( nHeader ); + if( Q_stricmp( pHeader->name().c_str(), pchHeaderName ) == 0 ) + { + pHeader->set_value( pchHeaderString ); + return; + } + } + + CMsgHttpRequest_RequestHeader* pHeader = m_pProto->add_headers(); + pHeader->set_name( pchHeaderName ); + pHeader->set_value( pchHeaderString ); +} + +//----------------------------------------------------------------------------- +// Purpose: Fetch a request header by header name and convert it to a time value +// This is just a helpful wrapper of GetRequestHeaderValue that deals with +// parsing the time value +//----------------------------------------------------------------------------- +RTime32 CHTTPRequest::GetRequestHeaderTimeValue( const char *pchRequestHeaderName, RTime32 rtDefault ) const +{ + const char *pchValue = GetRequestHeaderValue( pchRequestHeaderName ); + if( !pchValue ) + return rtDefault; + + return CRTime::RTime32FromHTTPDateString( pchValue ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Set the body data for the request +//----------------------------------------------------------------------------- +void CHTTPRequest::SetBodyData( const void *pubData, uint32 cubData ) +{ + m_pProto->set_body( pubData, cubData ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Get data out of a query string +//----------------------------------------------------------------------------- +void CHTTPRequest::RetrieveURLEncodedData( const char *pchQueryString, int nQueryStrLen, CUtlVector<CMsgHttpRequest_QueryParam> &vecParams ) +{ + CUtlBuffer bufParamName( 0, 64 ); + CUtlBuffer bufParamValue( 0, 128 ); + + // We shouldn't get passed the ? from a query string, but if we do just skip it and parse ok anyway + if ( nQueryStrLen && pchQueryString[0] == '?' ) + { + ++pchQueryString; + --nQueryStrLen; + } + + bool bInParamValue = false; + int iTokenStart = 0; + for( int i=0; i < nQueryStrLen; ++i ) + { + if ( pchQueryString[i] == '=' && !bInParamValue ) + { + // = switches to value from name, starts a new value token + bufParamName.Put( &pchQueryString[iTokenStart], i - iTokenStart ); + bInParamValue = true; + iTokenStart = i + 1; + } + else if ( pchQueryString[i] == '&' ) + { + // & terminates a value and starts a new name token + if ( bInParamValue ) + { + bufParamValue.Put( &pchQueryString[iTokenStart], i - iTokenStart ); + + int iIndex = vecParams.AddToTail(); + CMsgHttpRequest_QueryParam *pParam = &vecParams[iIndex]; + + uint32 unNameLen = Q_URLDecode( (char*)bufParamName.Base(), bufParamName.TellPut(), (const char*)bufParamName.Base(), bufParamName.TellPut() ); + pParam->set_name( (const char*)bufParamName.Base(), unNameLen ); + + uint32 unDataLen = (uint32)Q_URLDecode( (char*)bufParamValue.Base(), bufParamValue.TellPut(), (const char*)bufParamValue.Base(), bufParamValue.TellPut() ); + pParam->set_value( (const uint8*)bufParamValue.Base(), unDataLen ); + } + bufParamName.Clear(); + bufParamValue.Clear(); + bInParamValue = false; + iTokenStart = i+1; + } + } + + // Use any left over value from the end of the query string + if ( bInParamValue ) + { + bufParamValue.Put( &pchQueryString[iTokenStart], nQueryStrLen - iTokenStart ); + + int iIndex = vecParams.AddToTail(); + CMsgHttpRequest_QueryParam *pParam = &vecParams[iIndex]; + + uint32 unNameLen = Q_URLDecode( (char*)bufParamName.Base(), bufParamName.TellPut(), (const char*)bufParamName.Base(), bufParamName.TellPut() ); + pParam->set_name( (const char*)bufParamName.Base(), unNameLen ); + + uint32 unDataLen = (uint32)Q_URLDecode( (char*)bufParamValue.Base(), bufParamValue.TellPut(), (const char*)bufParamValue.Base(), bufParamValue.TellPut() ); + pParam->set_value( (const uint8*)bufParamValue.Base(), unDataLen ); + } +} + + +//---------------------------------------------------------------------------- +// Purpose: Gets a singleton buffer pool for HTTP responses +//---------------------------------------------------------------------------- +static GCConVar http_response_max_pool_size_mb( "http_response_max_pool_size_mb", "10", "Maximum size in bytes of the HTTP Response buffer pool" ); +static GCConVar http_response_init_buffer_size( "http_response_init_buffer_size", "65536", "Initial buffer size for buffers in the HTTP Response buffer pool" ); +/*static*/ CBufferPool &CHTTPResponse::GetBufferPool() +{ + static CBufferPool s_bufferPool( "HTTP Response", http_response_max_pool_size_mb, http_response_init_buffer_size, CUtlBuffer::TEXT_BUFFER | CUtlBuffer::CONTAINS_CRLF ); + return s_bufferPool; +} + + +//----------------------------------------------------------------------------- +// Purpose: Construct a response object, it defaults to being a 500 internal server error response +//----------------------------------------------------------------------------- +CHTTPResponse::CHTTPResponse() : +m_pbufBody( GetBufferPool().GetBuffer() ), +m_eStatusCode( k_EHTTPStatusCode500InternalServerError ) +{ + m_pkvResponseHeaders = new KeyValues( "ResponseHeaders" ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Destructor +//----------------------------------------------------------------------------- +CHTTPResponse::~CHTTPResponse() +{ + GetBufferPool().ReturnBuffer( m_pbufBody ); + m_pbufBody = NULL; + + if ( m_pkvResponseHeaders ) + m_pkvResponseHeaders->deleteThis(); + + m_pkvResponseHeaders = NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: Sets the "expiration" response header to a given number of seconds +// ahead or behind the current time. You can set the Expires header directly as well, +// this is just a helper so you don't have to deal with time formatting. +//----------------------------------------------------------------------------- +void CHTTPResponse::SetExpirationHeaderDeltaFromNow( int32 nSecondsFromNow ) +{ + time_t rawtime; + time( &rawtime ); + rawtime += nSecondsFromNow; + SetHeaderTimeValue( "expires", rawtime ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Formats a time value and sets it as a header. This is a helper so +// you don't have to deal with time formatting +//----------------------------------------------------------------------------- +void CHTTPResponse::SetHeaderTimeValue( const char *pchHeaderName, RTime32 rtTimestamp ) +{ + char rgchDate[128]; + struct tm tmStruct; + time_t rawtime = rtTimestamp; + Plat_gmtime( &rawtime, &tmStruct ); + DbgVerify( strftime( rgchDate, 128, "%a, %d %b %Y %H:%M:%S GMT", &tmStruct ) ); + SetResponseHeaderValue( pchHeaderName, rgchDate ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Serializes the response into a message object (for proxying between +// back-end Steam servers). +//----------------------------------------------------------------------------- +void CHTTPResponse::SerializeIntoProtoBuf( CMsgHttpResponse & response ) const +{ + MEM_ALLOC_CREDIT(); + response.set_status_code( m_eStatusCode ); + + FOR_EACH_VALUE( m_pkvResponseHeaders, pkvRequestHeader ) + { + const char *pchName = pkvRequestHeader->GetName(); + const char *pchValue = pkvRequestHeader->GetString(); + + if ( pchName && pchValue ) + { + CMsgHttpResponse_ResponseHeader *pHeader = response.add_headers(); + pHeader->set_name( pchName ); + pHeader->set_value( pchValue ); + } + } + + if( m_pbufBody->TellPut() > 0 ) + response.set_body( m_pbufBody->Base(), m_pbufBody->TellPut() ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Deserializes the response from a message object (for proxying between +// back-end Steam servers). +//----------------------------------------------------------------------------- +void CHTTPResponse::DeserializeFromProtoBuf( const CMsgHttpResponse & response ) +{ + m_eStatusCode = (EHTTPStatusCode)response.status_code(); + + for( int i=0; i<response.headers_size(); i++ ) + { + m_pkvResponseHeaders->SetString( response.headers(i).name().c_str(), response.headers(i).value().c_str() ); + } + + if( response.has_body() ) + m_pbufBody->Put( response.body().data(), response.body().size() ); +} + |