Request MyParser::parseRequest(char* http, int nbytes) const { const char* CRLF = "\r\n"; std::istringstream iss(http); //MSG("Input: %s", iss.str().c_str()); Request request; // start line std::string start_line; std::getline(iss, start_line); //MSG("start=%s", start_line.c_str()); request.startline = parseStartLine(start_line); // headers std::string header_line; std::vector<Header> headers; while (true) { std::getline(iss, header_line); if (isHeader(header_line)) { Header header = parseHeader(header_line); headers.push_back(header); //MSG("header=%s", header_line.c_str()); } else { break; } } request.headers = headers; // body std::string ending = ""; request.body = ""; std::string line; while (std::getline(iss, line)) { line.erase(std::remove(line.begin(), line.end(), '\r'), line.end()); request.body.append(ending); request.body.append(line); ending = "\n"; } return request; }
static int appendByte(char c, HttpMessage *msg) { int ret = 1; ParserData *pd = (ParserData *)msg->pri_data; switch (pd->state) { case HTTP_STARTLINE: _append(c, msg); if (c == '\r') { pd->last_state = HTTP_STARTLINE; pd->state = HTTP_CR; } break; case HTTP_HEADERS: _append(c, msg); if (c == '\r') { pd->last_state = HTTP_HEADERS; pd->state = HTTP_CR; } break; case HTTP_CR: _append(c, msg); if (c == '\n') { pd->state = HTTP_CRLF; // blank line ? if (!strncmp(pd->linedata, "\r\n", 2)) { if (_getmsglen(msg) > 0) { pd->state = HTTP_BODY; } else { pd->state = HTTP_COMPLETE; } } } else { pd->state = pd->last_state; } break; case HTTP_CRLF: if (isblank(c)) { char *p; // LSW pd->state = HTTP_LSW; p = strstr(pd->linedata, "\r\n"); if (p) { pd->line_datasize = p-pd->linedata; } } else { if (pd->last_state == HTTP_STARTLINE) { parseStartLine(msg); } else { parseHeaderLine(msg); } pd->line_datasize = 0; _append(c, msg); if (c == '\r') pd->state = HTTP_CR; else pd->state = HTTP_HEADERS; } break; case HTTP_LSW: if (!isblank(c)) { pd->state = pd->last_state; _append(c, msg); } break; case HTTP_BODY: msg->body = (char *)realloc(msg->body, msg->bodylen+1); msg->body[msg->bodylen] = c; msg->bodylen++; if (_getmsglen(msg) == msg->bodylen) pd->state = HTTP_COMPLETE; break; case HTTP_COMPLETE: break; } return ret; }
HttpParserImpl::ParseState HttpParserImpl::parseHttp(const char*& cur_pos, const char* end) { const char* line = nullptr; const char* line_end = nullptr; bool b_line = false; if(HTTP_READ_LINE == read_state_) {// try to get status line while ((b_line = getLine(cur_pos, end, line, line_end)) && line == line_end && str_buf_.empty()) ; if(b_line && (line != line_end || !str_buf_.empty())) { if(!parseStartLine(line, line_end)) { read_state_ = HTTP_READ_ERROR; return PARSE_STATE_ERROR; } read_state_ = HTTP_READ_HEAD; } else { // need more data if(saveData(cur_pos, end) != KUMA_ERROR_NOERR) { return PARSE_STATE_ERROR; } cur_pos = end; // all data was consumed return PARSE_STATE_CONTINUE; } } if(HTTP_READ_HEAD == read_state_) { while ((b_line = getLine(cur_pos, end, line, line_end))) { if(line == line_end && bufferEmpty()) {// blank line, header completed onHeaderComplete(); if(paused_) { return PARSE_STATE_CONTINUE; } if(hasBody() && !upgrade_) { read_state_ = HTTP_READ_BODY; } else { read_state_ = HTTP_READ_DONE; onComplete(); return PARSE_STATE_DONE; } break; } parseHeaderLine(line, line_end); } if(HTTP_READ_HEAD == read_state_) {// need more data if(saveData(cur_pos, end) != KUMA_ERROR_NOERR) { return PARSE_STATE_ERROR; } cur_pos = end; // all data was consumed return PARSE_STATE_CONTINUE; } } if(HTTP_READ_BODY == read_state_ && cur_pos < end) {// try to get body if(is_chunked_) { return parseChunk(cur_pos, end); } else { uint32_t cur_len = uint32_t(end - cur_pos); if(has_content_length_ && (content_length_ - total_bytes_read_) <= cur_len) {// data enough const char* notify_data = cur_pos; uint32_t notify_len = content_length_ - total_bytes_read_; cur_pos += notify_len; total_bytes_read_ = content_length_; read_state_ = HTTP_READ_DONE; KUMA_ASSERT(!destroy_flag_ptr_); bool destroyed = false; destroy_flag_ptr_ = &destroyed; if(cb_data_) cb_data_(notify_data, notify_len); if(destroyed) { return PARSE_STATE_DESTROY; } destroy_flag_ptr_ = nullptr; onComplete(); return PARSE_STATE_DONE; } else {// need more data, or read untill EOF const char* notify_data = cur_pos; total_bytes_read_ += cur_len; cur_pos = end; if(cb_data_) cb_data_(notify_data, cur_len); return PARSE_STATE_CONTINUE; } } } return HTTP_READ_DONE == read_state_?PARSE_STATE_DONE:PARSE_STATE_CONTINUE; }