|
Server 0.0.1
HTTP/REST server implementation
|
#include "class.h"#include "http/message.h"#include "http/message/queue.h"#include "cbuf.h"#include "stream.h"#include "commons.h"

Go to the source code of this file.
Data Structures | |
| struct | HttpParser |
Defines | |
| #define | PARSER_MAX_BUF 131072 |
Typedefs | |
| typedef enum e_HttpMessageState | HttpMessageState |
Enumerations | |
| enum | e_HttpMessageState { HTTP_MESSAGE_GARBAGE = 0, HTTP_MESSAGE_START, HTTP_MESSAGE_INTRO_DONE, HTTP_MESSAGE_HEADERS_DONE, HTTP_MESSAGE_DONE } |
Functions | |
| ssize_t | httpParserParse (void *, Stream) |
| void | httpParserRequestVars (HttpParser) |
| void | httpParserHeader (HttpParser, const char *, const char *) |
| void | httpParserNewMessage (HttpParser, const char *, const char *lend) |
| size_t | httpParserBody (HttpParser, const char *, size_t) |
| void | httpParserPostVars (HttpParser) |
Parse requests from an input stream.
Copyright © 2012 Georg Hopp
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
Definition in file parser.h.
| typedef enum e_HttpMessageState HttpMessageState |
| enum e_HttpMessageState |
| size_t httpParserBody | ( | HttpParser | , |
| const char * | , | ||
| size_t | |||
| ) |
| void httpParserHeader | ( | HttpParser | , |
| const char * | , | ||
| const char * | |||
| ) |
Definition at line 35 of file p_header.c.
{
const char * name = line;
char * value = memchr(line, ':', lend - line);
size_t nname = (value++) - name;
HttpMessage current = this->current;
if (NULL == value) {
return;
}
for (; *value == ' ' && value < lend; value++);
if (value == lend) {
return;
}
if (0 == strncasecmp("content-length", name, nname-1)) {
current->nbody = strtoul(value, NULL, 10);
if (0 < this->current->nbody) {
current->body = malloc(current->nbody);
}
current->dbody = 0;
}
if (0 == strncasecmp("cookie", name, nname-1)) {
HttpRequest request = (HttpRequest)this->current;
char * pair = value;
ssize_t togo = lend - value;
while(NULL != pair && 0 < togo) {
char * key = pair;
char * eqsign;
char * val;
size_t nval;
for (; *key == ' ' && key < lend; key++, togo--);
eqsign = memchr(key, '=', togo);
if (NULL == eqsign) {
break;
}
togo -= (eqsign - key);
pair = memchr(eqsign, ';', togo);
if (NULL == pair) {
pair = (char *)lend;
}
nval = pair-eqsign-1;
val = (0 != nval)? eqsign+1 : NULL;
hashAdd(request->cookies,
new(HashValue, key, eqsign-key, val, nval));
pair++;
togo -= (pair - eqsign);
}
}
hashAdd(current->header,
new(HttpHeader, name, nname, value, lend - value));
}


| void httpParserNewMessage | ( | HttpParser | , |
| const char * | , | ||
| const char * | lend | ||
| ) |
Definition at line 28 of file new_message.c.
{
const char * part1, * part2, * part3;
size_t len1, len2, len3;
part1 = line;
part2 = memchr(line, ' ', lend - line);
if (NULL == part2) return;
len1 = part2 - part1;
for (; *part2 == ' ' && *part2 != 0; part2++);
part3 = memchr(part2, ' ', lend - part2);
if (NULL == part3) return;
len2 = part3 - part2;
for (; *part3 == ' ' && *part3 != 0; part3++);
len3 = lend - part3;
this->current = httpGetMessage(part1, len1, part2, len2, part3, len3);
}


