00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "klone_conf.h"
00012 #include <time.h>
00013 #include <u/libu.h>
00014 #include <klone/response.h>
00015 #include <klone/utils.h>
00016 #include <klone/io.h>
00017 #include <klone/codec.h>
00018 #include <klone/http.h>
00019 #include <klone/rsfilter.h>
00020
00021 struct response_s
00022 {
00023 http_t *http;
00024 header_t *header;
00025 io_t *io;
00026 int status;
00027 int method;
00028 int cgi;
00029 };
00030
00031
00057 int response_set_content_encoding(response_t *rs, const char *encoding)
00058 {
00059 dbg_err_if(encoding == NULL);
00060
00061 dbg_err_if(header_set_field(rs->header, "Content-Encoding", encoding));
00062
00063 return 0;
00064 err:
00065 return ~0;
00066 }
00067
00086 int response_disable_caching(response_t *rs)
00087 {
00088 dbg_err_if(response_set_field(rs, "Cache-Control",
00089 "no-cache, must-revalidate"));
00090
00091 dbg_err_if(response_set_field(rs, "Expires",
00092 "Mon, 1 Jan 1990 05:00:00 GMT"));
00093
00094 dbg_err_if(response_set_field(rs, "Pragma", "no-cache"));
00095
00096 return 0;
00097 err:
00098 return ~0;
00099 }
00100
00119 int response_enable_caching(response_t *rs)
00120 {
00121 dbg_err_if(response_del_field(rs, "Cache-Control"));
00122
00123 dbg_err_if(response_del_field(rs, "Expires"));
00124
00125 dbg_err_if(response_del_field(rs, "Pragma"));
00126
00127 return 0;
00128 err:
00129 return ~0;
00130 }
00131
00150 int response_set_cookie(response_t *rs, const char *name, const char *value,
00151 time_t expire, const char *path, const char *domain, int secure)
00152 {
00153 enum { BUFSZ = 4096, DATESZ = 64 };
00154 field_t *field = NULL;
00155 char buf[BUFSZ], date[DATESZ];
00156
00157 if(value == NULL)
00158 {
00159 dbg_err_if(u_snprintf(buf, BUFSZ,
00160 "%s=; expires=Wed, 01-Jan-1990 10:10:10 GMT", name));
00161 } else {
00162
00163 dbg_err_if(u_snprintf(buf, BUFSZ, "%s=", name));
00164
00165
00166
00167 dbg_err_if(u_urlncpy(buf + strlen(buf), value, strlen(value),
00168 URLCPY_ENCODE) <= 0);
00169
00170
00171 if(expire)
00172 {
00173 dbg_err_if(u_tt_to_rfc822(date, expire));
00174
00175 dbg_err_if(u_snprintf(buf + strlen(buf), BUFSZ - strlen(buf),
00176 "; expire=%s", date));
00177 }
00178
00179
00180 if(path)
00181 dbg_err_if(u_snprintf(buf + strlen(buf),
00182 BUFSZ - strlen(buf), "; path=%s", path));
00183
00184
00185 if(domain)
00186 dbg_err_if(u_snprintf(buf + strlen(buf),
00187 BUFSZ - strlen(buf), "; domain=%s", domain));
00188
00189 if(secure)
00190 dbg_err_if(u_snprintf(buf + strlen(buf),
00191 BUFSZ - strlen(buf), "; secure"));
00192
00193 }
00194
00195 dbg_err_if(field_create("Set-Cookie", buf, &field));
00196
00197 dbg_err_if(header_add_field(rs->header, field));
00198
00199 return 0;
00200 err:
00201 if(field)
00202 field_free(field);
00203 return ~0;
00204 }
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 static int response_print_status(response_t *rs, io_t *io)
00220 {
00221 dbg_err_if(io_printf(io, "HTTP/1.0 %d %s\r\n", rs->status,
00222 http_get_status_desc(rs->status)) < 0);
00223
00224 return 0;
00225 err:
00226 return ~0;
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 static int response_print_field(response_t *rs, io_t *io, field_t *field)
00243 {
00244 u_unused_args(rs);
00245
00246 dbg_err_if(io_printf(io, "%s: %s\r\n", field->name, field->value) < 0);
00247
00248 return 0;
00249 err:
00250 return ~0;
00251 }
00252
00265 void response_set_method(response_t *rs, int method)
00266 {
00267 rs->method = method;
00268 }
00269
00281 int response_get_method(response_t *rs)
00282 {
00283 return rs->method;
00284 }
00285
00286
00287
00288 void response_set_cgi(response_t *rs, int cgi)
00289 {
00290 rs->cgi = cgi;
00291 return ;
00292 }
00293
00294
00295
00296 size_t response_get_max_header_size(response_t *rs)
00297 {
00298 field_t *field;
00299 int i, n;
00300 size_t sz = 0;
00301
00302
00303 sz += 16;
00304 sz += strlen(http_get_status_desc(rs->status));
00305
00306 n = header_field_count(rs->header);
00307 for(i = 0; i < n; ++i)
00308 {
00309 field = header_get_fieldn(rs->header, i);
00310 sz += strlen(field_get_name(field));
00311 sz += strlen(field_get_value(field));
00312 sz += 4;
00313 }
00314
00315 sz += 2;
00316 sz += 64;
00317
00318 return sz;
00319 }
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333 int response_print_header_to_io(response_t *rs, io_t *io)
00334 {
00335 int i, n;
00336
00337 dbg_err_if(io == NULL);
00338
00339
00340 if(!rs->cgi)
00341 dbg_err_if(response_print_status(rs, io));
00342
00343
00344 n = header_field_count(rs->header);
00345 for(i = 0; i < n; ++i)
00346 dbg_err_if(response_print_field(rs, io,
00347 header_get_fieldn(rs->header, i)));
00348
00349 dbg_err_if(io_printf(io, "\r\n") < 0);
00350
00351 return 0;
00352 err:
00353 return ~0;
00354 }
00355
00367 int response_print_header(response_t *rs)
00368 {
00369 return response_print_header_to_io(rs, rs->io);
00370 }
00371
00372
00386 int response_set_field(response_t *rs, const char *name, const char *value)
00387 {
00388 return header_set_field(rs->header, name, value);
00389 }
00390
00391
00404 int response_del_field(response_t *rs, const char *name)
00405 {
00406 field_t *f = NULL;
00407
00408 f = header_get_field(rs->header, name);
00409 dbg_err_if(f == NULL);
00410
00411
00412 dbg_err_if(header_del_field(rs->header, f));
00413
00414 field_free(f);
00415
00416 return 0;
00417 err:
00418 return ~0;
00419 }
00420
00433 int response_set_content_type(response_t *rs, const char *mime_type)
00434 {
00435 dbg_err_if(mime_type == NULL);
00436
00437 dbg_err_if(header_set_field(rs->header, "Content-Type", mime_type));
00438
00439 return 0;
00440 err:
00441 return ~0;
00442 }
00443
00456 int response_set_date(response_t *rs, time_t date)
00457 {
00458 enum { BUFSZ = 64 };
00459 char buf[BUFSZ];
00460
00461 dbg_err_if(u_tt_to_rfc822(buf, date));
00462
00463 dbg_err_if(header_set_field(rs->header, "Date", buf));
00464
00465 return 0;
00466 err:
00467 return ~0;
00468 }
00469
00482 int response_set_last_modified(response_t *rs, time_t mtime)
00483 {
00484 enum { BUFSZ = 64 };
00485 char buf[BUFSZ];
00486
00487 dbg_err_if(u_tt_to_rfc822(buf, mtime));
00488
00489 dbg_err_if(header_set_field(rs->header, "Last-Modified", buf));
00490
00491 return 0;
00492 err:
00493 return ~0;
00494 }
00495
00508 int response_set_content_length(response_t *rs, size_t sz)
00509 {
00510 enum { BUFSZ = 64 };
00511 char buf[BUFSZ];
00512
00513 dbg_err_if(u_snprintf(buf, BUFSZ, "%u", sz));
00514
00515 dbg_err_if(header_set_field(rs->header, "Content-Length", buf));
00516
00517 return 0;
00518 err:
00519 return ~0;
00520 }
00521
00533 int response_get_status(response_t *rs)
00534 {
00535 return rs->status;
00536 }
00537
00548 header_t* response_get_header(response_t *rs)
00549 {
00550 return rs->header;
00551 }
00552
00563 io_t* response_io(response_t *rs)
00564 {
00565 return rs->io;
00566 }
00567
00580 int response_redirect(response_t *rs, const char *url)
00581 {
00582 field_t *field;
00583
00584
00585 response_set_status(rs, HTTP_STATUS_MOVED_TEMPORARILY);
00586
00587 dbg_err_if(field_create("Location", url, &field));
00588
00589 header_add_field(rs->header, field);
00590
00591 return 0;
00592 err:
00593 return ~0;
00594 }
00595
00608 int response_set_status(response_t *rs, int status)
00609 {
00610 rs->status = status;
00611
00612 return 0;
00613 }
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626 int response_bind(response_t *rs, io_t *out)
00627 {
00628 rs->io = out;
00629
00630 return 0;
00631 }
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643 int response_create(http_t *http, response_t **prs)
00644 {
00645 response_t *rs = NULL;
00646
00647 rs = u_zalloc(sizeof(response_t));
00648 dbg_err_if(rs == NULL);
00649
00650 dbg_err_if(header_create(&rs->header));
00651
00652 rs->http = http;
00653
00654 *prs = rs;
00655
00656 return 0;
00657 err:
00658 if(rs->header)
00659 header_free(rs->header);
00660 if(rs)
00661 response_free(rs);
00662 return ~0;
00663 }
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673 int response_free(response_t *rs)
00674 {
00675 if(rs->io)
00676 io_free(rs->io);
00677
00678 if(rs->header)
00679 header_free(rs->header);
00680
00681 U_FREE(rs);
00682
00683 return 0;
00684 }
00685