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
00044 int response_set_content_encoding(response_t *rs, const char *encoding)
00045 {
00046 dbg_err_if(encoding == NULL);
00047
00048 dbg_err_if(header_set_field(rs->header, "Content-Encoding", encoding));
00049
00050 return 0;
00051 err:
00052 return ~0;
00053 }
00054
00074 int response_disable_caching(response_t *rs)
00075 {
00076 dbg_err_if(response_set_field(rs, "Cache-Control",
00077 "no-cache, must-revalidate"));
00078
00079 dbg_err_if(response_set_field(rs, "Expires",
00080 "Mon, 1 Jan 1990 05:00:00 GMT"));
00081
00082 dbg_err_if(response_set_field(rs, "Pragma", "no-cache"));
00083
00084 return 0;
00085 err:
00086 return ~0;
00087 }
00088
00108 int response_enable_caching(response_t *rs)
00109 {
00110 dbg_err_if(response_del_field(rs, "Cache-Control"));
00111
00112 dbg_err_if(response_del_field(rs, "Expires"));
00113
00114 dbg_err_if(response_del_field(rs, "Pragma"));
00115
00116 return 0;
00117 err:
00118 return ~0;
00119 }
00120
00140 int response_set_cookie(response_t *rs, const char *name, const char *value,
00141 time_t expire, const char *path, const char *domain, int secure)
00142 {
00143 enum { BUFSZ = 4096, DATESZ = 64 };
00144 field_t *field = NULL;
00145 char buf[BUFSZ], date[DATESZ];
00146
00147 if(value == NULL)
00148 {
00149 dbg_err_if(u_snprintf(buf, BUFSZ,
00150 "%s=; expires=Wed, 01-Jan-1990 10:10:10 GMT", name));
00151 } else {
00152
00153 dbg_err_if(u_snprintf(buf, BUFSZ, "%s=", name));
00154
00155
00156 dbg_err_if(u_urlncpy(buf + strlen(buf), value, strlen(value),
00157 URLCPY_ENCODE) <= 0);
00158
00159
00160 if(expire)
00161 {
00162 dbg_err_if(u_tt_to_rfc822(date, expire));
00163
00164 dbg_err_if(u_snprintf(buf + strlen(buf), BUFSZ - strlen(buf),
00165 "; expires=%s", date));
00166 }
00167
00168
00169 if(path)
00170 dbg_err_if(u_snprintf(buf + strlen(buf),
00171 BUFSZ - strlen(buf), "; path=%s", path));
00172
00173
00174 if(domain)
00175 dbg_err_if(u_snprintf(buf + strlen(buf),
00176 BUFSZ - strlen(buf), "; domain=%s", domain));
00177
00178 if(secure)
00179 dbg_err_if(u_snprintf(buf + strlen(buf),
00180 BUFSZ - strlen(buf), "; secure"));
00181
00182 }
00183
00184 dbg_err_if(field_create("Set-Cookie", buf, &field));
00185
00186 dbg_err_if(header_add_field(rs->header, field));
00187
00188 return 0;
00189 err:
00190 if(field)
00191 field_free(field);
00192 return ~0;
00193 }
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 static int response_print_status(response_t *rs, io_t *io)
00210 {
00211 dbg_err_if(io_printf(io, "HTTP/1.0 %d %s\r\n", rs->status,
00212 http_get_status_desc(rs->status)) < 0);
00213
00214 return 0;
00215 err:
00216 return ~0;
00217 }
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233 static int response_print_field(response_t *rs, io_t *io, field_t *field)
00234 {
00235 u_unused_args(rs);
00236
00237 dbg_err_if(io_printf(io, "%s: %s\r\n", field->name, field->value) < 0);
00238
00239 return 0;
00240 err:
00241 return ~0;
00242 }
00243
00257 void response_set_method(response_t *rs, int method)
00258 {
00259 rs->method = method;
00260 }
00261
00274 int response_get_method(response_t *rs)
00275 {
00276 return rs->method;
00277 }
00278
00279
00280
00281 void response_set_cgi(response_t *rs, int cgi)
00282 {
00283 rs->cgi = cgi;
00284 return ;
00285 }
00286
00287
00288
00289 size_t response_get_max_header_size(response_t *rs)
00290 {
00291 field_t *field;
00292 int i, n;
00293 size_t sz = 0;
00294
00295
00296 sz += 16;
00297 sz += strlen(http_get_status_desc(rs->status));
00298
00299 n = header_field_count(rs->header);
00300 for(i = 0; i < n; ++i)
00301 {
00302 field = header_get_fieldn(rs->header, i);
00303 sz += strlen(field_get_name(field));
00304 sz += strlen(field_get_value(field));
00305 sz += 4;
00306 }
00307
00308 sz += 2;
00309 sz += 64;
00310
00311 return sz;
00312 }
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327 int response_print_header_to_io(response_t *rs, io_t *io)
00328 {
00329 int i, n;
00330
00331 dbg_err_if(io == NULL);
00332
00333
00334 if(!rs->cgi)
00335 dbg_err_if(response_print_status(rs, io));
00336
00337
00338 n = header_field_count(rs->header);
00339 for(i = 0; i < n; ++i)
00340 dbg_err_if(response_print_field(rs, io,
00341 header_get_fieldn(rs->header, i)));
00342
00343 dbg_err_if(io_printf(io, "\r\n") < 0);
00344
00345 return 0;
00346 err:
00347 return ~0;
00348 }
00349
00362 int response_print_header(response_t *rs)
00363 {
00364 return response_print_header_to_io(rs, rs->io);
00365 }
00366
00367
00382 int response_set_field(response_t *rs, const char *name, const char *value)
00383 {
00384 return header_set_field(rs->header, name, value);
00385 }
00386
00387
00401 int response_del_field(response_t *rs, const char *name)
00402 {
00403 field_t *f = NULL;
00404
00405 f = header_get_field(rs->header, name);
00406 dbg_err_if(f == NULL);
00407
00408
00409 dbg_err_if(header_del_field(rs->header, f));
00410
00411 field_free(f);
00412
00413 return 0;
00414 err:
00415 return ~0;
00416 }
00417
00431 int response_set_content_type(response_t *rs, const char *mime_type)
00432 {
00433 dbg_err_if(mime_type == NULL);
00434
00435 dbg_err_if(header_set_field(rs->header, "Content-Type", mime_type));
00436
00437 return 0;
00438 err:
00439 return ~0;
00440 }
00441
00455 int response_set_date(response_t *rs, time_t date)
00456 {
00457 enum { BUFSZ = 64 };
00458 char buf[BUFSZ];
00459
00460 dbg_err_if(u_tt_to_rfc822(buf, date));
00461
00462 dbg_err_if(header_set_field(rs->header, "Date", buf));
00463
00464 return 0;
00465 err:
00466 return ~0;
00467 }
00468
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
00509 int response_set_content_length(response_t *rs, size_t sz)
00510 {
00511 enum { BUFSZ = 64 };
00512 char buf[BUFSZ];
00513
00514 dbg_err_if(u_snprintf(buf, BUFSZ, "%u", sz));
00515
00516 dbg_err_if(header_set_field(rs->header, "Content-Length", buf));
00517
00518 return 0;
00519 err:
00520 return ~0;
00521 }
00522
00535 int response_get_status(response_t *rs)
00536 {
00537 return rs->status;
00538 }
00539
00551 header_t* response_get_header(response_t *rs)
00552 {
00553 return rs->header;
00554 }
00555
00567 io_t* response_io(response_t *rs)
00568 {
00569 return rs->io;
00570 }
00571
00585 int response_redirect(response_t *rs, const char *url)
00586 {
00587 field_t *field;
00588
00589
00590 response_set_status(rs, HTTP_STATUS_MOVED_TEMPORARILY);
00591
00592 dbg_err_if(field_create("Location", url, &field));
00593
00594 header_add_field(rs->header, field);
00595
00596 return 0;
00597 err:
00598 return ~0;
00599 }
00600
00614 int response_set_status(response_t *rs, int status)
00615 {
00616 rs->status = status;
00617
00618 return 0;
00619 }
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633 int response_bind(response_t *rs, io_t *out)
00634 {
00635 rs->io = out;
00636
00637 return 0;
00638 }
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651 int response_create(http_t *http, response_t **prs)
00652 {
00653 response_t *rs = NULL;
00654
00655 rs = u_zalloc(sizeof(response_t));
00656 dbg_err_if(rs == NULL);
00657
00658 dbg_err_if(header_create(&rs->header));
00659
00660 rs->http = http;
00661
00662 *prs = rs;
00663
00664 return 0;
00665 err:
00666 if(rs->header)
00667 header_free(rs->header);
00668 if(rs)
00669 response_free(rs);
00670 return ~0;
00671 }
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682 int response_free(response_t *rs)
00683 {
00684 if(rs->io)
00685 io_free(rs->io);
00686
00687 if(rs->header)
00688 header_free(rs->header);
00689
00690 U_FREE(rs);
00691
00692 return 0;
00693 }
00694
00695
00696
00697
00698 field_t* response_get_field(response_t *rs, const char *name)
00699 {
00700 dbg_return_if (rs == NULL, NULL);
00701 dbg_return_if (name == NULL, NULL);
00702
00703 return header_get_field(rs->header, name);
00704 }
00705
00706
00707
00708 const char* response_get_field_value(response_t *rs, const char *name)
00709 {
00710 dbg_return_if (rs == NULL, NULL);
00711 dbg_return_if (name == NULL, NULL);
00712
00713 return header_get_field_value(rs->header, name);
00714 }