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 const char *p;
00303
00304 field = header_get_fieldn(rs->header, i);
00305 sz += ((p = field_get_name(field)) != NULL) ? strlen(p) : 0;
00306 sz += ((p = field_get_value(field)) != NULL) ? strlen(p) : 0;
00307 sz += 4;
00308 }
00309
00310 sz += 2;
00311 sz += 64;
00312
00313 return sz;
00314 }
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329 int response_print_header_to_io(response_t *rs, io_t *io)
00330 {
00331 int i, n;
00332
00333 dbg_err_if(io == NULL);
00334
00335
00336 if(!rs->cgi)
00337 dbg_err_if(response_print_status(rs, io));
00338
00339
00340 n = header_field_count(rs->header);
00341 for(i = 0; i < n; ++i)
00342 dbg_err_if(response_print_field(rs, io,
00343 header_get_fieldn(rs->header, i)));
00344
00345 dbg_err_if(io_printf(io, "\r\n") < 0);
00346
00347 return 0;
00348 err:
00349 return ~0;
00350 }
00351
00364 int response_print_header(response_t *rs)
00365 {
00366 return response_print_header_to_io(rs, rs->io);
00367 }
00368
00369
00384 int response_set_field(response_t *rs, const char *name, const char *value)
00385 {
00386 return header_set_field(rs->header, name, value);
00387 }
00388
00389
00403 int response_del_field(response_t *rs, const char *name)
00404 {
00405 field_t *f = NULL;
00406
00407 f = header_get_field(rs->header, name);
00408 dbg_err_if(f == NULL);
00409
00410
00411 dbg_err_if(header_del_field(rs->header, f));
00412
00413 field_free(f);
00414
00415 return 0;
00416 err:
00417 return ~0;
00418 }
00419
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
00457 int response_set_date(response_t *rs, time_t date)
00458 {
00459 enum { BUFSZ = 64 };
00460 char buf[BUFSZ];
00461
00462 dbg_err_if(u_tt_to_rfc822(buf, date));
00463
00464 dbg_err_if(header_set_field(rs->header, "Date", buf));
00465
00466 return 0;
00467 err:
00468 return ~0;
00469 }
00470
00484 int response_set_last_modified(response_t *rs, time_t mtime)
00485 {
00486 enum { BUFSZ = 64 };
00487 char buf[BUFSZ];
00488
00489 dbg_err_if(u_tt_to_rfc822(buf, mtime));
00490
00491 dbg_err_if(header_set_field(rs->header, "Last-Modified", buf));
00492
00493 return 0;
00494 err:
00495 return ~0;
00496 }
00497
00511 int response_set_content_length(response_t *rs, size_t sz)
00512 {
00513 enum { BUFSZ = 64 };
00514 char buf[BUFSZ];
00515
00516 dbg_err_if(u_snprintf(buf, BUFSZ, "%u", sz));
00517
00518 dbg_err_if(header_set_field(rs->header, "Content-Length", buf));
00519
00520 return 0;
00521 err:
00522 return ~0;
00523 }
00524
00537 int response_get_status(response_t *rs)
00538 {
00539 return rs->status;
00540 }
00541
00553 header_t* response_get_header(response_t *rs)
00554 {
00555 return rs->header;
00556 }
00557
00569 io_t* response_io(response_t *rs)
00570 {
00571 return rs->io;
00572 }
00573
00587 int response_redirect(response_t *rs, const char *url)
00588 {
00589 field_t *field;
00590
00591
00592 response_set_status(rs, HTTP_STATUS_MOVED_TEMPORARILY);
00593
00594 dbg_err_if(field_create("Location", url, &field));
00595
00596 header_add_field(rs->header, field);
00597
00598 return 0;
00599 err:
00600 return ~0;
00601 }
00602
00616 int response_set_status(response_t *rs, int status)
00617 {
00618 rs->status = status;
00619
00620 return 0;
00621 }
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635 int response_bind(response_t *rs, io_t *out)
00636 {
00637 rs->io = out;
00638
00639 return 0;
00640 }
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653 int response_create(http_t *http, response_t **prs)
00654 {
00655 response_t *rs = NULL;
00656
00657 rs = u_zalloc(sizeof(response_t));
00658 dbg_err_if(rs == NULL);
00659
00660 dbg_err_if(header_create(&rs->header));
00661
00662 rs->http = http;
00663
00664 *prs = rs;
00665
00666 return 0;
00667 err:
00668 if(rs->header)
00669 header_free(rs->header);
00670 if(rs)
00671 response_free(rs);
00672 return ~0;
00673 }
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684 int response_free(response_t *rs)
00685 {
00686 if(rs->io)
00687 io_free(rs->io);
00688
00689 if(rs->header)
00690 header_free(rs->header);
00691
00692 U_FREE(rs);
00693
00694 return 0;
00695 }
00696
00697
00698
00699
00700 field_t* response_get_field(response_t *rs, const char *name)
00701 {
00702 dbg_return_if (rs == NULL, NULL);
00703 dbg_return_if (name == NULL, NULL);
00704
00705 return header_get_field(rs->header, name);
00706 }
00707
00708
00709
00710 const char* response_get_field_value(response_t *rs, const char *name)
00711 {
00712 dbg_return_if (rs == NULL, NULL);
00713 dbg_return_if (name == NULL, NULL);
00714
00715 return header_get_field_value(rs->header, name);
00716 }