WEBBY - the embedded web server with many faces / objects in plain C Snapshot
Classes | Typedefs | Enumerations | Functions
HTTP_servlet_response
HTTP_SERVLET

represents the http response and includes methods to set response header and send the response body. More...

Collaboration diagram for HTTP_servlet_response:

Classes

struct  tagHTTP_servlet_response

Typedefs

typedef struct
tagHTTP_servlet_response 
HTTP_servlet_response

Enumerations

enum  HTTP_servlet_response_type { RESPONSE_CONNECTION_CLOSE, RESPONSE_CONTENT_LENGTH, RESPONSE_CHUNKED }

Functions

int HTTP_response_start (HTTP_servlet_response *resp, int status, const char *mime_type, HTTP_servlet_response_type rtype, size_t length)
 initiate an HTTP response
int HTTP_response_send (HTTP_servlet_response *resp, void *data, size_t size)
 send response data when sending RESPONSE_CONTENT_LENGTH or RESPONSE_CONNECTION_CLOSE responses
int HTTP_response_finish (HTTP_servlet_response *resp)
 finish sending of response
BF * HTTP_response_get_chunk_buffer (HTTP_servlet_response *resp, size_t chunk_size)
 returns buffer for sending chunks The buffer reserves enough space before start of buffer, in order to allow addition of chunk header before the sent daa
int HTTP_response_write_chunk (HTTP_servlet_response *resp, BF *bf)
 send chunk from buffer The buffer must reserve enough space for the chunk header, before start of buffer

Detailed Description

represents the http response and includes methods to set response header and send the response body.


Typedef Documentation


Enumeration Type Documentation

Enumerator:
RESPONSE_CONNECTION_CLOSE 
RESPONSE_CONTENT_LENGTH 
RESPONSE_CHUNKED 

Definition at line 311 of file webby.h.


Function Documentation

int HTTP_response_finish ( HTTP_servlet_response resp)

finish sending of response

Definition at line 1003 of file webby.c.

{
  RDATA rdata;

  if (resp->state < 1 || resp->state > 2) {
    return -1;
  }

  if (resp->state == 1) {
    if (call_next_filter_response_header( &resp->response,  resp->filter_context )) {
      return -1;
    }
  } 
 
 
  if (resp->response.base.flags & HTTP_MESSAGE_FLAG_TRANSFER_CHUNKED) {
 
    rdata.chunk.bf = 0;
    rdata.chunk.chunk_no = ++resp->chunk_no;

    if ( call_next_filter_response_data ( &resp->response, 1, rdata, resp->filter_context  ) )  {
      return -1;
    }

#if 0 
    if (resp->state == 1) {
      if (call_next_filter_response_data ( &resp->response, LAST_CHUNK, LAST_CHUNK_SIZE, resp->filter_context  )) {
        return -1;
      }
    } else {
      if (call_next_filter_response_data ( &resp->response, LAST_CHUNK_NOT_FIRST, LAST_CHUNK_NOT_FIRST_SIZE, resp->filter_context  )) {
        return -1;
      }
    }
#endif
  }
  resp->state = 3;
  
  return call_next_filter_response_completed ( &resp->response, resp->filter_context );
}
BF* HTTP_response_get_chunk_buffer ( HTTP_servlet_response resp,
size_t  chunk_size 
)

returns buffer for sending chunks The buffer reserves enough space before start of buffer, in order to allow addition of chunk header before the sent daa

Definition at line 928 of file webby.c.

{
  size_t sz;
  void *tmp;

  if (resp->chunk_buf != 0) {
    if (resp->chunk_buf_size < chunk_size ) {
      sz = chunk_size + RESERVED_FOR_CHUNK_HEADER_SIZE; 
      tmp = realloc( resp->chunk_buf, sz );
      if (!tmp) {
        return 0;
      }
      resp->chunk_buf = tmp;
      resp->chunk_buf_size = chunk_size;
    }
  } else {
    sz = chunk_size + RESERVED_FOR_CHUNK_HEADER_SIZE; 
    resp->chunk_buf = malloc( sz ); 
    if (!resp->chunk_buf) {
      return 0;
    }
    BF_init( &resp->bf, resp->chunk_buf, sz );
    resp->chunk_buf_size = chunk_size;
  } 
  
  BF_put_mode( &resp->bf );
  BF_set_start( &resp->bf, RESERVED_FOR_CHUNK_HEADER_SIZE ); 
  resp->bf.end = resp->bf.put_pos + chunk_size;
  
  return &resp->bf;
}
int HTTP_response_send ( HTTP_servlet_response resp,
void *  data,
size_t  size 
)

