mac-bot-template/include/dpp/http_server_request.h
2025-08-13 10:10:22 -06:00

261 lines
6.5 KiB
C++

/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* SPDX-License-Identifier: Apache-2.0
* 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/sslconnection.h>
#include <dpp/version.h>
#include <dpp/stringops.h>
#include <dpp/httpsclient.h>
#include <climits>
namespace dpp {
/**
* @brief Callback type for HTTP server request callbacks
*/
using http_server_request_event = std::function<void(class http_server_request*)>;
/*
* @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 http_server_request : public ssl_connection {
/**
* @brief The request body, e.g. form data
*/
std::string request_body;
/**
* @brief Headers from the client
*/
http_headers request_headers;
/**
* @brief Time at which the request should be abandoned
*/
time_t timeout;
/**
* @brief Headers for our response
*/
http_headers response_headers;
/**
* @brief Handler to handle the inbound request
*/
http_server_request_event handler{};
/**
* @brief Response body
*/
std::string response_body;
protected:
/**
* @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 Current connection state
*/
http_state state;
/**
* @brief HTTP status code for response
*/
uint16_t status{0};
/**
* @brief Start the connection
*/
virtual void connect() override;
/**
* @brief Called when the output buffer is drained to empty
*/
void on_buffer_drained() override;
/**
* @brief Maximum size of POST body
*/
[[nodiscard]] uint64_t get_max_post_size() const;
/**
* @brief Maximum size of headers
*/
[[nodiscard]] uint64_t get_max_header_size() const;
/**
* @brief Reply with an error message
* @param error_code error code
* @param message message
*/
void generate_error(uint16_t error_code, const std::string& message);
public:
/**
* @brief If true the response timed out while waiting
*/
bool timed_out;
/**
* @brief Get request state
* @return request state
*/
http_state get_state() const;
/**
* @brief Get current response body
* @return response body
*/
std::string get_response_body() const;
/**
* @brief Get current request body
* @return request body
*/
std::string get_request_body() const;
/**
* @brief Get current status code
* @return status code
*/
uint16_t get_status() const;
/**
* @brief Content length sent by client
*/
uint64_t content_length{ULLONG_MAX};
/**
* @brief Construct a new server request object.
* Server request objects are instantiated for an incoming server connection, as such they already
* have a file descriptor.
* @param creator creating owner
* @param fd file descriptor
* @param port Port the connection came in on
* @param plaintext_downgrade true if plaintext, false if SSL
* @param private_key if SSL, the path to the private key PEM
* @param public_key if SSL, the path to the public key PEM
* @param handle_request request handler callback
*/
http_server_request(cluster* creator, socket fd, uint16_t port, bool plaintext_downgrade, const std::string& private_key, const std::string& public_key, http_server_request_event handle_request);
/**
* @brief Destroy the https client object
*/
virtual ~http_server_request() override;
/**
* @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) override;
/**
* @brief Close HTTPS socket
*/
virtual void close() override;
/**
* @brief Fires every second from the underlying socket I/O loop, used for timeouts
*/
virtual void one_second_timer() override;
/**
* @brief Get a HTTP request 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
*/
[[nodiscard]] const std::string get_header(const 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
*/
[[nodiscard]] size_t get_header_count(const std::string& header_name) const;
/**
* @brief Get a set of HTTP request headers with a common name
*
* @param header_name
* @return A list of headers with the same name, or an empty list if not found
*/
[[nodiscard]] std::list<std::string> get_header_list(const std::string& header_name) const;
/**
* @brief Get all HTTP request headers
*
* @return headers as a map
*/
[[nodiscard]] std::multimap<std::string, std::string> get_headers() const;
/**
* @brief Set a response header
* @param header header name
* @param value header value
* @return ref to self
*/
http_server_request& set_response_header(const std::string& header, const std::string& value);
/**
* @brief Set the response content
*
* @param new_content response content
*/
http_server_request& set_response_body(const std::string& new_content);
/**
* @brief Set the response HTTP status, e.g.
* 200 for OK, 404 for not found, 429 for rate limited etc.
*
* @param new_status HTTP status
*/
http_server_request& set_status(uint16_t new_status);
/**
* @brief Get whole response as a string
*/
[[nodiscard]] std::string get_response();
};
}