diff options
author | aunsane <aunsane@gmail.com> | 2017-12-28 21:21:10 +0300 |
---|---|---|
committer | aunsane <aunsane@gmail.com> | 2017-12-28 21:21:28 +0300 |
commit | 0156ed41dceeef48f070adf67f14d4ba4c4f6d61 (patch) | |
tree | d0e1dca4c2c9c3c056ae9cb69dde10ea59316481 /protocols/Steam/src/http_request.h | |
parent | f0075f2b956969f29acd3bc9289c8a5f78faddad (diff) |
Steam: refactoring
- reworking http requests
- added ability to get game name by appid
- another attempt to fix #633
- minor refactoring
Diffstat (limited to 'protocols/Steam/src/http_request.h')
-rw-r--r-- | protocols/Steam/src/http_request.h | 413 |
1 files changed, 312 insertions, 101 deletions
diff --git a/protocols/Steam/src/http_request.h b/protocols/Steam/src/http_request.h index 841910dc32..43bb68d464 100644 --- a/protocols/Steam/src/http_request.h +++ b/protocols/Steam/src/http_request.h @@ -1,166 +1,377 @@ #ifndef _HTTP_REQUEST_H_ #define _HTTP_REQUEST_H_ -class HttpResponse : public NETLIBHTTPREQUEST, public MZeroedObject +class HttpRequest; +class HttpResponse; + +class HttpUri { + friend class HttpRequest; + private: - bool isEmptyResponse; + CMStringA m_uri; + NETLIBHTTPREQUEST *m_request; + + HttpUri(NETLIBHTTPREQUEST *request, const char *uri) + : m_request(request), m_uri(uri) + { + if (m_request) + m_request->szUrl = m_uri.GetBuffer(); + } + + HttpUri(NETLIBHTTPREQUEST *request, const char *urlFormat, va_list args) + : m_request(request) + { + m_uri.AppendFormatV(urlFormat, args); + if (m_request) + m_request->szUrl = m_uri.GetBuffer(); + } + + ~HttpUri() + { + if (m_request) + m_request->szUrl = NULL; + } + + void FormatV(const char *urlFormat, va_list args) + { + m_uri.AppendFormatV(urlFormat, args); + if (m_request) + m_request->szUrl = m_uri.GetBuffer(); + } + + void AppendFormat(const char *fmt, ...) + { + va_list args; + va_start(args, fmt); + m_uri += (m_uri.Find('?') == -1) ? '?' : '&'; + m_uri.AppendFormatV(fmt, args); + va_end(args); + + if (m_request) + m_request->szUrl = m_uri.GetBuffer(); + } public: - const NETLIBHTTPREQUEST* request; + HttpUri& operator=(const HttpUri&); // to prevent copying; - HttpResponse(const NETLIBHTTPREQUEST* response, const NETLIBHTTPREQUEST* request = NULL) + operator const char*() const { - this->request = request; - isEmptyResponse = (response == NULL); - if (response) - { - cbSize = response->cbSize; - requestType = response->requestType; - flags = response->flags; - szUrl = mir_strdup(response->szUrl); - headers = (NETLIBHTTPHEADER*)mir_alloc(sizeof(NETLIBHTTPHEADER) * response->headersCount); - headersCount = response->headersCount; - for (int i = 0; i < headersCount; i++) - { - headers[i].szName = mir_strdup(response->headers[i].szName); - headers[i].szValue = mir_strdup(response->headers[i].szValue); - } - pData = (char*)mir_alloc(response->dataLength); - dataLength = response->dataLength; - memcpy(pData, response->pData, dataLength); - resultCode = response->resultCode; - szResultDescr = mir_strdup(response->szResultDescr); - nlc = response->nlc; - timeout = response->timeout; - } - else if (request != NULL) - { - // when response is null, we must get resultCode from the request object - resultCode = request->resultCode; - } + return m_request + ? m_request->szUrl + : NULL; } - bool const operator !() const + HttpUri &operator<<(const PARAM ¶m) { - return isEmptyResponse; + AppendFormat(param.szName); + return *this; } - ~HttpResponse() + HttpUri &operator<<(const INT_PARAM ¶m) { - for (int i = 0; i < headersCount; i++) - { - mir_free(headers[i].szName); - mir_free(headers[i].szValue); - } - mir_free(szUrl); - mir_free(headers); - mir_free(pData); - mir_free(szResultDescr); + AppendFormat("%s=%i", param.szName, param.iValue); + return *this; + } + + HttpUri &operator<<(const INT64_PARAM ¶m) + { + AppendFormat("%s=%lld", param.szName, param.iValue); + return *this; + } + + HttpUri &operator<<(const CHAR_PARAM ¶m) + { + AppendFormat("%s=%s", param.szName, ptrA(mir_urlEncode(param.szValue))); + return *this; } }; -class HttpRequest : public NETLIBHTTPREQUEST, public MZeroedObject +class HttpHeaders { + friend class HttpContent; + friend class HttpRequest; + friend class HttpResponse; + private: - CMStringA m_url; + NETLIBHTTPREQUEST *m_request; + + HttpHeaders(NETLIBHTTPREQUEST *request) + : m_request(request) + { + } + + void Set(LPCSTR szName) + { + Set(szName, ""); + } + + void Set(LPCSTR szName, LPCSTR szValue) + { + if (!m_request) + return; + + m_request->headers = (NETLIBHTTPHEADER*)mir_realloc(m_request->headers, + sizeof(NETLIBHTTPHEADER)*(m_request->headersCount + 1)); + m_request->headers[m_request->headersCount].szName = mir_strdup(szName); + m_request->headers[m_request->headersCount].szValue = mir_strdup(szValue); + m_request->headersCount++; + } + +public: + HttpHeaders& operator=(const HttpHeaders&); // to prevent copying; + + const NETLIBHTTPHEADER* operator[](size_t idx) const + { + return m_request + ? &m_request->headers[idx] + : NULL; + } + + size_t GetSize() const + { + return m_request + ? m_request->headersCount + : 0; + } + + HttpHeaders& operator<<(const PARAM ¶m) + { + Set(param.szName); + return *this; + } + + HttpHeaders& operator<<(const CHAR_PARAM ¶m) + { + Set(param.szName, param.szValue); + return *this; + } +}; + +class HttpContent +{ + friend class HttpRequest; + friend class HttpResponse; protected: - enum HttpRequestUrlFormat { FORMAT }; + HttpHeaders Headers; + NETLIBHTTPREQUEST *m_request; - void Init(int type) + HttpContent(NETLIBHTTPREQUEST *request) + : Headers(request), m_request(request) { - cbSize = sizeof(NETLIBHTTPREQUEST); - requestType = type; - flags = NLHRF_HTTP11 | NLHRF_SSL | NLHRF_NODUMPSEND | NLHRF_DUMPASTEXT; - AddHeader("user-agent", "Steam 1.2.0 / iPhone"); } - void AddHeader(LPCSTR szName, LPCSTR szValue) + virtual ~HttpContent() + { + if (m_request) + { + m_request->pData = nullptr; + m_request->dataLength = 0; + } + } + +public: + HttpContent& operator=(const HttpContent&); // to prevent copying; + + operator bool() const + { + return m_request && m_request->pData && m_request->dataLength; + } + + operator const char*() const { - headers = (NETLIBHTTPHEADER*)mir_realloc(headers, sizeof(NETLIBHTTPHEADER)*(headersCount + 1)); - headers[headersCount].szName = mir_strdup(szName); - headers[headersCount].szValue = mir_strdup(szValue); - headersCount++; + return m_request + ? m_request->pData + : nullptr; } - void AddParameter(const char *fmt, ...) + const char* GetData() const + { + return m_request + ? m_request->pData + : nullptr; + } + + size_t GetSize() const + { + return m_request + ? m_request->dataLength + : 0; + } +}; + +class FormUrlEncodedContent : public HttpContent +{ + friend FormUrlEncodedContent* operator<<(FormUrlEncodedContent*, const PARAM&); + friend FormUrlEncodedContent* operator<<(FormUrlEncodedContent*, const BOOL_PARAM&); + friend FormUrlEncodedContent* operator<<(FormUrlEncodedContent*, const INT_PARAM&); + friend FormUrlEncodedContent* operator<<(FormUrlEncodedContent*, const INT64_PARAM&); + friend FormUrlEncodedContent* operator<<(FormUrlEncodedContent*, const CHAR_PARAM&); + +private: + CMStringA m_content; + + void AppendFormat(const char *fmt, ...) { va_list args; va_start(args, fmt); - m_url += m_url.Find('?') == -1 ? '?' : '&'; - m_url.AppendFormatV(fmt, args); + if (!m_content.IsEmpty()) + m_content += '&'; + m_content.AppendFormatV(fmt, args); va_end(args); + + if (m_request) + { + m_request->pData = m_content.GetBuffer(); + m_request->dataLength = m_content.GetLength(); + } } - void AddParameter(LPCSTR name, LPCSTR value) +public: + FormUrlEncodedContent(NETLIBHTTPREQUEST *request) + : HttpContent(request) { - AddParameter("%s=%s", name, value); + Headers << CHAR_PARAM("Content-Type", "application/x-www-form-urlencoded"); } +}; + +__forceinline FormUrlEncodedContent* operator<<(FormUrlEncodedContent *content, const PARAM ¶m) +{ + content->AppendFormat(param.szName); + return content; +} - void SetData(const char *data, size_t size) +__forceinline FormUrlEncodedContent* operator<<(FormUrlEncodedContent *content, const BOOL_PARAM ¶m) +{ + content->AppendFormat("%s=%s", param.szName, param.bValue ? "true" : "false"); + return content; +} + +__forceinline FormUrlEncodedContent* operator<<(FormUrlEncodedContent *content, const INT_PARAM ¶m) +{ + content->AppendFormat("%s=%i", param.szName, param.iValue); + return content; +} + +__forceinline FormUrlEncodedContent* operator<<(FormUrlEncodedContent *content, const INT64_PARAM ¶m) +{ + content->AppendFormat("%s=%lld", param.szName, param.iValue); + return content; +} + +__forceinline FormUrlEncodedContent* operator<<(FormUrlEncodedContent *content, const CHAR_PARAM ¶m) +{ + content->AppendFormat("%s=%s", param.szName, ptrA(mir_urlEncode(param.szValue))); + return content; +} + +enum HttpMethod +{ + HttpGet = 1, + HttpPost +}; + +class HttpResponse +{ + friend class HttpRequest; + +private: + NETLIBHTTPREQUEST *m_response; + +public: + HttpRequest *Request; + HttpHeaders Headers; + HttpContent Content; + + HttpResponse(HttpRequest *request, NETLIBHTTPREQUEST *response) + : Request(request), + m_response(response), + Headers(response), + Content(response) + { + } + + ~HttpResponse() + { + Netlib_FreeHttpRequest(m_response); + } + + bool operator!() const { - if (pData != NULL) - mir_free(pData); + return !m_response || !m_response->pData; + } + + operator bool() const + { + return m_response && m_response->pData; + } - dataLength = (int)size; - pData = (char*)mir_alloc(size + 1); - memcpy(pData, data, size); - pData[size] = 0; + bool IsSuccess() const + { + return m_response && + m_response->resultCode >= HTTP_CODE_OK && + m_response->resultCode <= HTTP_CODE_MULTI_STATUS; + } + + int GetStatusCode() const + { + return m_response->resultCode; } +}; + +class HttpRequest : protected NETLIBHTTPREQUEST, public MZeroedObject +{ + friend class HttpUri; + friend class HttpHeaders; + friend class HttpContent; + +protected: + enum HttpRequestUrlFormat { FORMAT }; public: - HttpRequest(int type, LPCSTR url) + HttpUri Uri; + HttpHeaders Headers; + HttpContent *Content; + + HttpRequest(HttpMethod method, const char *url) + : Uri(this, url), Headers(this), Content(nullptr) { - Init(type); + cbSize = sizeof(NETLIBHTTPREQUEST); + requestType = method; + flags = NLHRF_HTTP11 | NLHRF_SSL; - m_url = url; + Content = new HttpContent(this); } - HttpRequest(int type, HttpRequestUrlFormat, LPCSTR urlFormat, ...) + HttpRequest(HttpMethod method, HttpRequestUrlFormat, const char *urlFormat, ...) + : Uri(this, urlFormat), Headers(this), Content(nullptr) { - Init(type); + cbSize = sizeof(NETLIBHTTPREQUEST); + requestType = method; + flags = NLHRF_HTTP11 | NLHRF_SSL; va_list formatArgs; va_start(formatArgs, urlFormat); - m_url.AppendFormatV(urlFormat, formatArgs); + Uri.FormatV(urlFormat, formatArgs); va_end(formatArgs); + + Content = new HttpContent(this); } ~HttpRequest() { - for (int i = 0; i < headersCount; i++) + if (Content != nullptr) { - mir_free(headers[i].szName); - mir_free(headers[i].szValue); + delete Content; + Content = nullptr; } - mir_free(headers); - - if (pData != NULL) - mir_free(pData); } - HttpResponse* Send(HNETLIBUSER nlu) + operator NETLIBHTTPREQUEST*() { - szUrl = m_url.GetBuffer(); - - Netlib_Logf(nlu, "Send request to %s", szUrl); - - NETLIBHTTPREQUEST* response = Netlib_HttpTransaction(nlu, this); - HttpResponse* result = new HttpResponse(response, this); - Netlib_FreeHttpRequest(response); - - return result; + return this; } }; - -bool __forceinline ResponseHttpOk(const HttpResponse *response) { - return (response && response->pData && (response->resultCode == HTTP_CODE_OK)); -} - -bool __forceinline CheckResponse(const HttpResponse *response) { - return (response && response->pData); -} - #endif //_HTTP_REQUEST_H_
\ No newline at end of file |