123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339 |
- static void
- free_buffered_response_header_list(struct mg_connection *conn)
- {
- while (conn->response_info.num_headers > 0) {
- conn->response_info.num_headers--;
- mg_free((void *)conn->response_info
- .http_headers[conn->response_info.num_headers]
- .name);
- conn->response_info.http_headers[conn->response_info.num_headers].name =
- 0;
- mg_free((void *)conn->response_info
- .http_headers[conn->response_info.num_headers]
- .value);
- conn->response_info.http_headers[conn->response_info.num_headers]
- .value = 0;
- }
- (void)conn;
- }
- static int
- send_http1_response_status_line(struct mg_connection *conn)
- {
- const char *status_txt;
- const char *http_version = conn->request_info.http_version;
- int status_code = conn->status_code;
- if ((status_code < 100) || (status_code > 999)) {
-
- status_code = 500;
- }
- if (!http_version) {
- http_version = "1.0";
- }
-
- status_txt = mg_get_response_code_text(conn, conn->status_code);
- if (mg_printf(
- conn, "HTTP/%s %i %s\r\n", http_version, status_code, status_txt)
- < 10) {
-
- return 0;
- }
- return 1;
- }
- int
- mg_response_header_start(struct mg_connection *conn, int status)
- {
- int ret = 0;
- if ((conn == NULL) || (status < 100) || (status > 999)) {
-
- return -1;
- }
- if ((conn->connection_type != CONNECTION_TYPE_REQUEST)
- || (conn->protocol_type == PROTOCOL_TYPE_WEBSOCKET)) {
-
- return -2;
- }
- if (conn->request_state != 0) {
-
- return -3;
- }
- conn->status_code = status;
- conn->request_state = 1;
-
- free_buffered_response_header_list(conn);
- if (!send_http1_response_status_line(conn)) {
- ret = -4;
- };
- conn->request_state = 1;
- return ret;
- }
- int
- mg_response_header_add(struct mg_connection *conn,
- const char *header,
- const char *value,
- int value_len)
- {
- int hidx;
- if ((conn == NULL) || (header == NULL) || (value == NULL)) {
-
- return -1;
- }
- if ((conn->connection_type != CONNECTION_TYPE_REQUEST)
- || (conn->protocol_type == PROTOCOL_TYPE_WEBSOCKET)) {
-
- return -2;
- }
- if (conn->request_state != 1) {
-
- return -3;
- }
- hidx = conn->response_info.num_headers;
- if (hidx >= MG_MAX_HEADERS) {
-
- return -4;
- }
-
- conn->response_info.http_headers[hidx].name =
- mg_strdup_ctx(header, conn->phys_ctx);
- if (value_len >= 0) {
- char *hbuf =
- (char *)mg_malloc_ctx((unsigned)value_len + 1, conn->phys_ctx);
- if (hbuf) {
- memcpy(hbuf, value, (unsigned)value_len);
- hbuf[value_len] = 0;
- }
- conn->response_info.http_headers[hidx].value = hbuf;
- } else {
- conn->response_info.http_headers[hidx].value =
- mg_strdup_ctx(value, conn->phys_ctx);
- }
- if ((conn->response_info.http_headers[hidx].name == 0)
- || (conn->response_info.http_headers[hidx].value == 0)) {
-
- mg_free((void *)conn->response_info.http_headers[hidx].name);
- conn->response_info.http_headers[hidx].name = 0;
- mg_free((void *)conn->response_info.http_headers[hidx].value);
- conn->response_info.http_headers[hidx].value = 0;
- return -5;
- }
-
- conn->response_info.num_headers++;
- if (value_len >= 0) {
- mg_printf(conn, "%s: %.*s\r\n", header, (int)value_len, value);
- } else {
- mg_printf(conn, "%s: %s\r\n", header, value);
- }
- conn->request_state = 1;
- return 0;
- }
- static int parse_http_headers(char **buf, struct mg_header hdr[MG_MAX_HEADERS]);
- int
- mg_response_header_add_lines(struct mg_connection *conn,
- const char *http1_headers)
- {
- struct mg_header add_hdr[MG_MAX_HEADERS];
- int num_hdr, i, ret;
- char *workbuffer, *parse;
-
- workbuffer = mg_strdup_ctx(http1_headers, conn->phys_ctx);
- if (!workbuffer) {
-
- return -5;
- }
-
- parse = workbuffer;
- num_hdr = parse_http_headers(&parse, add_hdr);
- ret = num_hdr;
- for (i = 0; i < num_hdr; i++) {
- int lret =
- mg_response_header_add(conn, add_hdr[i].name, add_hdr[i].value, -1);
- if ((ret > 0) && (lret < 0)) {
-
- ret = lret;
- }
- }
-
- mg_free(workbuffer);
- return ret;
- }
- static int http2_send_response_headers(struct mg_connection *conn);
- int
- mg_response_header_send(struct mg_connection *conn)
- {
- int i;
- int has_date = 0;
- int has_connection = 0;
- if (conn == NULL) {
-
- return -1;
- }
- if ((conn->connection_type != CONNECTION_TYPE_REQUEST)
- || (conn->protocol_type == PROTOCOL_TYPE_WEBSOCKET)) {
-
- return -2;
- }
- if (conn->request_state != 1) {
-
- return -3;
- }
-
- conn->request_state = 2;
- if (conn->protocol_type == PROTOCOL_TYPE_HTTP2) {
- int ret = http2_send_response_headers(conn);
- return (ret ? 0 : -4);
- }
-
- if (!send_http1_response_status_line(conn)) {
- return -4;
- };
- for (i = 0; i < conn->response_info.num_headers; i++) {
- mg_printf(conn,
- "%s: %s\r\n",
- conn->response_info.http_headers[i].name,
- conn->response_info.http_headers[i].value);
-
- if (!mg_strcasecmp("Date", conn->response_info.http_headers[i].name)) {
- has_date = 1;
- }
- if (!mg_strcasecmp("Connection",
- conn->response_info.http_headers[i].name)) {
- has_connection = 1;
- }
- }
- if (!has_date) {
- time_t curtime = time(NULL);
- char date[64];
- gmt_time_string(date, sizeof(date), &curtime);
- mg_printf(conn, "Date: %s\r\n", date);
- }
- if (!has_connection) {
- mg_printf(conn, "Connection: %s\r\n", suggest_connection_header(conn));
- }
- mg_write(conn, "\r\n", 2);
- conn->request_state = 3;
-
- return 0;
- }
|