HTTP Parser and message builder / objects in plain C Snapshot
Classes | Typedefs | Functions
HTTP_REQUEST_PARSER

parser of http requests More...

Classes

struct  tagHTTP_REQUEST_PARSER

Typedefs

typedef struct
tagHTTP_REQUEST_PARSER 
HTTP_REQUEST_PARSER

Functions

int HTTP_REQUEST_PARSER_init (HTTP_REQUEST_PARSER *parser, HTTP_REQ_HEADER_PARSED header_parsed, HTTP_REQ_MESSAGE_BODY_DATA on_message_body_data, HTTP_REQ_FINISHED on_request_finished, void *ctx)
 initialise request parser object
PARSER_STATUS HTTP_REQUEST_PARSER_process (HTTP_REQUEST_PARSER *parser, HTTP_REQUEST *request, BF *data)
 parse a http request

Detailed Description

parser of http requests


Typedef Documentation


Function Documentation

int HTTP_REQUEST_PARSER_init ( HTTP_REQUEST_PARSER parser,
HTTP_REQ_HEADER_PARSED  header_parsed,
HTTP_REQ_MESSAGE_BODY_DATA  on_message_body_data,
HTTP_REQ_FINISHED  on_request_finished,
void *  ctx 
)

initialise request parser object

Definition at line 646 of file http.c.

{
  parser->ctx = ctx;
  parser->ev_header  = header_parsed;
  parser->ev_body = on_message_body_data;
  parser->ev_finish = on_request_finished;
     
  if (HTTP_PARSER_init( &parser->base )) {
    return -1;
  }
 
  if (init_parsers_request_header( &parser->base ) ||
      init_parsers_general_header( &parser->base ) ) {
    return -1;
  }
 
  return 0;
}
PARSER_STATUS HTTP_REQUEST_PARSER_process ( HTTP_REQUEST_PARSER parser,
HTTP_REQUEST request,
BF *  data 
)

parse a http request

Returns:
0 - done parsing, 1 need more data, -1 error occured.

Definition at line 671 of file http.c.

{
  int rt, eof_header;


  while(1) {
   switch( parser->base.state ) {
    case HTTP_STATE_PARSING_REQUEST_LINE:
      rt = parse_request_line( request, bf );
      if (rt != 0) {
       goto req_do_return;
      }
      parser->base.state = HTTP_STATE_PARSING_HEADERS; // 
   //break; - fall through


    case HTTP_STATE_PARSING_HEADERS:
      rt = HTTP_parse_header_line( (HTTP_PARSER *) parser, (HTTP_MESSAGE *) request, bf, &eof_header );
      if (rt != 0) {
        goto req_do_return;
      }

      if (eof_header) {
#if 0
          // this check will we done by web server; if no host header then send back HTTP status 400.

          // if http 1.1 then host header is a must. no host header is an error.
          if (request->version ==  HTTP_VERSION_1_1 &&
              !request->has_host_header) {
            return PARSER_STATUS_ERROR;  
          }
#endif    

          // eof parsing http header.
          if (parser->ev_header( request, parser->ctx )) {
            return PARSER_STATUS_ERROR; 
          }
          BF_compact(bf);

          if (request->base.flags & HTTP_MESSAGE_FLAG_TRANSFER_CHUNKED) {
             HTTP_PARSER_chunked_data_init( &parser->base );
             continue;  
          }

 
          if (request->base.flags & HTTP_MESSAGE_FLAG_HAS_CONTENT_LENGTH) {
             HTTP_PARSER_content_length_init( &parser->base, &request->base );
             continue;  
          }

next_request:
          if (parser->ev_finish( request, parser->ctx )) {
            return PARSER_STATUS_ERROR;
          }
          parser->base.state = HTTP_STATE_PARSING_REQUEST_LINE; 
          HTTP_REQUEST_free(request);  
          return PARSER_STATUS_COMPLETED;
      }
      break;

    case HTTP_STATE_PARSING_BODY_CONTENT_LENGTH:
      rt = HTTP_PARSER_content_length_process( 
                &parser->base, bf, 
                (HTTP_PROCESS_MSG_DATA) parser->ev_body, 
                &request->base, parser->ctx);
      if (rt != 0) {
        goto req_do_return;
      }
      goto next_request;

    default: // remaining states deal with chunks
      rt =  HTTP_PARSER_chunked_data_process( 
                &parser->base, bf, 
                (HTTP_PROCESS_MSG_DATA) parser->ev_body, 
                &request->base, parser->ctx);

      if (rt != 0) {
        goto req_do_return;
      }
      goto next_request;
    }
  }

req_do_return:
  if (rt ==  PARSER_STATUS_NEED_MORE_DATA) {
    BF_compact( bf );
  }
  return rt;
}