//作者:京东瀚览家居官方旗舰店 <--点击关注
//文件名:Response.c
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <ctype.h>
#include <assert.h>
#include <stdio.h>
#include "response.h"
#include "keyvalue.h"
#include "log.h"
#include "stat_cache.h"
#include "chunk.h"
#include "configfile.h"
#include "connections.h"
#include "plugin.h"
#include "sys-socket.h"
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));
if (con->request.http_version != HTTP_VERSION_1_1 || con->keep_alive == 0) {
buffer_append_string_len(b, CONST_STR_LEN("\r\nConnection: "));
if (con->keep_alive) {
buffer_append_string_len(b, CONST_STR_LEN("keep-alive"));
} else {
buffer_append_string_len(b, CONST_STR_LEN("close"));
}
}
if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
buffer_append_string_len(b, CONST_STR_LEN("\r\nTransfer-Encoding: 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 != strcasecmp(ds->key->ptr, "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_NAME "/" PACKAGE_VERSION));
} 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);
}
}
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;
}
/* 调用插件处理请求*/
handler_t http_response_prepare(server *srv, connection *con) {
handler_t r;
/* looks like someone has already done a decision */
/* 该请求被处理, 直接返回*/
if (con->mode == DIRECT &&
(con->http_status != 0 && con->http_status != 200)) {
/* remove a packets in the queue */
if (con->file_finished == 0) {
chunkqueue_rese