|
|
| version 1.9, 2020/11/12 16:16:01 | version 1.20, 2024/11/09 15:38:21 |
|---|---|
| Line 8 | Line 8 |
| /// IIS refuses to read bigger chunks | /// IIS refuses to read bigger chunks |
| const size_t READ_POST_CHUNK_SIZE=0x400*0x400; // 1M | const size_t READ_POST_CHUNK_SIZE=0x400*0x400; // 1M |
| const int HEADERS_SENT = 999; // can't send error message after headers have been sent | |
| // for signal handlers and cgi console detection | |
| static Request *request=0; | |
| class SAPI_Info : public PA_Allocated { | class SAPI_Info : public PA_Allocated { |
| public: | public: |
| int http_response_code; | int http_response_code; |
| String::Body headers; | |
| SAPI_Info() : http_response_code(200) {} | SAPI_Info() : http_response_code(200) {} |
| Line 22 public: | Line 28 public: |
| return 0; | return 0; |
| } | } |
| virtual bool set_env(const char* name, const char* value) { | virtual bool set_env(const char*, const char*) { |
| return false; | return false; |
| } | } |
| Line 40 public: | Line 46 public: |
| return 0; | return 0; |
| } | } |
| virtual void add_header_attribute(const char* dont_store_key, const char* dont_store_value) { | virtual void add_header(const char* dont_store_key, const char* dont_store_value) { |
| if(strcasecmp(dont_store_key, "location")==0) | |
| http_response_code=302; | |
| if(strcasecmp(dont_store_key, HTTP_STATUS)==0) | if(strcasecmp(dont_store_key, HTTP_STATUS)==0) |
| http_response_code=atoi(dont_store_value); | http_response_code=atoi(dont_store_value); |
| } | } |
| virtual void send_header() {} | virtual void send_headers() {} |
| virtual size_t send_body(const void *buf, size_t size) { | virtual size_t send_body(const void *buf, size_t size) { |
| return stdout_write(buf, size); | return stdout_write(buf, size); |
| } | } |
| } *sapiInfo = NULL; | virtual void send_error(const char *exception_cstr, const char *status){ |
| http_response_code=atoi(status); | |
| send_body(exception_cstr, strlen(exception_cstr)); | |
| } | |
| }; | |
| class SAPI_Info_CGI : public SAPI_Info { | class SAPI_Info_CGI : public SAPI_Info { |
| public: | public: |
| Line 67 public: | Line 79 public: |
| return read_size; | return read_size; |
| } | } |
| virtual void add_header_attribute(const char* dont_store_key, const char* dont_store_value) { | virtual void add_header(const char* dont_store_key, const char* dont_store_value) { |
| SAPI_Info::add_header_attribute(dont_store_key, dont_store_value); | headers << capitalize(dont_store_key) << ": " << pa_strdup(dont_store_value) << "\r\n"; |
| // if(!request || !request->console.was_used()) | |
| printf("%s: %s\n", capitalize(dont_store_key), dont_store_value); | |
| } | } |
| virtual void send_header() { | virtual void send_headers() { |
| puts(""); | if(!request || !request->console.was_used()){ |
| headers << "\r\n"; | |
| send_body(headers.cstr(), headers.length()); | |
| http_response_code=HEADERS_SENT; | |
| } | |
| } | } |
| virtual void send_error(const char *exception_cstr, const char *status){ | |
| if (http_response_code==HEADERS_SENT) | |
| return; | |
| // memory allocation is not allowed | |
| char buf[MAX_STRING]; | |
| snprintf(buf, MAX_STRING, HTTP_STATUS_CAPITALIZED ": %s\r\n" | |
| HTTP_CONTENT_TYPE_CAPITALIZED ": text/plain\r\n\r\n", status); | |
| send_body(buf, strlen(buf)); | |
| send_body(exception_cstr, strlen(exception_cstr)); | |
| } | |
| }; | }; |
| char* replace_char(char* str, char from, char to){ | static char* replace_char(char* str, char from, char to){ |
| for(char *pos = strchr(str,from); pos; pos=strchr(pos,from)) { | for(char *pos = strchr(str,from); pos; pos=strchr(pos,from)) { |
| *pos = to; | *pos = to; |
| } | } |
| Line 91 class SAPI_Info_HTTPD : public SAPI_Info | Line 115 class SAPI_Info_HTTPD : public SAPI_Info |
| public: | public: |
| HTTPD_Connection &connection; | HTTPD_Connection &connection; |
| String output; | |
| HashStringString env; | HashStringString env; |
| SAPI_Info_HTTPD(HTTPD_Connection &aconnection) : connection(aconnection) {} | SAPI_Info_HTTPD(HTTPD_Connection &aconnection) : connection(aconnection) {} |
| void populate_env() { | void populate_env() { |
| String::Body host("localhost"); | String::Body host("localhost"); |
| for(Array_iterator<HTTP_Headers::Header> i(connection.headers()); i.has_next(); ){ | for(Array_iterator<HTTP_Headers::Header> i(connection.headers()); i; ){ |
| HTTP_Headers::Header header=i.next(); | HTTP_Headers::Header header=i.next(); |
| String name("HTTP_"); | String name("HTTP_"); |
| name << replace_char(header.name.cstrm(), '-', '_'); | name << replace_char(header.name.cstrm(), '-', '_'); |
| Line 118 public: | Line 141 public: |
| env.put("QUERY_STRING", connection.query()); | env.put("QUERY_STRING", connection.query()); |
| env.put("SERVER_NAME", host); | env.put("SERVER_NAME", host); |
| env.put("SERVER_PORT", HTTPD_Server::port); | |
| env.put("REMOTE_ADDR", connection.remote_addr); | env.put("REMOTE_ADDR", connection.remote_addr); |
| } | } |
| virtual char* get_env(const char* name) { | virtual char* get_env(const char* name) { |
| String::Body value = env.get(name); | String::Body request_value = env.get(name); |
| return !value ? NULL : value.cstrm(); | if(!request_value.is_empty()) |
| return request_value.cstrm(); | |
| if(char *server_value=getenv(name)) | |
| return pa_strdup(server_value); | |
| return NULL; | |
| } | } |
| virtual bool set_env(const char* name, const char* value) { | virtual bool set_env(const char* name, const char* value) { |
| Line 148 public: | Line 176 public: |
| return connection.read_post(buf, max_bytes); | return connection.read_post(buf, max_bytes); |
| } | } |
| virtual void add_header_attribute(const char* dont_store_key, const char* dont_store_value) { | |
| if(strcasecmp(dont_store_key, "location")==0) | |
| http_response_code=302; | |
| if(strcasecmp(dont_store_key, HTTP_STATUS)==0) | |
| http_response_code=atoi(dont_store_value); | |
| else | |
| output << capitalize(dont_store_key) << ": " << pa_strdup(dont_store_value) << "\r\n"; | |
| } | |
| static const char *exception_http_status(const char *type) { | static const char *exception_http_status(const char *type) { |
| struct Lookup { | struct Lookup { |
| const char *code; | const char *code; |
| const char *type; | const char *type; |
| } static lookup[] = { | } static lookup[] = { |
| { "", "httpd.write"}, | |
| {"400", "httpd.request"}, | {"400", "httpd.request"}, |
| {"400", "http.response"}, | {"400", "http.response"}, |
| {"404", "file.missing"}, | {"404", "file.missing"}, |
| {"408", "httpd.timeout"}, | {"408", "httpd.timeout"}, |
| {"408", "httpd.read"}, | |
| {"501", "httpd.method"}, | {"501", "httpd.method"}, |
| { NULL, ""} | { NULL, ""} |
| }; | }; |
| Line 182 public: | Line 203 public: |
| const char *message; | const char *message; |
| } static lookup[] = { | } static lookup[] = { |
| {200, "OK"}, | {200, "OK"}, |
| {204, "No Content"}, | |
| {206, "Partial Content"}, | {206, "Partial Content"}, |
| {301, "Moved Permanently"}, | {301, "Moved Permanently"}, |
| {302, "Found"}, | {302, "Found"}, |
| Line 191 public: | Line 213 public: |
| {403, "Forbidden"}, | {403, "Forbidden"}, |
| {404, "Not Found"}, | {404, "Not Found"}, |
| {408, "Request Timeout"}, | {408, "Request Timeout"}, |
| {416, "Range Not Satisfiable"}, | |
| {500, "Internal Server Error"}, | {500, "Internal Server Error"}, |
| {501, "Not Implemented"}, | {501, "Not Implemented"}, |
| {502, "Bad Gateway"}, | {502, "Bad Gateway"}, |
| Line 204 public: | Line 227 public: |
| return cur->message; | return cur->message; |
| } | } |
| virtual void send_header() { | virtual void add_header(const char* dont_store_key, const char* dont_store_value) { |
| if(strcasecmp(dont_store_key, "location")==0) | |
| http_response_code=302; | |
| if(strcasecmp(dont_store_key, HTTP_STATUS)==0) | |
| http_response_code=atoi(dont_store_value); | |
| else | |
| headers << capitalize(dont_store_key) << ": " << pa_strdup(dont_store_value) << "\r\n"; | |
| } | |
| virtual void send_headers() { | |
| String result("HTTP/1.0 "); | String result("HTTP/1.0 "); |
| result << String::Body::Format(http_response_code) << " " << status_message(http_response_code) << "\r\n" << output << "\r\n"; | result << pa_uitoa(http_response_code) << " " << status_message(http_response_code) << "\r\n" << headers << "\r\n"; |
| send_body(result.cstr(), result.length()); | send_body(result.cstr(), result.length()); |
| http_response_code=HEADERS_SENT; | |
| } | } |
| virtual size_t send_body(const void *buf, size_t size) { | virtual size_t send_body(const void *buf, size_t size) { |
| return connection.send_body(buf, size); | return connection.send_body(buf, size); |
| } | } |
| virtual void send_error(const char *exception_cstr, const char *status){ | |
| if (http_response_code==HEADERS_SENT) | |
| return; | |
| // memory allocation is not allowed | |
| char buf[MAX_STRING]; | |
| snprintf(buf, MAX_STRING, "HTTP/1.0 %s %s\r\n" | |
| HTTP_CONTENT_TYPE_CAPITALIZED ": text/plain\r\n\r\n", status, status_message(atoi(status))); | |
| send_body(buf, strlen(buf)); | |
| send_body(exception_cstr, strlen(exception_cstr)); | |
| } | |
| }; | }; |
| #endif | #endif |