acl/lib_acl_cpp/include/acl_cpp/http/http_response.hpp
2024-07-22 17:07:57 +08:00

139 lines
4.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include "../acl_cpp_define.hpp"
#include "../stdlib/noncopyable.hpp"
#include "http_header.hpp"
namespace acl {
class http_client;
class http_pipe;
class socket_stream;
class xml;
class json;
class ACL_CPP_API http_response : public noncopyable {
public:
/**
* 构造函数:通过该构造函数传入的 socket_stream 流对象需要用户自己进行
* 删除,内部在析构时并不会删除它.
* @param client {socket_stream*} 数据连接流,非空
* 注:该类实例在长连接时可以被多次使用,但一定得注意使用
* 顺序get_body->response
*/
explicit http_response(socket_stream* client);
virtual ~http_response();
//////////////////////////////////////////////////////////////////////
// 与读取请求数据相关的方法
/**
* 读取 HTTP 请求客户端的 HTTP 请求头,在调用本方法后才可以调用
* get_body/read_body 读取 HTTP 请求体数据
* @return {bool} 是否成功
*/
bool read_header();
/**
* 读取 xml 格式的 HTTP 请求数据体,调用完此函数后应该调用
* response 给客户端返回响应数据;该函数每次被调用时,内部的
* 对象会被初始化,所以该函数可以在多个会话中被多次调用
* @param out {xml&} 将 HTTP 请求体数据存储于该 xml 对象中
* @param to_charset {const char*} 当该项非空,内部自动
* 将数据转成该字符集存储于 xml 对象中
* @return {bool} 是否正常
* 注:必须首先调用 read_header 后才能调用本函数
* 当请求数据体特别大时不应用此函数,以免内存耗光
*/
bool get_body(xml& out, const char* to_charset = NULL);
/**
* 读取 json 格式的 HTTP 请求数据体,调用完此函数后应该调用
* response 给客户端返回响应数据;该函数每次被调用时,内部的
* 对象会被初始化,所以该函数可以在多个会话中被多次调用
* @param out {json&} 将 HTTP 请求体数据存储于该 json 对象中
* @param to_charset {const char*} 当该项非空,内部自动
* 将数据转成该字符集存储于 json 对象中
* @return {bool} 是否正常
* 注:必须首先调用 read_header 后才能调用本函数
* 当请求数据体特别大时不应用此函数,以免内存耗光
*/
bool get_body(json& out, const char* to_charset = NULL);
/**
* 读取 HTTP 全部请求体数据并存储于输入的缓冲区中
* @param out {string&} 存储请求数据体
* @param to_charset {const char*} 当该项非空,内部自动
* 将数据转成该字符集存储于 out 对象中
* 注:当请求数据体特别大时不应用此函数,以免内存耗光
* 必须首先调用 read_header 后才能调用本函数
*/
bool get_body(string& out, const char* to_charset = NULL);
/**
* 读取 HTTP 请求体数据并存储于输入的缓冲区中,可以循环
* 调用本函数,直至数据读完了,
* @param buf {char*} 存储部分请求体数据
* @param size {size_t} buf 缓冲区大小
* @return {int} 返回值 == 0 表示正常读完毕,< 0 表示客户端
* 关闭连接,> 0 表示已经读到的数据,用户应该一直读数据直到
* 返回值 <= 0 为止
* 注:该函数读到的是原始 HTTP 数据体数据,不做解压和字符集
* 解码,用户自己根据需要进行处理;必须首先调用 read_header
* 后才能调用本函数
*/
int read_body(char* buf, size_t size);
//////////////////////////////////////////////////////////////////////
// 与数据响应相关的方法函数
/**
* 获得 HTTP 响应头对象,然后在返回的 HTTP 响应头对象中添加
* 自己的响应头字段或 http_header::reset()重置响应头状态,
* 参考http_header 类
* @return {http_header&}
*/
http_header& response_header();
/**
* 向客户端发送 HTTP 响应数据,可以循环调用此函数;
* <b>在调用本函数前,必须提前保证以下操作:</b>
* 1必须先调用 read_header && get_body 获得 HTTP 客户端的请求数据;
* 2必须通过 response_header 取得 http_header 对象,同时设置响应头部
* 字段set_status, set_keep_alive 等)
* <b>在调用本函数时,以下操作将会发生:</b>
* 1内部会自动在第一次写时发送 HTTP 响应头;
* 2当通过 http_header::set_chunked 设置了 chunked 传输方式后,
* 内部自动采用 chunked 传输方式;
* 3在使用 chunked 方式传输数据时,应该最后再调用一次本函数,
* 且参数均设为 0 表示数据结束
* @param data {const void*} 数据地址
* @param len {size_t} data 数据长度
* @return {bool} 发送是否成功,如果返回 false 表示连接中断
*/
bool response(const void* data, size_t len);
//////////////////////////////////////////////////////////////////////
/**
* 获得 http_client HTTP 连接流,可以通过返回的对象获得
* 客户端请求头的部分数据参考http_client 类
* @return {http_client*} 当返回空时表示流出错了
*/
http_client* get_client() const;
/**
* 关闭 HTTP 连接流
*/
void close();
private:
bool debug_;
bool header_ok_;
http_client* client_;
http_header header_;
bool head_sent_;
http_pipe* get_pipe(const char* to_charset);
};
} // namespace acl