acl  3.5.3.0
HttpServletRequest.hpp
浏览该文件的文档.
1 #pragma once
2 #include "../acl_cpp_define.hpp"
3 #include <vector>
4 #include "../stdlib/string.hpp"
5 #include "../stdlib/noncopyable.hpp"
6 #include "../http/http_header.hpp"
7 #include "http_ctype.hpp"
8 #include "http_type.hpp"
9 
10 #ifndef ACL_CLIENT_ONLY
11 
12 namespace acl {
13 
14 class dbuf_guard;
15 class istream;
16 class ostream;
17 class socket_stream;
18 class http_client;
19 class http_mime;
20 class json;
21 class xml;
22 class session;
23 class HttpSession;
24 class HttpCookie;
25 class HttpServletResponse;
26 
27 /**
28  * 与 HTTP 客户端请求相关的类,该类不应被继承,用户也不需要
29  * 定义或创建该类对象
30  */
32 {
33 public:
34  /**
35  * 构造函数
36  * @param res {HttpServletResponse&}
37  * @param store {session&} 存储会话数据的对象
38  * @param stream {socket_stream&} 数据流,内部不会主动关闭流
39  * @param charset {const char*} 本地字符集,该值非空时,
40  * 内部会自动将 HTTP 请求的数据转换为本地字符集,否则不转换
41  * @param body_limit {int} 针对 POST 方法,当数据体为文本参数
42  * 类型时,此参数限制数据体的长度;当数据体为数据流或 MIME
43  * 格式或 on 为 false,此参数无效
44  */
46  socket_stream& stream, const char* charset = NULL,
47  int body_limit = 102400);
48  ~HttpServletRequest(void);
49 
50  /**
51  * 获得 HTTP 客户端请求方法:GET, POST, PUT, CONNECT, PURGE
52  * @param method_s {string*} 非空时存储字符串方式的请求方法
53  * @return {http_method_t}
54  */
55  http_method_t getMethod(string* method_s = NULL) const;
56 
57  /**
58  * 获得 HTTP 客户端请求的所有 cookie 对象集合
59  * @return {const std::vector<HttpCookie*>&}
60  */
61  const std::vector<HttpCookie*>& getCookies(void) const;
62 
63  /**
64  * 获得 HTTP 客户端请求的某个 cookie 值
65  * @param name {const char*} cookie 名称,必须非空
66  * @return {const char*} cookie 值,若返回 NULL 则表示该 cookie
67  * 不存在
68  */
69  const char* getCookieValue(const char* name) const;
70 
71  /**
72  * 给 HTTP 请求对象添加 cookie 对象
73  * @param name {const char*} cookie 名,非空字符串
74  * @param value {const char*} cookie 值,非空字符串
75  */
76  void setCookie(const char* name, const char* value);
77 
78  /**
79  * 获得 HTTP 请求头中的某个字段值
80  * @param name {const char*} HTTP 请求头中的字段名,非空
81  * @return {const char*} HTTP 请求头中的字段值,返回 NULL
82  * 时表示不存在
83  */
84  const char* getHeader(const char* name) const;
85 
86  /**
87  * 获得 HTTP GET 请求方式 URL 中的参数部分,即 ? 后面的部分
88  * @return {const char*} 没有进行URL 解码的请求参数部分,
89  * 返回空串则表示 URL 中没有参数
90  */
91  const char* getQueryString(void) const;
92 
93  /**
94  * 获得 http://test.com.cn/cgi-bin/test?name=value 中的
95  * /cgi-bin/test 路径部分
96  * @return {const char*} 返回空串表示不存在
97  */
98  const char* getPathInfo(void) const;
99 
100  /**
101  * 获得 http://test.com.cn/cgi-bin/test?name=value 中的
102  * /cgi-bin/test?name=value 路径部分
103  * @return {const char*} 返回空串表示不存在
104  */
105  const char* getRequestUri(void) const;
106 
107  /**
108  * 获得与该 HTTP 会话相关的 HttpSession 对象引用
109  * @param create {bool} 当 session 不存在时是否在缓存服务器自动创建;
110  * 当某客户端的 session 不存在且该参数为 false 时,则该函数返
111  * 回的 session 对象会因没有被真正创建而无法进行读写操作
112  * @param sid {const char*} 当 session 不存在,且 create 参数非空时,
113  * 如果 sid 非空,则使用此值设置用户的唯一会话,同时添加进客户端的
114  * cookie 中
115  * @return {HttpSession&}
116  * 注:优先级,浏览器 COOKIE > create = true > sid != NULL
117  */
118  HttpSession& getSession(bool create = true, const char* sid = NULL);
119 
120  /**
121  * 获得与 HTTP 客户端连接关联的输入流对象引用
122  * @return {istream&}
123  */
124  istream& getInputStream(void) const;
125 
126  /**
127  * 获得 HTTP 双向流对象,由构造函数的参数输入
128  * @return {socket_stream&}
129  */
130  socket_stream& getSocketStream(void) const;
131 
132  /**
133  * 获得 HTTP 请求数据的数据长度
134  * @return {acl_int64} 返回 -1 表示可能为 GET 方法,
135  * 或 HTTP 请求头中没有 Content-Length 字段
136  */
137 #if defined(_WIN32) || defined(_WIN64)
138  __int64 getContentLength(void) const;
139 #else
140  long long int getContentLength(void) const;
141 #endif
142 
143  /**
144  * 如果客户端的请求是分段数据,则该函数将获得请求头中的长度起始地址
145  * 及结束地址
146  * @param range_from {long long int&} 偏移起始位置
147  * @param range_to {long long int&} 偏移结束位置
148  * @return {bool} 若出错或非分段请求则返回false,若是分段请求则返回true
149  * 注:range_from/range_to 下标从 0 开始
150  */
151 #if defined(_WIN32) || defined(_WIN64)
152  bool getRange(__int64& range_from, __int64& range_to);
153 #else
154  bool getRange(long long int& range_from, long long int& range_to);
155 #endif
156  /**
157  * 获得 HTTP 请求头中 Content-Type: text/html; charset=gb2312
158  * Content-Type 的字段值
159  * @param part {bool} 如果为 true 则返回 text,否则返回完整的
160  * 值,如:text/html; charset=gb2312
161  * @param ctype {http_ctype*} 为非空指针时,将存储完整的 http_ctype 信息
162  * @return {const char*} 返回 NULL 表示 Content-Type 字段不存在
163  */
164  const char* getContentType(
165  bool part = true, http_ctype* ctype = NULL) const;
166 
167  /**
168  * 获得 HTTP 请求头中的 Content-Type: text/html; charset=gb2312
169  * 中的 charset 字段值 gb2312
170  * @return {const char*} 返回 NULL 表示 Content-Type 字段 或
171  * charset=xxx 不存在
172  */
173  const char* getCharacterEncoding(void) const;
174 
175  /**
176  * 返回本地的字段字符集
177  * @ return {const char*} 返回 NULL 表示没有设置本地字符集
178  */
179  const char* getLocalCharset(void) const;
180 
181  /**
182  * 返回 HTTP 连接的本地 IP 地址
183  * @return {const char*} 返回空,表示无法获得
184  */
185  const char* getLocalAddr(void) const;
186 
187  /**
188  * 返回 HTTP 连接的本地 PORT 号
189  * @return {unsigned short} 返回 0 表示无法获得
190  */
191  unsigned short getLocalPort(void) const;
192 
193  /**
194  * 返回 HTTP 连接的远程客户端 IP 地址
195  * @return {const char*} 返回空,表示无法获得
196  */
197  const char* getRemoteAddr(void) const;
198 
199  /**
200  * 返回 HTTP 连接的远程客户端 PORT 号
201  * @return {unsigned short} 返回 0 表示无法获得
202  */
203  unsigned short getRemotePort(void) const;
204 
205  /**
206  * 获得 HTTP 请求头中设置的 Host 字段
207  * @return {const char*} 如果为空,则表示不存在
208  */
209  const char* getRemoteHost(void) const;
210 
211  /**
212  * 获得 HTTP 请求头中设置的 User-Agent 字段
213  * @return {const char*} 如果为空,则表示不存在
214  */
215  const char* getUserAgent(void) const;
216 
217  /**
218  * 获得 HTTP 请求中的参数值,该值已经被 URL 解码且
219  * 转换成本地要求的字符集;针对 GET 方法,则是获得
220  * URL 中 ? 后面的参数值;针对 POST 方法,则可以获得
221  * URL 中 ? 后面的参数值或请求体中的参数值
222  * @param name {const char*} 参数名
223  * @param case_sensitive {bool} 比较时针对参数名是否区分大小写
224  * @return {const char*} 返回参数值,当参数不存在时返回 NULL
225  */
226  const char* getParameter(const char* name,
227  bool case_sensitive = false) const;
228 
229  /**
230  * 当 HTTP 请求头中的 Content-Type 为
231  * multipart/form-data; boundary=xxx 格式时,说明为文件上传数据类型,
232  * 则可以通过此函数获得 http_mime 对象
233  * @return {const http_mime*} 返回 NULL 则说明没有 MIME 对象,
234  * 返回的值用户不能手工释放,因为在 HttpServletRequest 的析
235  * 构中会自动释放
236  */
237  http_mime* getHttpMime(void);
238 
239  /**
240  * 数据类型为 text/json 或 application/json 格式时可调用此方法读取 json
241  * 数据体并进行解析,成功后返回 json 对象,该对象由内部产生并管理,当
242  * 本 HttpServletRequest 对象释放时该 json 对象一起被释放
243  * @param body_limit {size_t} 限定数据体长度以防止内存溢出,若请求数据
244  * 体超过此值,则返回错误;如果此值设为 0,则不限制长度
245  * @return {json*} 返回解析好的 json 对象,若返回 NULL 则有以下几个原因:
246  * 1、读数据出错
247  * 2、非 json 数据格式
248  * 3、数据体过长
249  */
250  json* getJson(size_t body_limit = 1024000);
251 
252  /**
253  * 该功能与上面方法类似,唯一区别是将解析结果存入用户传入的对象中
254  * @param out {json&}
255  * @param body_limit {size_t} 限定数据体长度以防止内存溢出,若请求数据
256  * 体超过此值,则返回错误;如果此值设为 0,则不限制长度
257  * @return {bool} 返回 false 原因如下:
258  * 1、读数据出错
259  * 2、非 json 数据格式
260  * 3、数据体过长
261  */
262  bool getJson(json& out, size_t body_limit = 1024000);
263 
264  /**
265  * 数据类型为 text/xml 或 application/xml 格式时可调用此方法读取 xml
266  * 数据体并进行解析,成功后返回 mxl 对象,该对象由内部产生并管理,当
267  * 本 HttpServletRequest 对象释放时该 xml 对象一起被释放
268  * @param body_limit {size_t} 限定数据体长度以防止内存溢出,若请求数据
269  * 体超过此值,则返回错误;如果此值设为 0,则不限制长度
270  * @return {xml*} 返回解析好的 xml 对象,若返回 NULL 则有以下几个原因:
271  * 1、读数据出错
272  * 2、非 xml 数据格式
273  */
274  xml* getXml(size_t body_limit = 1024000);
275 
276  /**
277  * 该功能与上面方法类似,唯一区别是将解析结果存入用户传入的对象中
278  * @param out {xml&}
279  * @param body_limit {size_t} 限定数据体长度以防止内存溢出,若请求数据
280  * 体超过此值,则返回错误;如果此值设为 0,则不限制长度
281  * @return {bool} 返回 false 原因如下:
282  * 1、读数据出错
283  * 2、非 xml 数据格式
284  * 3、数据体过长
285  */
286  bool getXml(xml& out, size_t body_limit = 1024000);
287 
288  /**
289  * 针对 POST 类方法(即有数据请求体情形),可以直接调用此方法获得请求
290  * 数据体的内容
291  * @param body_limit {size_t} 限定数据体长度以防止内存溢出,若请求数据
292  * 体超过此值,则返回错误;如果此值设为 0,则不限制长度
293  * @return {string*} 返回存放数据体的对象,返回 NULL 有以下原因:
294  * 1、读数据出错
295  * 2、没有数据体
296  * 3、数据体过长
297  */
298  string* getBody(size_t body_limit = 1024000);
299 
300  /**
301  * 该功能与上面方法类似,唯一区别是将结果存入用户传入的对象中
302  * @param out {string&}
303  * @param body_limit {size_t}
304  * @return {bool} 返回 false 原因如下:
305  * 1、读数据出错
306  * 2、没有数据体
307  * 3、数据体过长
308  */
309  bool getBody(string& out, size_t body_limit = 1024000);
310 
311  /**
312  * 获得 HTTP 请求数据的类型
313  * @return {http_request_t},一般对 POST 方法中的上传文件应用,需要调用
314  * 该函数获得是否是上传数据类型,当该函数返回 HTTP_REQUEST_OTHER 时,
315  * 用户可以通过调用 getContentType 获得具体的类型字符串
316  */
317  http_request_t getRequestType(void) const;
318 
319  /**
320  * 获得 HTTP 请求页面的 referer URL
321  * @return {const char*} 为 NULL 则说明用户直接访问本 URL
322  */
323  const char* getRequestReferer(void) const;
324 
325  /**
326  * 获得根据 HTTP 请求头获得的 http_ctype 对象
327  * @return {const http_ctype&}
328  */
329  const http_ctype& getHttpCtype(void) const;
330 
331  /**
332  * 判断 HTTP 客户端是否要求保持长连接
333  * @return {bool}
334  */
335  bool isKeepAlive(void) const;
336 
337  /**
338  * 当客户端要求保持长连接时,从 HTTP 请求头中获得保持的时间
339  * @return {int} 返回值 < 0 表示不存在 Keep-Alive 字段
340  */
341  int getKeepAlive(void) const;
342 
343  /**
344  * 获得 HTTP 客户端请求的版本号
345  * @param major {unsigned&} 将存放主版本号
346  * @param minor {unsigned&} 将存放次版本号
347  * @return {bool} 是否成功取得了客户端请求的版本号
348  */
349  bool getVersion(unsigned& major, unsigned& minor) const;
350 
351  /**
352  * 获得 HTTP 客户端支持的数据压缩算法集合
353  * @param out {std::vector<string>&} 存储结果集
354  */
355  void getAcceptEncoding(std::vector<string>& out) const;
356 
357  /*
358  * 当 HTTP 请求为 POST 方法,通过本函数设置读 HTTP 数据体的
359  * IO 超时时间值(秒)
360  * @param rw_timeout {int} 读数据体时的超时时间(秒)
361  */
362  void setRwTimeout(int rw_timeout);
363 
364  /**
365  * 获得上次出错的错误号
366  * @return {http_request_error_t}
367  */
368  http_request_error_t getLastError(void) const;
369 
370  /**
371  * 当 HttpServlet 类以服务模式(即非 CGI 方式)运行时,可以调用此
372  * 方法获得客户端连接的 HTTP 类对象,从而获得更多的参数
373  * @return {http_client*} 当以服务模式运行时,此函数返回 HTTP 客户端
374  * 连接非空对象;当以 CGI 方式运行时,则返回空指针
375  */
376  http_client* getClient(void) const;
377 
378  /**
379  * 将 HTTP 请求头输出至流中(文件流或网络流)
380  * @param out {ostream&}
381  * @param prompt {const char*} 提示内容
382  */
383  void fprint_header(ostream& out, const char* prompt);
384 
385  /**
386  * 将 HTTP 请求头输出至给定缓冲区中
387  * @param out {string&}
388  * @param prompt {const char*} 提示内容
389  */
390  void sprint_header(string& out, const char* prompt);
391 
392 private:
393  dbuf_guard* dbuf_internal_;
394  dbuf_guard* dbuf_;
395  http_request_error_t req_error_;
396  char cookie_name_[64];
397  HttpServletResponse& res_;
398  session& store_;
399  HttpSession* http_session_;
400  socket_stream& stream_;
401  int body_limit_;
402  bool body_parsed_;
403 
404  std::vector<HttpCookie*> cookies_;
405  bool cookies_inited_;
406  http_client* client_;
407  http_method_t method_;
408  bool cgi_mode_;
409  http_ctype content_type_;
410  char localAddr_[32];
411  char remoteAddr_[32];
412  char localCharset_[32];
413  int rw_timeout_;
414  std::vector<HTTP_PARAM*> params_;
415  http_request_t request_type_;
416  http_mime* mime_;
417  string* body_;
418  json* json_;
419  xml* xml_;
420 
421  bool readHeaderCalled_;
422  bool readHeader(string* method_s);
423 
424  void add_cookie(char* data);
425  void parseParameters(const char* str);
426 };
427 
428 } // namespace acl
429 
430 #endif // ACL_CLIENT_ONLY
HTTP_API void const char * name
Definition: lib_http.h:620
http_request_t
Definition: http_type.hpp:45
http_request_error_t
Definition: http_type.hpp:66
http_method_t
Definition: http_type.hpp:29
#define ACL_CPP_API