send response data when sending RESPONSE_CONTENT_LENGTH or RESPONSE_CONNECTION_CLOSE responses

Precondition: HTTP_response_start has been called. and response type is either RESPONSE_CONTENT_LENGTH or RESPONSE_CONNECTION_CLOSE

Definition at line 892 of file webby.c.

{
  RDATA rdata;

  if (resp->state < 1 || resp->state > 2) {
    return -1;
  }

  if (resp->state == 1) {
    if (call_next_filter_response_header( &resp->response,  resp->filter_context )) {
      return -1;
    }
    resp->state = 2;
  }

  if (resp->response.base.flags & HTTP_MESSAGE_FLAG_TRANSFER_CHUNKED ) {
    return -1;
  }

  // check that not sending more data than allowed by set value of Content-Length header.
  if (resp->data_sent != (size_t) -1) {
    if (resp->data_sent < size ) {
      return -1;
    }
    resp->data_sent -= size;
  }

  rdata.no_chunk.data = data;
  rdata.no_chunk.data_size = size;

  return call_next_filter_response_data ( &resp->response, 0, rdata, resp->filter_context );
}
int HTTP_response_start ( HTTP_servlet_response resp,
int  status,
const char *  mime_type,
HTTP_servlet_response_type  rtype,
size_t  length 
)

initiate an HTTP response

Definition at line 855 of file webby.c.

{
  if (resp->state !=0) {
    return -1;
  }
  resp->response.status_code = status;
  if (mime_type) {
    HTTP_MESSAGE_add_header( &resp->response.base, "Content-Type", mime_type );
  }

  if ( ! HTTP_REQUEST_is_persistent( resp->request ) ) {
    rtype = RESPONSE_CONNECTION_CLOSE;
  }
 
  switch(rtype) {
   case RESPONSE_CONNECTION_CLOSE:
     resp->response.base.flags = HTTP_MESSAGE_FLAG_CONNECTION_CLOSE;  
     resp->data_sent = (size_t) -1;
     break;
   case RESPONSE_CONTENT_LENGTH:
     HTTP_MESSAGE_set_content_length( &resp->response.base, length );
     resp->data_sent = length;
     break;
   case RESPONSE_CHUNKED:
     resp->response.base.flags = HTTP_MESSAGE_FLAG_TRANSFER_CHUNKED;  
#if 0
     if (HTTP_MESSAGE_add_header( &resp->response.base, "Transfer-Encoding" , "chunked" )) {
       return -1;
     }
#endif
     break;
  }

  resp->state = 1;
  return 0;
}
int HTTP_response_write_chunk ( HTTP_servlet_response resp,
BF *  bf 
)

send chunk from buffer The buffer must reserve enough space for the chunk header, before start of buffer

Precondition: HTTP_response_start has been called, and response type is RESPONSE_CHUNKED

Definition at line 960 of file webby.c.

{
  RDATA rdata;

  if (resp->state < 1 || resp->state > 2) {
    return -1;
  }
  if ( (resp->response.base.flags & (HTTP_MESSAGE_FLAG_TRANSFER_CHUNKED | HTTP_MESSAGE_FLAG_CONNECTION_CLOSE)  ) == 0) {
    return -1;
  }

  if (resp->state == 1) {
    if (call_next_filter_response_header( &resp->response,  resp->filter_context )) {
      return -1;
    }
    resp->state = 2;
  } else {
    ++ resp->chunk_no;
  }

  if ( resp->response.base.flags & HTTP_MESSAGE_FLAG_CONNECTION_CLOSE ) { 
    rdata.no_chunk.data = bf->get_pos;
    rdata.no_chunk.data_size = BF_get_size( bf );  

    return call_next_filter_response_data ( &resp->response, 0, rdata, resp->filter_context  );
  }

#if 0
  if (first_chunk) {
    len = snprintf( chunk_header, sizeof( chunk_header ),  "%x\r\n", BF_get_size(bf) );
  } else {
    len = snprintf( chunk_header, sizeof( chunk_header ),  "\r\n%x\r\n", BF_get_size(bf) );
  }

#endif

  rdata.chunk.bf = bf;
  rdata.chunk.chunk_no = resp->chunk_no;


  return call_next_filter_response_data ( &resp->response, 1, rdata, resp->filter_context  );
}