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
00157 dbg_err_if(u_urlncpy(buf + strlen(buf), value, strlen(value),
00158 URLCPY_ENCODE) <= 0);
00159
00160
00161 if(expire)
00162 {
00163 dbg_err_if(u_tt_to_rfc822(date, expire));
00164
00165 dbg_err_if(u_snprintf(buf + strlen(buf), BUFSZ - strlen(buf),
00166 "; expire=%s", date));
00167 }
00168
00169
00170 if(path)
00171 dbg_err_if(u_snprintf(buf + strlen(buf),
00172 BUFSZ - strlen(buf), "; path=%s", path));
00173
00174
00175 if(domain)
00176 dbg_err_if(u_snprintf(buf + strlen(buf),
00177 BUFSZ - strlen(buf), "; domain=%s", domain));
00178
00179 if(secure)
00180 dbg_err_if(u_snprintf(buf + strlen(buf),
00181 BUFSZ - strlen(buf), "; secure"));
00182
00183 }
00184
00185 dbg_err_if(field_create("Set-Cookie", buf, &field));
00186
00187 dbg_err_if(header_add_field(rs->header, field));
00188
00189 return 0;
00190 err:
00191 if(field)
00192 field_free(field);
00193 return ~0;
00194 }
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210 static int response_print_status(response_t *rs, io_t *io)
00211 {
00212 dbg_err_if(io_printf(io, "HTTP/1.0 %d %s\r\n", rs->status,
00213 http_get_status_desc(rs->status)) < 0);
00214
00215 return 0;
00216 err:
00217 return ~0;
00218 }
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 static int response_print_field(response_t *rs, io_t *io, field_t *field)
00235 {
00236 u_unused_args(rs);
00237
00238 dbg_err_if(io_printf(io, "%s: %s\r\n", field->name, field->value) < 0);
00239
00240 return 0;
00241 err:
00242 return ~0;
00243 }
00244
00258 void response_set_method(response_t *rs, int method)
00259 {
00260 rs->method = method;
00261 }
00262
00275 int response_get_method(response_t *rs)
00276 {
00277 return rs->method;
00278 }
00279
00280
00281
00282 void response_set_cgi(response_t *rs, int cgi)
00283 {
00284 rs->cgi = cgi;
00285 return ;
00286 }
00287
00288
00289
00290 size_t response_get_max_header_size(response_t *rs)
00291 {
00292 field_t *field;
00293 int i, n;
00294 size_t sz = 0;
00295
00296
00297 sz += 16;
00298 sz += strlen(http_get_status_desc(rs->status));
00299
00300 n = header_field_count(rs->header);
00301 for(i = 0; i < n; ++i)
00302 {
00303 field = header_get_fieldn(rs->header, i);
00304 sz += strlen(field_get_name(field));
00305 sz += strlen(field_get_value(field));
00306 sz += 4;
00307 }
00308
00309 sz += 2;
00310 sz += 64;
00311
00312 return sz;
00313 }
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328 int response_print_header_to_io(response_t *rs, io_t *io)
00329 {
00330 int i, n;
00331
00332 dbg_err_if(io == NULL);
00333
00334
00335 if(!rs->cgi)
00336 dbg_err_if(response_print_status(rs, io));
00337
00338
00339 n = header_field_count(rs->header);
00340 for(i = 0; i < n; ++i)
00341 dbg_err_if(response_print_field(rs, io,
00342 header_get_fieldn(rs->header, i)));
00343
00344 dbg_err_if(io_printf(io, "\r\n") < 0);
00345
00346 return 0;
00347 err:
00348 return ~0;
00349 }
00350
00363 int response_print_header(response_t *rs)
00364 {
00365 return response_print_header_to_io(rs, rs->io);
00366 }
00367
00368
00383 int response_set_field(response_t *rs, const char *name, const char *value)
00384 {
00385 return header_set_field(rs->header, name, value);
00386 }
00387
00388
00402 int response_del_field(response_t *rs, const char *name)
00403 {
00404 field_t *f = NULL;
00405
00406 f = header_get_field(rs->header, name);
00407 dbg_err_if(f == NULL);
00408
00409
00410 dbg_err_if(header_del_field(rs->header, f));
00411
00412 field_free(f);
00413
00414 return 0;
00415 err:
00416 return ~0;
00417 }
00418
00432 int response_set_content_type(response_t *rs, const char *mime_type)
00433 {
00434 dbg_err_if(mime_type == NULL);
00435
00436 dbg_err_if(header_set_field(rs->header, "Content-Type", mime_type));
00437
00438 return 0;
00439 err:
00440 return ~0;
00441 }
00442
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
00483 int response_set_last_modified(response_t *rs, time_t mtime)
00484 {
00485 enum { BUFSZ = 64 };
00486 char buf[BUFSZ];
00487
00488 dbg_err_if(u_tt_to_rfc822(buf, mtime));
00489
00490 dbg_err_if(header_set_field(rs->header, "Last-Modified", buf));
00491
00492 return 0;
00493 err:
00494 return ~0;
00495 }
00496
00510 int response_set_content_length(response_t *rs, size_t sz)
00511 {
00512 enum { BUFSZ = 64 };
00513 char buf[BUFSZ];
00514
00515 dbg_err_if(u_snprintf(buf, BUFSZ, "%u", sz));
00516
00517 dbg_err_if(header_set_field(rs->header, "Content-Length", buf));
00518
00519 return 0;
00520 err:
00521 return ~0;
00522 }
00523
00536 int response_get_status(response_t *rs)
00537 {
00538 return rs->status;
00539 }
00540
00552 header_t* response_get_header(response_t *rs)
00553 {
00554 return rs->header;
00555 }
00556
00568 io_t* response_io(response_t *rs)
00569 {
00570 return rs->io;
00571 }
00572
00586 int response_redirect(response_t *rs, const char *url)
00587 {
00588 field_t *field;
00589
00590
00591 response_set_status(rs, HTTP_STATUS_MOVED_TEMPORARILY);
00592
00593 dbg_err_if(field_create("Location", url, &field));
00594
00595 header_add_field(rs->header, field);
00596
00597 return 0;
00598 err:
00599 return ~0;
00600 }
00601
00615 int response_set_status(response_t *rs, int status)
00616 {
00617 rs->status = status;
00618
00619 return 0;
00620 }
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634 int response_bind(response_t *rs, io_t *out)
00635 {
00636 rs->io = out;
00637
00638 return 0;
00639 }
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652 int response_create(http_t *http, response_t **prs)
00653 {
00654 response_t *rs = NULL;
00655
00656 rs = u_zalloc(sizeof(response_t));
00657 dbg_err_if(rs == NULL);
00658
00659 dbg_err_if(header_create(&rs->header));
00660
00661 rs->http = http;
00662
00663 *prs = rs;
00664
00665 return 0;
00666 err:
00667 if(rs->header)
00668 header_free(rs->header);
00669 if(rs)
00670 response_free(rs);
00671 return ~0;
00672 }
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683 int response_free(response_t *rs)
00684 {
00685 if(rs->io)
00686 io_free(rs->io);
00687
00688 if(rs->header)
00689 header_free(rs->header);
00690
00691 U_FREE(rs);
00692
00693 return 0;
00694 }
00695
00696
00697
00698
00699 field_t* response_get_field(response_t *rs, const char *name)
00700 {
00701 dbg_return_if (rs == NULL, NULL);
00702 dbg_return_if (name == NULL, NULL);
00703
00704 return header_get_field(rs->header, name);
00705 }
00706
00707
00708
00709 const char* response_get_field_value(response_t *rs, const char *name)
00710 {
00711 dbg_return_if (rs == NULL, NULL);
00712 dbg_return_if (name == NULL, NULL);
00713
00714 return header_get_field_value(rs->header, name);
00715 }