response.c

00001 /*
00002  * Copyright (c) 2005-2012 by KoanLogic s.r.l. <http://www.koanlogic.com>
00003  * All rights reserved.
00004  *
00005  * This file is part of KLone, and as such it is subject to the license stated
00006  * in the LICENSE file which you have received as part of this distribution.
00007  *
00008  * $Id: response.c,v 1.30 2008/07/25 09:38:56 tho Exp $
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;           /* http server handle               */
00024     header_t *header;       /* output header                    */
00025     io_t *io;               /* output stream                    */
00026     int status;             /* http status code                 */
00027     int method;             /* HTTP request method              */
00028     int cgi;                /* if we're running in cgi context  */
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     {   /* delete this cookie */
00149         dbg_err_if(u_snprintf(buf, BUFSZ, 
00150             "%s=; expires=Wed, 01-Jan-1990 10:10:10 GMT", name));
00151     } else {
00152         /* name */
00153         dbg_err_if(u_snprintf(buf, BUFSZ, "%s=", name));
00154 
00155         /* encoded value */
00156         dbg_err_if(u_urlncpy(buf + strlen(buf), value, strlen(value), 
00157             URLCPY_ENCODE) <= 0);
00158 
00159         /* expiration date */
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         /* path */
00169         if(path)
00170             dbg_err_if(u_snprintf(buf + strlen(buf), 
00171                         BUFSZ - strlen(buf), "; path=%s", path));
00172 
00173         /* domain */
00174         if(domain)
00175             dbg_err_if(u_snprintf(buf + strlen(buf), 
00176                         BUFSZ - strlen(buf), "; domain=%s", domain));
00177         /* secure flag */
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  * \ingroup response
00197  * \brief   Print the status of a response object.
00198  *
00199  * A string representing the status of a response object \p rs is printed to \p
00200  * io. 
00201  *
00202  * \param rs      response object
00203  * \param io      output I/O object
00204  *
00205  * \return
00206  *  - \c 0 if successful
00207  *  - \c ~0 on error
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  * \ingroup response
00221  * \brief   Print a response field.
00222  *
00223  * Print the name and value of a \p field of \p response to \p io.
00224  *
00225  * \param rs      response object
00226  * \param io      output I/O object
00227  * \param field   field to be printed
00228  *
00229  * \return
00230  *  - \c 0 if successful
00231  *  - \c ~0 on error
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 /* set is-cgi flag */
00281 void response_set_cgi(response_t *rs, int cgi)
00282 {
00283     rs->cgi = cgi;
00284     return ;
00285 }
00286 
00287 /* calculate the approx max value of the current header (useful to alloc a
00288  * buffer big enough) */
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     /* calc status line length */
00296     sz += 16; /* http/x.y nnn[n] \r\n */
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; /* blanks and new lines */
00308     }
00309 
00310     sz += 2; /* final \r\n */
00311     sz += 64; /* guard bytes */
00312 
00313     return sz;
00314 }
00315 
00316 /* 
00317  * \ingroup response
00318  * \brief   Output a response header 
00319  *
00320  * Print the header of \p rs to \p io.
00321  *
00322  * \param rs        response object
00323  * \param io        output I/O object
00324  * 
00325  * \return
00326  *  - \c 0 if successful
00327  *  - \c ~0 on error
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     /* print status line */
00336     if(!rs->cgi)
00337         dbg_err_if(response_print_status(rs, io));
00338 
00339     /* print field list */
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     /* field found, delete it */
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     /* send Location: with redirect status code */
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  * \ingroup response
00625  * \brief   Bind the response to a given I/O object
00626  *  
00627  * Bind response \p rs to I/O object \p out.
00628  *
00629  * \param rs     
00630  * \param out  output I/O object
00631  *  
00632  * \return
00633  *  - \c 0  always
00634  */
00635 int response_bind(response_t *rs, io_t *out)
00636 {
00637     rs->io = out;
00638 
00639     return 0;
00640 }
00641 
00642 /*
00643  * \ingroup response
00644  * \brief   Create a response object
00645  *  
00646  * \param http  parameter \p http description
00647  * \param prs   parameter \p prs description
00648  *  
00649  * \return
00650  *  - \c 0  if successful
00651  *  - \c ~0 on error
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  * \ingroup response
00677  * \brief   Free a response object
00678  *  
00679  * \param rs response object
00680  *  
00681  * \return
00682  *  - \c 0  always
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 /* return a field obj of the field named 'name' or NULL if the field does not 
00699    exist */
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 /* return the string value of the field named 'name' or NULL if the field does
00709    not exist */
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 }

←Products
Copyright © 2005-2012 - KoanLogic S.r.l. - All rights reserved