1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 00:37:15 +01:00
SqMod/vendor/DPP/include/dpp/httpsclient.h
Sandu Liviu Catalin 9298065cef Update WIP discord and some vendors.
CPR has features disabled and PCRE is fully disabled until updated to new code.
2023-08-05 21:31:33 +03:00

339 lines
8.6 KiB
C++

/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <string>
#include <map>
#include <list>
#include <vector>
#include <variant>
#include <dpp/sslclient.h>
namespace dpp {
/**
* @brief HTTP connection status
*/
enum http_state : uint8_t {
/**
* @brief Sending/receiving HTTP headers and request body
*/
HTTPS_HEADERS,
/**
* @brief Receiving body content.
*/
HTTPS_CONTENT,
/**
* @brief Completed connection, as it was closed or the body is >= Content-Length
*
*/
HTTPS_DONE,
/**
* @brief Received chunk length
*
*/
HTTPS_CHUNK_LEN,
/**
* @brief Received chunk trailing CRLF
*/
HTTPS_CHUNK_TRAILER,
/**
* @brief The last received chunk is the final chunk
*/
HTTPS_CHUNK_LAST,
/**
* @brief Receiving contents of a chunk
*/
HTTPS_CHUNK_CONTENT
};
/**
* @brief Request headers
*/
typedef std::multimap<std::string, std::string> http_headers;
/**
* @brief Represents a multipart mime body and the correct top-level mime type
* If a non-multipart request is passed in, this is represented as a plain body
* and the application/json mime type.
*/
struct multipart_content {
/**
* @brief Multipart body
*/
std::string body;
/**
* @brief MIME type
*/
std::string mimetype;
};
/**
* @brief Represents a HTTP scheme, hostname and port
* split into parts for easy use in https_client.
*/
struct http_connect_info {
/**
* @brief True if the connection should be SSL
*/
bool is_ssl;
/**
* @brief The request scheme, e.g. 'https' or 'http'
*/
std::string scheme;
/**
* @brief The request hostname part, e.g. 'discord.com'
*/
std::string hostname;
/**
* @brief The port number, either determined from the scheme,
* or from the part of the hostname after a colon ":" character
*/
uint16_t port;
};
/**
* @brief Implements a HTTPS socket client based on the SSL client.
* @note plaintext HTTP without SSL is also supported via a "downgrade" setting
*/
class DPP_EXPORT https_client : public ssl_client
{
/**
* @brief Current connection state
*/
http_state state;
/**
* @brief The type of the request, e.g. GET, POST
*/
std::string request_type;
/**
* @brief Path part of URL for HTTPS connection
*/
std::string path;
/**
* @brief The request body, e.g. form data
*/
std::string request_body;
/**
* @brief The response body, e.g. file content or JSON
*/
std::string body;
/**
* @brief The reported length of the content. If this is
* UULONG_MAX, then no length was reported by the server.
*/
uint64_t content_length;
/**
* @brief Headers for the request, e.g. Authorization, etc.
*/
http_headers request_headers;
/**
* @brief The status of the HTTP request from the server,
* e.g. 200 for OK, 404 for not found. A value of 0 means
* no request has been completed.
*/
uint16_t status;
/**
* @brief Time at which the request should be abandoned
*/
time_t timeout;
/**
* @brief If true the content is chunked encoding
*/
bool chunked;
/**
* @brief Size of current chunk
*/
size_t chunk_size;
/**
* @brief Number of bytes received in current chunk
*/
size_t chunk_receive;
/**
* @brief Headers from the server's response, e.g. RateLimit
* headers, cookies, etc.
*/
std::multimap<std::string, std::string> response_headers;
/**
* @brief Handle input buffer
*
* @param buffer Buffer to read
* @return returns true if the connection should remain open
*/
bool do_buffer(std::string& buffer);
protected:
/**
* @brief Start the connection
*/
virtual void connect();
/**
* @brief Get request state
* @return request state
*/
http_state get_state();
public:
/**
* @brief Connect to a specific HTTP(S) server and complete a request.
*
* The constructor will attempt the connection, and return the content.
* By the time the constructor completes, the HTTP request will be stored
* in the object.
*
* @note This is a blocking call. It starts a loop which runs non-blocking
* functions within it, but does not return until the request completes.
* See queues.cpp for how to make this asynchronous.
*
* @param hostname Hostname to connect to
* @param port Port number to connect to, usually 443 for SSL and 80 for plaintext
* @param urlpath path part of URL, e.g. "/api"
* @param verb Request verb, e.g. GET or POST
* @param req_body Request body, use dpp::https_client::build_multipart() to build a multipart MIME body (e.g. for multiple file upload)
* @param extra_headers Additional request headers, e.g. user-agent, authorization, etc
* @param plaintext_connection Set to true to make the connection plaintext (turns off SSL)
* @param request_timeout How many seconds before the connection is considered failed if not finished
*/
https_client(const std::string &hostname, uint16_t port = 443, const std::string &urlpath = "/", const std::string &verb = "GET", const std::string &req_body = "", const http_headers& extra_headers = {}, bool plaintext_connection = false, uint16_t request_timeout = 5);
/**
* @brief Destroy the https client object
*/
virtual ~https_client();
/**
* @brief Build a multipart content from a set of files and some json
*
* @param json The json content
* @param filenames File names of files to send
* @param contents Contents of each of the files to send
* @param mimetypes MIME types of each of the files to send
* @return multipart mime content and headers
*/
static multipart_content build_multipart(const std::string &json, const std::vector<std::string>& filenames = {}, const std::vector<std::string>& contents = {}, const std::vector<std::string>& mimetypes = {});
/**
* @brief Processes incoming data from the SSL socket input buffer.
*
* @param buffer The buffer contents. Can modify this value removing the head elements when processed.
*/
virtual bool handle_buffer(std::string &buffer);
/**
* @brief Close HTTPS socket
*/
virtual void close();
/**
* @brief Fires every second from the underlying socket I/O loop, used for timeouts
*/
virtual void one_second_timer();
/**
* @brief Get a HTTP response header
*
* @param header_name Header name to find, case insensitive
* @return Header content or empty string if not found.
* If multiple values have the same header_name, this will return one of them.
* @see get_header_count to determine if multiple are present
* @see get_header_list to retrieve all entries of the same header_name
*/
const std::string get_header(std::string header_name) const;
/**
* @brief Get the number of headers with the same header name
*
* @param header_name
* @return the number of headers with this count
*/
size_t get_header_count(std::string header_name) const;
/**
* @brief Get a set of HTTP response headers with a common name
*
* @param header_name
* @return A list of headers with the same name, or an empty list if not found
*/
const std::list<std::string> get_header_list(std::string header_name) const;
/**
* @brief Get all HTTP response headers
*
* @return headers as a map
*/
const std::multimap<std::string, std::string> get_headers() const;
/**
* @brief Get the response content
*
* @return response content
*/
const std::string get_content() const;
/**
* @brief Get the response HTTP status, e.g.
* 200 for OK, 404 for not found, 429 for rate limited.
* A value of 0 indicates the request was not completed.
*
* @return uint16_t HTTP status
*/
uint16_t get_status() const;
/**
* @brief Break down a scheme, hostname and port into
* a http_connect_info.
*
* All but the hostname portion are optional. The path component
* should not be passed to this function.
*
* @param url URL to break down
* @return Split URL
*/
static http_connect_info get_host_info(std::string url);
};
};