static BOOL SendResponseHeaderEx(isapi_cid *cid, const char *stat, const char *head, DWORD statlen, DWORD headlen) { int termarg; char *termch; if (!stat || statlen == 0 || !*stat) { stat = "Status: 200 OK"; } else { char *newstat; newstat = ap_palloc(cid->r->pool, statlen + 9); strcpy(newstat, "Status: "); ap_cpystrn(newstat + 8, stat, statlen + 1); stat = newstat; } if (!head || headlen == 0 || !*head) { head = "\r\n"; } else { if (head[headlen]) { /* Whoops... not NULL terminated */ head = ap_pstrndup(cid->r->pool, head, headlen); } } /* Parse them out, or die trying */ cid->status = ap_scan_script_header_err_strs(cid->r, NULL, &termch, &termarg, stat, head, NULL); cid->ecb->dwHttpStatusCode = cid->r->status; /* All the headers should be set now */ ap_send_http_header(cid->r); /* Any data left should now be sent directly, * it may be raw if headlen was provided. */ if (termch && (termarg == 1)) { if (headlen == -1 && *termch) ap_rputs(termch, cid->r); else if (headlen > (size_t) (termch - head)) ap_rwrite(termch, headlen - (termch - head), cid->r); } if (cid->status == HTTP_INTERNAL_SERVER_ERROR) return FALSE; return TRUE; }
/* copied from mod_cgi.c and slightly modified * to work with fcgi_record types */ static int fcgi_server_parse_headers(fcgi_request_t *fr, uint16_t request_id, char **data) { request_rec *r = fr->r; int ret, termarg; if ((ret = ap_scan_script_header_err_strs(r, NULL, (const char **)data, &termarg, *data, NULL))) { /* * ret could be HTTP_NOT_MODIFIED in the case that the CGI script * does not set an explicit status and ap_meets_conditions, which * is called by ap_scan_script_header_err_brigade, detects that * the conditions of the requests are met and the response is * not modified. * In this case set r->status and return OK in order to prevent * running through the error processing stack as this would * break with mod_cache, if the conditions had been set by * mod_cache itself to validate a stale entity. * BTW: We circumvent the error processing stack anyway if the * CGI script set an explicit status code (whatever it is) and * the only possible values for ret here are: * * HTTP_NOT_MODIFIED (set by ap_meets_conditions) * HTTP_PRECONDITION_FAILED (set by ap_meets_conditions) * HTTP_INTERNAL_SERVER_ERROR (if something went wrong during the * processing of the response of the CGI script, e.g broken headers * or a crashed CGI process). */ if (ret == HTTP_NOT_MODIFIED) { r->status = ret; return OK; } return ret; } const char *location = apr_table_get(r->headers_out, "Location"); #if 0 if (location && r->status == 200) { /* For a redirect whether internal or not, discard any * remaining stdout from the script, and log any remaining * stderr output, as normal. */ discard_script_output(bb); apr_brigade_destroy(bb); apr_file_pipe_timeout_set(script_err, r->server->timeout); log_script_err(r, script_err); } #endif if (location && location[0] == '/' && r->status == 200) { /* This redirect needs to be a GET no matter what the original * method was. */ r->method = apr_pstrdup(r->pool, "GET"); r->method_number = M_GET; /* We already read the message body (if any), so don't allow * the redirected request to think it has one. We can ignore * Transfer-Encoding, since we used REQUEST_CHUNKED_ERROR. */ apr_table_unset(r->headers_in, "Content-Length"); ap_internal_redirect_handler(location, r); return OK; } else if (location && r->status == 200) { /* XX Note that if a script wants to produce its own Redirect * body, it now has to explicitly *say* "Status: 302" */ return HTTP_MOVED_TEMPORARILY; } }