1 /*
2  *
3  *  C++ Portable Types Library (PTypes)
4  *  Version 2.1.1  Released 27-Jun-2007
5  *
6  *  Copyright (C) 2001-2007 Hovik Melikyan
7  *
8  *  http://www.melikyan.com/ptypes/
9  *
10  */
11 
12 
13 #ifndef W_REQUEST_H
14 #define W_REQUEST_H
15 
16 
17 #include <ptypes.h>
18 #include <pstreams.h>
19 #include <pinet.h>
20 
21 #include "sysutils.h"
22 #include "urlutils.h"
23 
24 
25 USING_PTYPES
26 
27 
28 enum http_version_t {
29     HTTP_VER_09,
30     HTTP_VER_10,
31     HTTP_VER_11,
32     HTTP_VER_UNKNOWN,
33         HTTP_VER_MAX
34 };
35 
36 
37 enum http_method_t {
38     HTTP_GET,
39     HTTP_HEAD,
40     HTTP_OTHER,
41         HTTP_METHOD_MAX
42 };
43 
44 
45 enum req_stat_t
46 {
47     STAT_READ,
48     STAT_WRITE,
49     STAT_WAIT,
50         STAT_MAX
51 };
52 
53 
54 struct ehttp
55 {
56     int code;
ehttpehttp57     ehttp(int icode): code(icode) {}
58 };
59 
60 
61 class request_rec
62 {
63 public:
64     datetime        started;
65     int             rsp_code;       // rsp: response code, set through begin_response(), used for logging
66     req_stat_t      stat;           // for status requests: READ, WRITE or WAIT (if keep-alive)
67     instm*          sockin;         // client input stream
68     outstm*         sockout;        // client output stream
69     ipaddress       client_ip;      // req: client's IP
70     http_version_t  version;        // req/rsp: HTTP version, 0.9, 1.0, 1.1 or 1.*
71     http_method_t   method;         // req: HTTP method, currently GET or HEAD
72     string          method_str;     // method string, for other method handlers
73     bool            keep_alive;     // req/rsp: whether to close the connection; determined
74                                     // based on the HTTP version and the "Connection:" header;
75                                     // can be forced to false for some response types, e.g. 400 Bad Request
76     datetime        if_modified;    // req: "If-modified-since:" if present, invdatetime otherwise
77     string          req_line;       // req: the whole request line, e.g. "GET / HTTP/1.1"
78     string          uri;            // req: request-URI, as is
79     string          host;           // req: "Host:" header, if present
80     string          referer;        // req: "Referer:"; may be converted to relative URI
81     bool            partial;        // req: partial content requested (see rsp_file())
82     large           range_min;      // req: partial content
83     large           range_max;      // req: partial content
84     textmap         headers;        // other headers
85 
86     // requested object info
87     urlrec          url;            // req: the request-URI parsed and split into components
88     strlist         path_parts;     // request-URI path split into components
89 
90     unknown*        user;           // user data for custom handlers, freed automatically by ~request_rec()
91 
92     // helpers for method handlers
93     string get_token(const cset& chars);
94     string get_uri();
95     void parse_request_line();      // ... excluding the method string
96     void parse_hdr(string& fname, string& fvalue);
97     void parse_uri();               // sets url and path_parts fields
98     void analyze_uri();             // sets all fields starting from file_type
99 
100     // response utilities; headers are not sent if the HTTP version is 0.9
101     void begin_response(int code, const char* msg);
102 
103     void put_header(const char* name, const char* value);
104     void put_header(const char* name, const string& value);
105     void put_content_type(const char* mime);
106     void put_content_length(large length);
107     void end_headers();
108     void std_response(bool conn_close, int code, const char* msg, const char* descr);
109     void std_response(bool conn_close, int code, const char* msg, const char* descr, const string& dparam);
110 
111     // standard responses; all functions of this group raise ehttp exceptions
112     void rsp_not_found();
113     void rsp_bad_request();
114     void rsp_bad_method(const char* ok_methods);
115     void rsp_uri_too_long();
116     void rsp_forbidden();
117     void rsp_dir_index_forbidden();
118     void rsp_overloaded();
119     void abort_request();
120     void rsp_redirect(const string& newurl);
121     void rsp_not_modified();
122 
123     void end_response();
124 
125 protected:
126     string location;       // rsp: add "Location:" header to the response; set through
127                            // rsp_redirect()
128     int    hdr_size;       // byte size of response headers; used for logging, to determine
129                            // the actual response content length (see respond())
130 
131     // request parsers
132     void parse_method();
133     void parse_headers();
134 
135     // the boss
136     void respond();
137 
138     // reset the state between requests when keep-alive
139     void reset_state();
140 
141     request_rec(instm& isockin, outstm& isockout, ipaddress iclient_ip);
142     ~request_rec();
143 };
144 
145 
146 // this structure is created and handled in mod_file, however, we
147 // declare it here since this information can be passed to the
148 // file extension handlers.
149 
150 class file_request_rec
151 {
152 public:
153     file_type_t     file_type;      // file, directory or other (device or pipe)
154     bool            sym_link;       // the object is a symbolic link (Unix only)
155     bool            executable;     // the object is executable (binary on Unix, .exe on Windows)
156     string          abs_path;       // absolute file path to the requested object
157     string          rel_path;       // file path to the requested object relative to document root,
158                                     // may not be the same as url.path
159     string          file_name;      // file name
160     string          file_ext;       // file extension, including the leading dot
161 
file_request_rec()162     file_request_rec(): file_type(FT_ERROR), sym_link(false), executable(false),
163         abs_path(), rel_path(), file_name(), file_ext()  {}
~file_request_rec()164     ~file_request_rec()  {}
165 };
166 
167 
168 #endif
169