int http_response_write_header(server *srv, connection *con) { buffer *b; size_t i; int have_date = 0; int have_server = 0; b = chunkqueue_get_prepend_buffer(con->write_queue); if (con->request.http_version == HTTP_VERSION_1_1) { buffer_copy_string_len(b, CONST_STR_LEN("HTTP/1.1 ")); } else { buffer_copy_string_len(b, CONST_STR_LEN("HTTP/1.0 ")); } buffer_append_long(b, con->http_status); buffer_append_string_len(b, CONST_STR_LEN(" ")); buffer_append_string(b, get_http_status_name(con->http_status)); /* disable keep-alive if requested */ if (con->request_count > con->conf.max_keep_alive_requests || 0 == con->conf.max_keep_alive_idle) { con->keep_alive = 0; } else { con->keep_alive_idle = con->conf.max_keep_alive_idle; } if (con->request.http_version != HTTP_VERSION_1_1 || con->keep_alive == 0) { if (con->keep_alive) { response_header_overwrite(srv, con, CONST_STR_LEN("Connection"), CONST_STR_LEN("keep-alive")); } else { response_header_overwrite(srv, con, CONST_STR_LEN("Connection"), CONST_STR_LEN("close")); } } if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) { response_header_overwrite(srv, con, CONST_STR_LEN("Transfer-Encoding"), CONST_STR_LEN("chunked")); } /* add all headers */ for (i = 0; i < con->response.headers->used; i++) { data_string *ds; ds = (data_string *)con->response.headers->data[i]; if (ds->value->used && ds->key->used && 0 != strncasecmp(ds->key->ptr, CONST_STR_LEN("X-LIGHTTPD-")) && 0 != strncasecmp(ds->key->ptr, CONST_STR_LEN("X-Sendfile"))) { if (0 == strcasecmp(ds->key->ptr, "Date")) have_date = 1; if (0 == strcasecmp(ds->key->ptr, "Server")) have_server = 1; if (0 == strcasecmp(ds->key->ptr, "Content-Encoding") && 304 == con->http_status) continue; buffer_append_string_len(b, CONST_STR_LEN("\r\n")); buffer_append_string_buffer(b, ds->key); buffer_append_string_len(b, CONST_STR_LEN(": ")); #if 0 /** * the value might contain newlines, encode them with at least one white-space */ buffer_append_string_encoded(b, CONST_BUF_LEN(ds->value), ENCODING_HTTP_HEADER); #else buffer_append_string_buffer(b, ds->value); #endif } } if (!have_date) { /* HTTP/1.1 requires a Date: header */ buffer_append_string_len(b, CONST_STR_LEN("\r\nDate: ")); /* cache the generated timestamp */ if (srv->cur_ts != srv->last_generated_date_ts) { buffer_prepare_copy(srv->ts_date_str, 255); strftime(srv->ts_date_str->ptr, srv->ts_date_str->size - 1, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(srv->cur_ts))); srv->ts_date_str->used = strlen(srv->ts_date_str->ptr) + 1; srv->last_generated_date_ts = srv->cur_ts; } buffer_append_string_buffer(b, srv->ts_date_str); } if (!have_server) { if (buffer_is_empty(con->conf.server_tag)) { buffer_append_string_len(b, CONST_STR_LEN("\r\nServer: " PACKAGE_DESC)); } else if (con->conf.server_tag->used > 1) { buffer_append_string_len(b, CONST_STR_LEN("\r\nServer: ")); buffer_append_string_encoded(b, CONST_BUF_LEN(con->conf.server_tag), ENCODING_HTTP_HEADER); } } //- Jerry add 20110923 #if EMBEDDED_EANBLE char * ddns_host_n = nvram_get_ddns_host_name(); if(ddns_host_n){ buffer_append_string_len(b, CONST_STR_LEN("\r\nDDNS: ")); buffer_append_string(b, ddns_host_n); }else #endif buffer_append_string_len(b, CONST_STR_LEN("\r\nDDNS: ")); buffer_append_string_len(b, CONST_STR_LEN("\r\n\r\n")); con->bytes_header = b->used - 1; if (con->conf.log_response_header) { log_error_write(srv, __FILE__, __LINE__, "sSb", "Response-Header:", "\n", b); } return 0; }
int http_response_finish_header(server *srv, connection *con) { if (NULL == srv || NULL == con || NULL == con -> write_queue) { return -1; } /* * 这个header有安全问题。通产默认不添加。 */ //http_response_insert_header(srv, con, CONST_STR_LEN("Server"), CONST_STR_LEN("Swiftd/0.1 written by hcy")); buffer *b = chunkqueue_get_prepend_buffer(con -> write_queue); if (NULL == b) { log_error_write(srv, __FILE__, __LINE__, "s", "chunkqueue_get_prepend_buffer failed."); return -1; } buffer_reset(b); /* * Status-Line: * HTTP-Version SP Status-Code SP Reason-Phrase CRLF */ buffer_copy_string_len(b, CONST_STR_LEN("HTTP/1.1")); buffer_append_string_len(b, CONST_STR_LEN(" ")); //SP buffer_append_long(b, con -> http_status); buffer_append_string_len(b, CONST_STR_LEN(" ")); //SP buffer_append_string(b, get_http_status_name(con -> http_status)); buffer_append_string_len(b, CONST_STR_LEN(CRLF)); //CRLF = '\r\n' defined in base.h if(con -> keep_alive) { http_response_insert_header(srv, con, CONST_STR_LEN("Connection") , CONST_STR_LEN("keep-alive")); } else { http_response_insert_header(srv, con, CONST_STR_LEN("Connection") , CONST_STR_LEN("close")); } /* * Headers: * Key:Value CRLF */ size_t i; data_string *ds; for (i = 0; i < con -> response.headers -> used; ++i) { ds = (data_string *)con -> response.headers -> data[i]; if (NULL == ds) { continue; } buffer_append_string_buffer(b, ds -> key); buffer_append_string_len(b, CONST_STR_LEN(": ")); buffer_append_string_buffer(b, ds -> value); buffer_append_string_len(b, CONST_STR_LEN(CRLF)); } /* * header 和 message body之间的CRLF。 */ buffer_append_string_len(b, CONST_STR_LEN(CRLF)); /* * 最后一个'\0'不能发送出去!! */ -- b -> used; log_error_write(srv, __FILE__, __LINE__, "sb", "Response Headers:", b); array_reset(con -> response.headers); return 0; }