1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
5 * Copyright (C) 2001-2010, Eduardo Silva P. <edsiper@gmail.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Library General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
31 #include "http_status.h"
40 int mk_header_iov_add_entry(struct mk_iov
*mk_io
, mk_pointer data
,
41 mk_pointer sep
, int free
)
43 return mk_iov_add_entry(mk_io
, data
.data
, data
.len
, sep
, free
);
46 struct mk_iov
*mk_header_iov_get()
48 return mk_cache_get(mk_cache_iov_header
);
51 void mk_header_iov_free(struct mk_iov
*iov
)
53 mk_iov_free_marked(iov
);
56 /* Send_Header , envia las cabeceras principales */
57 int mk_header_send(int fd
, struct client_request
*cr
,
61 unsigned long len
= 0;
63 struct header_values
*sh
;
68 iov
= mk_header_iov_get();
73 mk_header_iov_add_entry(iov
, mk_hr_http_ok
,
74 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
78 mk_header_iov_add_entry(iov
, mk_hr_http_partial
,
79 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
83 mk_header_iov_add_entry(iov
, mk_hr_redir_moved
,
84 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
88 mk_header_iov_add_entry(iov
, mk_hr_redir_moved_t
,
89 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
93 mk_header_iov_add_entry(iov
, mk_hr_not_modified
,
94 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
97 case M_CLIENT_BAD_REQUEST
:
98 mk_header_iov_add_entry(iov
, mk_hr_client_bad_request
,
99 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
102 case M_CLIENT_FORBIDDEN
:
103 mk_header_iov_add_entry(iov
, mk_hr_client_forbidden
,
104 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
107 case M_CLIENT_NOT_FOUND
:
108 mk_header_iov_add_entry(iov
, mk_hr_client_not_found
,
109 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
112 case M_CLIENT_METHOD_NOT_ALLOWED
:
113 mk_header_iov_add_entry(iov
, mk_hr_client_method_not_allowed
,
114 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
117 case M_CLIENT_REQUEST_TIMEOUT
:
118 mk_header_iov_add_entry(iov
, mk_hr_client_request_timeout
,
119 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
122 case M_CLIENT_LENGTH_REQUIRED
:
123 mk_header_iov_add_entry(iov
, mk_hr_client_length_required
,
124 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
127 case M_CLIENT_REQUEST_ENTITY_TOO_LARGE
:
128 mk_header_iov_add_entry(iov
, mk_hr_client_request_entity_too_large
,
129 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
132 case M_SERVER_NOT_IMPLEMENTED
:
133 mk_header_iov_add_entry(iov
, mk_hr_server_not_implemented
,
134 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
137 case M_SERVER_INTERNAL_ERROR
:
138 mk_header_iov_add_entry(iov
, mk_hr_server_internal_error
,
139 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
142 case M_SERVER_HTTP_VERSION_UNSUP
:
143 mk_header_iov_add_entry(iov
,
144 mk_hr_server_http_version_unsup
,
145 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
152 mk_header_iov_free(iov
);
157 mk_iov_add_entry(iov
, sr
->host_conf
->header_host_signature
.data
,
158 sr
->host_conf
->header_host_signature
.len
,
159 mk_iov_crlf
, MK_IOV_NOT_FREE_BUF
);
162 mk_iov_add_entry(iov
,
163 mk_header_short_date
.data
,
164 mk_header_short_date
.len
,
165 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
166 mk_iov_add_entry(iov
,
167 header_current_time
.data
,
168 header_current_time
.len
,
169 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
172 if (sh
->last_modified
> 0) {
174 lm
= mk_cache_get(mk_cache_header_lm
);
175 mk_utils_utime2gmt(&lm
, sh
->last_modified
);
177 mk_iov_add_entry(iov
, mk_header_last_modified
.data
,
178 mk_header_last_modified
.len
,
179 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
180 mk_iov_add_entry(iov
, lm
->data
, lm
->len
,
181 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
185 if (config
->keep_alive
== VAR_ON
&&
186 sr
->keep_alive
== VAR_ON
&&
187 cr
->counter_connections
< config
->max_keep_alive_request
) {
189 /* A valid connection header */
190 if (sr
->connection
.len
> 0) {
191 mk_string_build(&buffer
,
193 "Keep-Alive: timeout=%i, max=%i"
195 config
->keep_alive_timeout
,
196 (config
->max_keep_alive_request
-
197 cr
->counter_connections
)
199 mk_iov_add_entry(iov
, buffer
, len
, mk_iov_none
, MK_IOV_FREE_BUF
);
200 mk_iov_add_entry(iov
,
201 mk_header_conn_ka
.data
,
202 mk_header_conn_ka
.len
,
203 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
206 else if(sr
->close_now
== VAR_ON
) {
207 mk_iov_add_entry(iov
,
208 mk_header_conn_close
.data
,
209 mk_header_conn_close
.len
,
210 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
214 if (sh
->location
!= NULL
) {
215 mk_iov_add_entry(iov
,
216 mk_header_short_location
.data
,
217 mk_header_short_location
.len
,
218 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
220 mk_iov_add_entry(iov
,
222 strlen(sh
->location
), mk_iov_crlf
, MK_IOV_FREE_BUF
);
226 if (sh
->content_type
.len
> 0) {
227 mk_iov_add_entry(iov
,
228 mk_header_short_ct
.data
,
229 mk_header_short_ct
.len
,
230 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
232 mk_iov_add_entry(iov
,
233 sh
->content_type
.data
,
234 sh
->content_type
.len
,
235 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
238 /* Transfer Encoding: the transfer encoding header is just sent when
239 * the response has some content defined by the HTTP status response
241 if ((sh
->status
< M_REDIR_MULTIPLE
) || (sh
->status
> M_REDIR_USE_PROXY
)) {
242 switch (sh
->transfer_encoding
) {
243 case MK_HEADER_TE_TYPE_CHUNKED
:
244 mk_iov_add_entry(iov
,
245 mk_header_te_chunked
.data
,
246 mk_header_te_chunked
.len
,
247 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
253 if (sh
->content_length
>= 0 && sr
->method
!= HTTP_METHOD_HEAD
) {
254 /* Map content length to MK_POINTER */
256 cl
= mk_cache_get(mk_cache_header_cl
);
257 mk_string_itop(sh
->content_length
, cl
);
260 mk_iov_add_entry(iov
, mk_header_content_length
.data
,
261 mk_header_content_length
.len
,
262 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
264 mk_iov_add_entry(iov
, cl
->data
, cl
->len
,
265 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
269 if ((sh
->content_length
!= 0 &&
270 (sh
->ranges
[0] >= 0 || sh
->ranges
[1] >= 0)) &&
271 config
->resume
== VAR_ON
) {
275 if (sh
->ranges
[0] >= 0 && sh
->ranges
[1] == -1) {
276 mk_string_build(&buffer
,
281 (sh
->real_length
- 1), sh
->real_length
);
282 mk_iov_add_entry(iov
, buffer
, len
, mk_iov_crlf
, MK_IOV_FREE_BUF
);
286 if (sh
->ranges
[0] >= 0 && sh
->ranges
[1] >= 0) {
287 mk_string_build(&buffer
,
291 sh
->ranges
[0], sh
->ranges
[1], sh
->real_length
);
293 mk_iov_add_entry(iov
, buffer
, len
, mk_iov_crlf
, MK_IOV_FREE_BUF
);
297 if (sh
->ranges
[0] == -1 && sh
->ranges
[1] > 0) {
298 mk_string_build(&buffer
,
302 (sh
->real_length
- sh
->ranges
[1]),
303 (sh
->real_length
- 1), sh
->real_length
);
304 mk_iov_add_entry(iov
, buffer
, len
, mk_iov_crlf
, MK_IOV_FREE_BUF
);
308 if (sh
->cgi
== SH_NOCGI
|| sh
->breakline
== MK_HEADER_BREAKLINE
) {
309 mk_iov_add_entry(iov
, mk_iov_crlf
.data
, mk_iov_crlf
.len
,
310 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
313 mk_socket_set_cork_flag(fd
, TCP_CORK_ON
);
314 mk_iov_send(fd
, iov
, MK_IOV_SEND_TO_SOCKET
);
317 MK_TRACE("Headers sent to FD %i", fd
);
318 printf("%s", ANSI_YELLOW
);
320 mk_iov_send(0, iov
, MK_IOV_SEND_TO_SOCKET
);
321 printf("%s", ANSI_RESET
);
325 mk_header_iov_free(iov
);
329 char *mk_header_chunked_line(int len
)
333 buf
= mk_mem_malloc_z(10);
334 snprintf(buf
, 9, "%x%s", len
, MK_CRLF
);
339 void mk_header_set_http_status(struct request
*sr
, int status
)
341 sr
->headers
->status
= status
;
344 struct header_values
*mk_header_create()
346 struct header_values
*headers
;
349 (struct header_values
*) mk_mem_malloc(sizeof(struct header_values
));
351 headers
->ranges
[0] = -1;
352 headers
->ranges
[1] = -1;
353 headers
->content_length
= -1;
354 headers
->transfer_encoding
= -1;
355 headers
->last_modified
= -1;
356 mk_pointer_reset(&headers
->content_type
);
357 headers
->location
= NULL
;