| ssize_t httpParserParse | ( | void * | , |
| Stream | |||
| ) |
do we have form data??
> then parse them...
enqueue current request
prepare for next request
Definition at line 40 of file parse.c.
{
HttpParser this = _this;
int cont = 1;
ssize_t read;
char * line;
char * line_end;
if (cbufIsLocked(this->buffer)) {
if (FALSE == this->ourLock)
return 0;
}
else {
cbufLock(this->buffer);
this->ourLock = TRUE;
}
if (NULL != this->incomplete) {
cbufSetData(this->buffer, this->incomplete, this->isize);
free(this->incomplete);
this->incomplete = NULL;
}
if (0 > (read = cbufRead(this->buffer, st))) {
return read;
}
while (cont) {
switch(this->state) {
case HTTP_MESSAGE_GARBAGE:
cbufSkipNonAlpha(this->buffer);
if (! cbufIsEmpty(this->buffer)) {
this->state = HTTP_MESSAGE_START;
}
else {
cbufRelease(this->buffer);
this->ourLock = FALSE;
cont = 0;
}
break;
case HTTP_MESSAGE_START:
if (NULL == (line = cbufGetLine(this->buffer, &line_end))) {
if (! cbufIsEmpty(this->buffer)) {
this->isize = this->buffer->bused;
this->incomplete = malloc(this->isize);
memcpy(this->incomplete,
cbufGetData(this->buffer, this->isize),
this->isize);
}
cbufRelease(this->buffer);
this->ourLock = FALSE;
cont = 0;
break;
}
httpParserNewMessage(this, line, line_end);
if (NULL == this->current) {
cbufRelease(this->buffer);
this->ourLock = FALSE;
return -1;
}
httpParserRequestVars(this);
this->state = HTTP_MESSAGE_INTRO_DONE;
break;
case HTTP_MESSAGE_INTRO_DONE:
if (NULL == (line = cbufGetLine(this->buffer, &line_end))) {
if (! cbufIsEmpty(this->buffer)) {
this->isize = this->buffer->bused;
this->incomplete = malloc(this->isize);
memcpy(this->incomplete,
cbufGetData(this->buffer, this->isize),
this->isize);
}
cbufRelease(this->buffer);
this->ourLock = FALSE;
cont = 0;
break;
}
if (0 == strlen(line)) {
this->state = HTTP_MESSAGE_HEADERS_DONE;
break;
}
httpParserHeader(this, line, line_end);
break;
case HTTP_MESSAGE_HEADERS_DONE:
if (this->current->dbody == this->current->nbody) {
this->state = HTTP_MESSAGE_DONE;
break;
}
if (cbufIsEmpty(this->buffer)) {
cbufRelease(this->buffer);
this->ourLock = FALSE;
cont = 0;
break;
}
cbufIncRead(
this->buffer,
httpParserBody(
this,
cbufGetRead(this->buffer),
this->buffer->bused));
break;
case HTTP_MESSAGE_DONE:
{
HttpHeader enc = hashGet(
this->current->header,
CSTRA("content-type"));
if (NULL != enc && 0 == strncasecmp(
"application/x-www-form-urlencoded",
enc->value[0],
MIN(sizeof("application/x-www-form-urlencoded")-1,
enc->nvalue[0]))) {
httpParserPostVars(this);
}
this->queue->msgs[(this->queue->nmsgs)++] = this->current;
this->current = NULL;
this->state = HTTP_MESSAGE_GARBAGE;
}
break;
default:
break;
}
}
return this->queue->nmsgs;
}


| void httpParserPostVars | ( | HttpParser | this | ) |
Definition at line 37 of file p_post_vars.c.
{
HttpRequest request = (HttpRequest)this->current;
char * pair = this->current->body;
ssize_t togo = this->current->nbody;
while(NULL != pair && 0 < togo) {
char * key = pair;
char * eqsign = memchr(key, '=', togo);
char * value;
size_t nvalue;
if (NULL == eqsign) {
return;
}
togo -= (eqsign - key);
pair = memchr(eqsign, '&', togo);
if (NULL == pair) {
pair = &(this->current->body[this->current->nbody]);
}
nvalue = pair-eqsign-1;
value = (0 != nvalue)? eqsign+1 : NULL;
hashAdd(request->post,
new(HashValue, key, eqsign-key, value, nvalue));
pair++;
togo -= (pair - eqsign);
}
}


| void httpParserRequestVars | ( | HttpParser | ) |
Definition at line 33 of file p_request_vars.c.
{
HttpRequest request = (HttpRequest)this->current;
char * delim = strchr(request->uri, '?');
if (NULL == delim) {
delim = request->uri + strlen(request->uri);
}
request->path = malloc(delim - request->uri + 1);
request->path[delim - request->uri] = 0;
memcpy(request->path, request->uri, delim - request->uri);
while(NULL != delim && 0 != *delim) {
char * key = delim + 1;
char * eqsign = strchr(key, '=');
char * value;
size_t nvalue;
if (NULL == eqsign) {
return;
}
delim = strchr(eqsign, '&');
if (NULL == delim) {
delim = key + strlen(key);
}
nvalue = delim-eqsign-1;
value = (0 != nvalue)? eqsign+1 : NULL;
hashAdd(request->get,
new(HashValue, key, eqsign-key, value, nvalue));
}
}

