Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

408 lines
15 KiB

  1. //====== Copyright � 1996-2010, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose: HTTP related enums and objects, stuff that both clients and server use should go here
  4. //
  5. //=============================================================================
  6. #ifndef HTTP_H
  7. #define HTTP_H
  8. #ifdef _WIN32
  9. #pragma once
  10. #endif
  11. #include "steam/steamhttpenums.h"
  12. #include "tier1/keyvalues.h"
  13. #include "tier1/netadr.h"
  14. class CMsgHttpRequest;
  15. class CMsgHttpResponse;
  16. #include "tier0/memdbgon.h"
  17. namespace GCSDK
  18. {
  19. // Container class for useful parsing methods and other utility code used by client or server http code
  20. class CHTTPUtil
  21. {
  22. public:
  23. // Check if a status code allows a body to exist
  24. static bool BStatusCodeAllowsBody( EHTTPStatusCode eHTTPStatus );
  25. };
  26. class CHTTPRequest;
  27. class CHTTPResponse;
  28. class CHTTPServerClientConnection;
  29. // A request parameter, either get or post, or parsed out of the URL
  30. class CHTTPRequestParam
  31. {
  32. public:
  33. // Default constructor
  34. CHTTPRequestParam()
  35. {
  36. m_pData = NULL;
  37. m_cubDataLength = 0;
  38. }
  39. // Constructor with data
  40. CHTTPRequestParam( const char *pchName, uint8 *pData, uint32 cubDataLen )
  41. {
  42. m_strName = pchName;
  43. // We always allocate an extra byte to null terminate, so we can treat as a string safely
  44. // even though treating as a string may truncate early if the data is binary.
  45. m_pData = new uint8[cubDataLen+1];
  46. Q_memcpy( m_pData, pData, cubDataLen );
  47. m_pData[cubDataLen] = 0;
  48. m_cubDataLength = cubDataLen;
  49. }
  50. // Copy constructor (does a deep copy)
  51. CHTTPRequestParam(const CHTTPRequestParam& rhs)
  52. {
  53. m_strName = rhs.m_strName;
  54. m_cubDataLength = rhs.m_cubDataLength;
  55. m_pData = new uint8[rhs.m_cubDataLength+1];
  56. Q_memcpy( m_pData, rhs.m_pData, rhs.m_cubDataLength );
  57. m_pData[m_cubDataLength] = 0;
  58. }
  59. // Operator =
  60. const CHTTPRequestParam& operator=(const CHTTPRequestParam& rhs)
  61. {
  62. if ( m_pData )
  63. delete[] m_pData;
  64. m_strName = rhs.m_strName;
  65. m_cubDataLength = rhs.m_cubDataLength;
  66. m_pData = new uint8[rhs.m_cubDataLength+1];
  67. Q_memcpy( m_pData, rhs.m_pData, rhs.m_cubDataLength );
  68. m_pData[m_cubDataLength] = 0;
  69. return *this;
  70. }
  71. // Destructor
  72. ~CHTTPRequestParam()
  73. {
  74. if ( m_pData )
  75. delete[] m_pData;
  76. m_pData = NULL;
  77. }
  78. // Set the request parameters name
  79. void SetName( const char *pchName )
  80. {
  81. m_strName = pchName;
  82. }
  83. // Set the data for the parameter, this is expected to either be binary
  84. // data, or to be in string form, the conversion Getters will all Q_atoi
  85. // or such when converting to non-string forms.
  86. void SetRawData( uint8 *pData, uint32 cubDataLen )
  87. {
  88. if ( m_pData )
  89. delete[] m_pData;
  90. m_cubDataLength = cubDataLen;
  91. m_pData = new uint8[cubDataLen+1];
  92. Q_memcpy( m_pData, pData, cubDataLen );
  93. m_pData[m_cubDataLength] = 0;
  94. }
  95. // Get the name
  96. const char *GetName() const
  97. {
  98. return m_strName.Get();
  99. }
  100. // Get pointer to the data
  101. const uint8 *GetPubData() const
  102. {
  103. return m_pData;
  104. }
  105. // Get the length of the data
  106. uint32 GetCubData() const
  107. {
  108. return m_cubDataLength;
  109. }
  110. // Get the data as a string
  111. const char *ToString() const
  112. {
  113. return (char *)m_pData;
  114. }
  115. // Get the data converted to an int32
  116. int32 ToInt32() const
  117. {
  118. return Q_atoi( (char *)m_pData );
  119. }
  120. // Get the data converted to an int64
  121. int64 ToInt64() const
  122. {
  123. return Q_atoi64( (char*)m_pData );
  124. }
  125. // Get the data converted to an uint32
  126. uint32 ToUInt32() const
  127. {
  128. return (uint32)V_atoui64( (char *)m_pData );
  129. }
  130. // Get the data converted to an uint64
  131. uint64 ToUInt64() const
  132. {
  133. return V_atoui64( (char *)m_pData );
  134. }
  135. // Get the data converted to a float
  136. float ToFloat() const
  137. {
  138. return Q_atof( (char *)m_pData );
  139. }
  140. #ifdef DBGFLAG_VALIDATE
  141. virtual void Validate( CValidator &validator, const char *pchName )
  142. {
  143. VALIDATE_SCOPE();
  144. ValidateObj( m_strName );
  145. validator.ClaimMemory( m_pData );
  146. }
  147. #endif // DBGFLAG_VALIDATE
  148. private:
  149. CUtlString m_strName;
  150. uint32 m_cubDataLength;
  151. uint8 *m_pData;
  152. };
  153. class CHTTPRequest
  154. {
  155. public:
  156. CHTTPRequest();
  157. CHTTPRequest( EHTTPMethod eMethod, const char *pchHost, const char *pchRelativeURL );
  158. CHTTPRequest( EHTTPMethod eMethod, const char *pchAbsoluteURL );
  159. virtual ~CHTTPRequest();
  160. // Get the method type for the request (ie, GET, POST, etc)
  161. EHTTPMethod GetEHTTPMethod() { return m_eRequestMethod; }
  162. // Get the relative URL for the request
  163. const char *GetURL() { return m_strURL.Get(); }
  164. // Get the value of a GET parameter, using the default value if not set. This is case-insensitive by default.
  165. const CHTTPRequestParam *GetGETParam( const char *pchGetParamName, bool bMatchCase = false ) const;
  166. const char *GetGETParamString( const char *pchGetParamName, const char *pchDefault, bool bMatchCase = false ) const;
  167. bool GetGETParamBool( const char *pchGetParamName, bool bDefault, bool bMatchCase = false ) const;
  168. int32 GetGETParamInt32( const char *pchGetParamName, int32 nDefault, bool bMatchCase = false ) const;
  169. uint32 GetGETParamUInt32( const char *pchGetParamName, uint32 unDefault, bool bMatchCase = false ) const;
  170. int64 GetGETParamInt64( const char *pchGetParamName, int64 nDefault, bool bMatchCase = false ) const;
  171. uint64 GetGETParamUInt64( const char *pchGetParamName, uint64 unDefault, bool bMatchCase = false ) const;
  172. float GetGETParamFloat( const char *pchGetParamName, float fDefault, bool bMatchCase = false ) const;
  173. // Get the value of a POST parameter, using the default value if not set. This is case-insensitive by default.
  174. const CHTTPRequestParam *GetPOSTParam( const char *pchPostParamName, bool bMatchCase = false ) const;
  175. const char *GetPOSTParamString( const char *pchGetParamName, const char *pchDefault, bool bMatchCase = false ) const;
  176. bool GetPOSTParamBool( const char *pchGetParamName, bool bDefault, bool bMatchCase = false ) const;
  177. int32 GetPOSTParamInt32( const char *pchGetParamName, int32 nDefault, bool bMatchCase = false ) const;
  178. uint32 GetPOSTParamUInt32( const char *pchGetParamName, uint32 unDefault, bool bMatchCase = false ) const;
  179. int64 GetPOSTParamInt64( const char *pchGetParamName, int64 nDefault, bool bMatchCase = false ) const;
  180. uint64 GetPOSTParamUInt64( const char *pchGetParamName, uint64 unDefault, bool bMatchCase = false ) const;
  181. float GetPOSTParamFloat( const char *pchGetParamName, float fDefault, bool bMatchCase = false ) const;
  182. // Add a GET param to the request
  183. void SetGETParamString( const char *pchGetParamName, const char *pString ) { SetGETParamRaw( pchGetParamName, (uint8*)pString, Q_strlen(pString) ); }
  184. void SetGETParamBool( const char *pchPostParamName, bool bValue ) { SetGETParamRaw( pchPostParamName, (uint8*)(bValue ? "1" : "0"), 1 ); }
  185. void SetGETParamInt32( const char *pchPostParamName, int32 nValue ) { CFmtStrN<32> str( "%d", nValue ); SetGETParamRaw( pchPostParamName, (uint8*)str.Access(), str.Length() ); }
  186. void SetGETParamUInt32( const char *pchPostParamName, uint32 unValue ) { CFmtStrN<32> str( "%u", unValue ); SetGETParamRaw( pchPostParamName, (uint8*)str.Access(), str.Length() ); }
  187. void SetGETParamInt64( const char *pchPostParamName, int64 nValue ) { CFmtStrN<32> str( "%lld", nValue ); SetGETParamRaw( pchPostParamName, (uint8*)str.Access(), str.Length() ); }
  188. void SetGETParamUInt64( const char *pchPostParamName, uint64 unValue ) { CFmtStrN<32> str( "%llu", unValue ); SetGETParamRaw( pchPostParamName, (uint8*)str.Access(), str.Length() ); }
  189. void SetGETParamFloat( const char *pchPostParamName, float fValue ) { CFmtStrN<32> str( "%f", fValue ); SetGETParamRaw( pchPostParamName, (uint8*)str.Access(), str.Length() ); }
  190. // Adds a GET param containing raw data to the request. If you are using the Web API, you probably do not want this function
  191. void SetGETParamRaw( const char *pchGetParamName, uint8 *pData, uint32 cubDataLen );
  192. // Add a POST param to the request given a string for the name and value
  193. void SetPOSTParamString( const char *pchPostParamName, const char *pString ) { SetPOSTParamRaw( pchPostParamName, (uint8*)pString, Q_strlen(pString) ); }
  194. void SetPOSTParamBool( const char *pchPostParamName, bool bValue ) { SetPOSTParamRaw( pchPostParamName, (uint8*)(bValue ? "1" : "0"), 1 ); }
  195. void SetPOSTParamInt32( const char *pchPostParamName, int32 nValue ) { CFmtStrN<32> str( "%d", nValue ); SetPOSTParamRaw( pchPostParamName, (uint8*)str.Access(), str.Length() ); }
  196. void SetPOSTParamUInt32( const char *pchPostParamName, uint32 unValue ) { CFmtStrN<32> str( "%u", unValue ); SetPOSTParamRaw( pchPostParamName, (uint8*)str.Access(), str.Length() ); }
  197. void SetPOSTParamInt64( const char *pchPostParamName, int64 nValue ) { CFmtStrN<32> str( "%lld", nValue ); SetPOSTParamRaw( pchPostParamName, (uint8*)str.Access(), str.Length() ); }
  198. void SetPOSTParamUInt64( const char *pchPostParamName, uint64 unValue ) { CFmtStrN<32> str( "%llu", unValue ); SetPOSTParamRaw( pchPostParamName, (uint8*)str.Access(), str.Length() ); }
  199. void SetPOSTParamFloat( const char *pchPostParamName, float fValue ) { CFmtStrN<32> str( "%f", fValue ); SetPOSTParamRaw( pchPostParamName, (uint8*)str.Access(), str.Length() ); }
  200. // Adds a POST param containing raw data to the request. If you are using the Web API, you probably do not want this function
  201. void SetPOSTParamRaw( const char *pchPostParamName, uint8 *pData, uint32 cubDataLen );
  202. // Get count of POST params in the request
  203. uint32 GetPOSTParamCount() { return m_vecPostParams.Count(); }
  204. // Get count of GET params in the request
  205. uint32 GetGETParamCount() { return m_vecGetParams.Count(); }
  206. // Fetch a request header by header name and convert it to a time value
  207. RTime32 GetRequestHeaderTimeValue( const char *pchRequestHeaderName, RTime32 rtDefault = 0 );
  208. // Fetch a request headers value by header name
  209. const char *GetRequestHeaderValue( const char *pchRequestHeaderName, const char *pchDefault = NULL ) { return m_pkvRequestHeaders->GetString( pchRequestHeaderName, pchDefault ); }
  210. // Check if the request has any value for the header with the given name
  211. bool BHasRequestHeader( const char *pchRequestHeaderName ) { return (m_pkvRequestHeaders->GetString(pchRequestHeaderName, NULL ) ? true : false); }
  212. // Set the method for the request object
  213. void SetEHTTPMethod( EHTTPMethod eMethod ) { m_eRequestMethod = eMethod; }
  214. // Set the relative URL for the request
  215. void SetURL( const char *pchURL )
  216. {
  217. AssertMsg1( pchURL && pchURL[0] == '/', "URLs must start with the slash (/) character. Param: %s", pchURL );
  218. m_strURL = pchURL;
  219. }
  220. // Set a header field for the request
  221. void SetRequestHeaderValue( const char *pchHeaderName, const char *pchHeaderString ) { m_pkvRequestHeaders->SetString( pchHeaderName, pchHeaderString ); }
  222. // Set body data
  223. bool BSetBodyData( uint8 *pubData, int cubData );
  224. // Get direct access to body data buffer
  225. CUtlBuffer *GetBodyBuffer() { return &m_bufBody; }
  226. // Set hostname for request to target (or host it was received on)
  227. void SetHostname( const char *pchHost ) { m_strHostname.Set( pchHost ); }
  228. void SetHostnameDirect( const char *pchHost, uint32 unLength ) { m_strHostname.SetDirect( pchHost, unLength ); }
  229. const char *GetHostname() { return m_strHostname.Get(); }
  230. // Get direct access to GET param vector
  231. CUtlVector<CHTTPRequestParam> &GetGETParamVector() { return m_vecGetParams; }
  232. CUtlVector<CHTTPRequestParam> &GetPOSTParamVector() { return m_vecPostParams; }
  233. // Get direct access to request headers
  234. KeyValues *GetRequestHeadersKV() { return m_pkvRequestHeaders; }
  235. // writes the request into a protobuf for use in messages
  236. void SerializeIntoProtoBuf( CMsgHttpRequest & request ) const;
  237. // reads the request out of a protobuf from a message
  238. void DeserializeFromProtoBuf( const CMsgHttpRequest & apiKey );
  239. #ifdef DBGFLAG_VALIDATE
  240. virtual void Validate( CValidator &validator, const char *pchName ); // Validate our internal structures
  241. #endif // DBGFLAG_VALIDATE
  242. protected:
  243. // Common initialization code
  244. void Init();
  245. // Method for this request
  246. EHTTPMethod m_eRequestMethod;
  247. // Header values and get param values. Headers are defined with the name case-insensitive, so KV is a good fit.
  248. KeyValues *m_pkvRequestHeaders;
  249. // Get/Post params, these can be case sensitive, so keyvalues would be a bad fit. They would also be a bad
  250. // fit for KV since we may use lots of random param names and use up space in the global string table.
  251. CUtlVector<CHTTPRequestParam> m_vecGetParams;
  252. CUtlVector<CHTTPRequestParam> m_vecPostParams;
  253. // Host to issue the request to (or host received on server side)
  254. // Note: This is not the Host: header value, but rather the actual address the request is received on
  255. // is meant to be issued to. The Host: header may be different containing a virtual hostname.
  256. CUtlString m_strHostname;
  257. // Relative URL
  258. CUtlString m_strURL;
  259. // Body of the request
  260. CUtlBuffer m_bufBody;
  261. };
  262. //-----------------------------------------------------------------------------
  263. // Purpose: A wrapper to CHTTPRequest for Steam WebAPIs. Host, mode, and API key
  264. // are set automatically
  265. //-----------------------------------------------------------------------------
  266. class CSteamAPIRequest : public CHTTPRequest
  267. {
  268. public:
  269. CSteamAPIRequest( EHTTPMethod eMethod, const char *pchInterface, const char *pchMethod, int nVersion );
  270. };
  271. class CHTTPResponse
  272. {
  273. public:
  274. CHTTPResponse();
  275. virtual ~CHTTPResponse();
  276. // Get a specific headers data
  277. const char *GetResponseHeaderValue( const char *pchName, const char *pchDefault = NULL ) { return m_pkvResponseHeaders->GetString( pchName, pchDefault ); }
  278. // Set a specific headers data, will clobber any existing value for that header
  279. virtual void SetResponseHeaderValue( const char *pchName, const char *pchValue ) { m_pkvResponseHeaders->SetString( pchName, pchValue ); }
  280. // Set status code for response
  281. virtual void SetStatusCode( EHTTPStatusCode eStatusCode ) { m_eStatusCode = eStatusCode; }
  282. // Set the expiration header based on a time delta from now
  283. void SetExpirationHeaderDeltaFromNow( int32 nSecondsFromNow );
  284. // Set the expiration header based on a time delta from now
  285. void SetHeaderTimeValue( const char *pchHeaderName, RTime32 rtTimestamp );
  286. // Get the entire headers KV (in case you want to iterate them all or such)
  287. KeyValues *GetResponseHeadersKV() { return m_pkvResponseHeaders; }
  288. // Accessors to the body data in the response
  289. uint8 *GetPubBody() { return (uint8*)m_bufBody.Base(); }
  290. uint32 GetCubBody() { return m_bufBody.TellPut(); }
  291. CUtlBuffer *GetBodyBuffer() { return &m_bufBody; }
  292. // Accessor
  293. EHTTPStatusCode GetStatusCode() { return m_eStatusCode; }
  294. // writes the response into a protobuf for use in messages
  295. void SerializeIntoProtoBuf( CMsgHttpResponse & response ) const;
  296. // reads the response out of a protobuf from a message
  297. void DeserializeFromProtoBuf( const CMsgHttpResponse & response );
  298. #ifdef DBGFLAG_VALIDATE
  299. virtual void Validate( CValidator &validator, const char *pchName ); // Validate our internal structures
  300. #endif // DBGFLAG_VALIDATE
  301. protected:
  302. EHTTPStatusCode m_eStatusCode;
  303. CUtlBuffer m_bufBody;
  304. KeyValues *m_pkvResponseHeaders;
  305. };
  306. }
  307. #include "tier0/memdbgoff.h"
  308. #endif // HTTP_H