Annotation of parser3/src/targets/cgi/pa_sapi_info.h, revision 1.2
1.1 moko 1: #ifndef PA_SAPI_INFO_H
2: #define PA_SAPI_INFO_H
3:
1.2 ! moko 4: #define IDENT_PA_SAPI_INFO_H "$Id: pa_sapi_info.h,v 1.1 2020/10/10 06:08:37 moko Exp $"
1.1 moko 5:
6: #include "pa_sapi.h"
7: #include "pa_http.h"
8:
9: /// IIS refuses to read bigger chunks
10: const size_t READ_POST_CHUNK_SIZE=0x400*0x400; // 1M
11:
12: class SAPI_Info : public PA_Allocated {
13: public:
14: int http_response_code;
15:
16: SAPI_Info() : http_response_code(0) {}
17:
18: virtual char* get_env(const char* name) {
19: if(char *local=getenv(name))
20: return pa_strdup(local);
21: else
22: return 0;
23: }
24:
25: virtual const char* const *get_env() {
26: #ifdef _MSC_VER
27: extern char **_environ;
28: return _environ;
29: #else
30: extern char **environ;
31: return environ;
32: #endif
33: }
34:
35: virtual size_t read_post(char *, size_t) {
36: return 0;
37: }
38:
39: virtual void add_header_attribute(const char* dont_store_key, const char* dont_store_value) {
40: if(strcasecmp(dont_store_key, HTTP_STATUS)==0)
41: http_response_code=atoi(dont_store_value);
42: }
43:
44: virtual void send_header() {}
45:
46: virtual size_t send_body(const void *buf, size_t size) {
47: return stdout_write(buf, size);
48: }
49:
50: virtual void die(const char *content, int content_length) {
51: stdout_write(content, content_length);
52: }
53:
54: } *sapiInfo = NULL;
55:
56: class SAPI_Info_CGI : public SAPI_Info {
57: public:
58:
59: virtual size_t read_post(char *buf, size_t max_bytes) {
60: size_t read_size=0;
61: do {
62: ssize_t chunk_size=read(fileno(stdin), buf+read_size, min(READ_POST_CHUNK_SIZE, max_bytes-read_size));
63: if(chunk_size<=0)
64: break;
65: read_size+=chunk_size;
66: } while(read_size<max_bytes);
67: return read_size;
68: }
69:
70: virtual void add_header_attribute(const char* dont_store_key, const char* dont_store_value) {
71: SAPI_Info::add_header_attribute(dont_store_key, dont_store_value);
72: // if(!request || !request->console.was_used())
73: printf("%s: %s\n", capitalize(dont_store_key), dont_store_value);
74: }
75:
76: virtual void send_header() {
77: puts("");
78: }
79:
80: virtual void die(const char *content, int content_length) {
81: // prepare header
82: // let's be honest, that's bad we couldn't produce valid output
83: // capitalized headers passed for preventing malloc during capitalization
84: add_header_attribute(HTTP_STATUS_CAPITALIZED, "500");
85: add_header_attribute(HTTP_CONTENT_TYPE_CAPITALIZED, "text/plain");
86: // don't use 'format' function because it calls malloc
87: char content_length_cstr[MAX_NUMBER];
88: snprintf(content_length_cstr, sizeof(content_length_cstr), "%u", content_length);
89: add_header_attribute(HTTP_CONTENT_LENGTH_CAPITALIZED, content_length_cstr);
90:
91: // send header
92: send_header();
93: // body
94: send_body(content, content_length);
95: }
96:
97: };
98:
99: class SAPI_Info_HTTPD : public SAPI_Info {
100: public:
101:
102: HTTPD_Connection &connection;
103: String output;
104:
105: SAPI_Info_HTTPD(HTTPD_Connection &aconnection) : connection(aconnection) {}
106:
107: virtual char* get_env(const char* name) {
1.2 ! moko 108: for(Array_iterator<HTTP_Headers::Header> i(connection.headers()); i.has_next(); ){
! 109: HTTP_Headers::Header header=i.next();
1.1 moko 110: if(!strcmp(name, header.name.cstr()))
111: return header.value.cstrm();
112: }
113: return NULL;
114: }
115:
116: static const char* mk_env_pair(const char* key, const char* value) {
117: char *result=new(PointerFreeGC) char[5 /*HTTP_*/ + strlen(key) + 1 /*=*/ + strlen(value) + 1 /*0*/];
118: strcpy(result, "HTTP_"); strcat(result, key); strcat(result, "="); strcat(result, value);
119: return result;
120: }
121:
122: virtual const char* const *get_env() {
123: const char** result=new(PointerGC) const char*[connection.headers().count()+1/*0*/];
124: const char** cur=result;
1.2 ! moko 125: for(Array_iterator<HTTP_Headers::Header> i(connection.headers()); i.has_next(); ){
! 126: HTTP_Headers::Header header=i.next();
1.1 moko 127: *cur++=mk_env_pair(header.name.cstr(), header.value.cstr());
128: }
129: *cur=NULL;
130: return result;
131: }
132:
133: virtual size_t read_post(char *, size_t) {
134: return 0;
135: }
136:
137: virtual void add_header_attribute(const char* dont_store_key, const char* dont_store_value) {
138: if(strcasecmp(dont_store_key, "location")==0)
139: http_response_code=302;
140: if(strcasecmp(dont_store_key, HTTP_STATUS)==0)
141: http_response_code=atoi(dont_store_value);
142: else
143: output << capitalize(dont_store_key) << ": " << pa_strdup(dont_store_value) << "\r\n";
144: }
145:
146: static const char *message(int code) {
147: struct Lookup {
148: int code;
149: const char *message;
150: } static lookup[] = {
151: {200, "OK"},
152: {206, "Partial Content"},
153: {301, "Moved Permanently"},
154: {302, "Found"},
155: {400, "Bad Request"},
156: {401, "Unauthorized"},
157: {403, "Forbidden"},
158: {404, "Not Found"},
159: {500, "Internal Server Error"},
160: {501, "Not Implemented"},
161: {502, "Bad Gateway"},
162: {504, "Gateway Timeout"},
163: { 0, "Undescribed"}
164: };
165: Lookup *cur = lookup;
166: for(; cur->code; cur++)
167: if(code == cur->code)
168: return cur->message;
169: return cur->message;
170: }
171:
172: virtual void send_header() {
173: String result("HTTP/1.0 ");
174: result << String::Body::Format(http_response_code) << " " << message(http_response_code) << "\r\n" << output << "\r\n";
175: send_body(result.cstr(), result.length());
176: }
177:
178: virtual size_t send_body(const void *buf, size_t size) {
179: if(send(connection.sock, buf, size, 0)!=(ssize_t)size) {
180: int no=pa_socks_errno();
181: throw Exception("httpd.timeout", 0, "error sending response: %s (%d)", pa_socks_strerr(no), no);
182: }
183: return size;
184: }
185:
186: };
187:
188: #endif
E-mail: