void RequestRead(TSession * const sessionP, uint32_t const timeout, const char ** const errorP, uint16_t * const httpErrorCodeP) { /*---------------------------------------------------------------------------- Read the headers of a new HTTP request (assuming nothing has yet been read on the session). Update *sessionP with the information from the headers. Leave the connection positioned to the body of the request, ready to be read by an HTTP request handler (via SessionRefillBuffer() and SessionGetReadData()). -----------------------------------------------------------------------------*/ time_t const deadline = time(NULL) + timeout; uint16_t httpErrorCode; /* zero for no error */ char * requestLine; /* In connection;s internal buffer */ readRequestHeader(sessionP, deadline, &requestLine, &httpErrorCode); if (httpErrorCode) { xmlrpc_asprintf(errorP, "Problem getting the request header"); *httpErrorCodeP = httpErrorCode; } else { TMethod httpMethod; const char * host; const char * path; const char * query; unsigned short port; bool moreHeaders; parseRequestLine(requestLine, &httpMethod, &sessionP->version, &host, &port, &path, &query, &moreHeaders, &httpErrorCode); if (httpErrorCode) { xmlrpc_asprintf(errorP, "Unable to parse the request header " "'%s'", requestLine); *httpErrorCodeP = httpErrorCode; } else { initRequestInfo(&sessionP->requestInfo, sessionP->version, requestLine, httpMethod, host, port, path, query); if (moreHeaders) { readAndProcessHeaders(sessionP, deadline, errorP, httpErrorCodeP); } else *errorP = NULL; if (!*errorP) sessionP->validRequest = true; xmlrpc_strfreenull(host); xmlrpc_strfree(path); xmlrpc_strfreenull(query); } } }
//Parses the request QTSS_Error HTTPRequest::Parse() { Assert(fRequestHeader.Ptr != NULL); StringParser parser(&fRequestHeader); // Store the request line (used for logging) // (ex: GET /index.html HTTP/1.0) StringParser requestLineParser(&fRequestHeader); requestLineParser.ConsumeUntil(&fRequestLine, StringParser::sEOLMask); // Parse request line returns an error if there is an error in the // request URI or the formatting of the request line. // If the method or version are not found, they are set // to httpIllegalMethod or httpIllegalVersion respectively, // and QTSS_NoErr is returned. QTSS_Error err = QTSS_NoErr; do { err = parseRequestLine(&parser); if (err != QTSS_NoErr) return err; } while (fHTTPType == httpIllegalType); // Parse headers and set values of headers into fFieldValues array err = parseHeaders(&parser); if (err != QTSS_NoErr) return err; return QTSS_NoErr; }
/** * @brief Parse socket data. * @param [in] s The socket from which to retrieve data. */ void HttpParser::parse(Socket s) { std::string line; line = s.readToDelim(lineTerminator); parseRequestLine(line); line = s.readToDelim(lineTerminator); while(!line.empty()) { m_headers.insert(parseHeader(line)); line = s.readToDelim(lineTerminator); } // Only PUT and POST requests have a body if (getMethod() != "POST" && getMethod() != "PUT") { return; } // We have now parsed up to and including the separator ... we are now at the point where we // want to read the body. There are two stories here. The first is that we know the exact length // of the body or we read until we can't read anymore. if (hasHeader(HttpRequest::HTTP_HEADER_CONTENT_LENGTH)) { std::string val = getHeader(HttpRequest::HTTP_HEADER_CONTENT_LENGTH); int length = std::atoi(val.c_str()); uint8_t data[length]; s.receive_cpp(data, length, true); m_body = std::string((char *)data, length); } else { uint8_t data[512]; int rc = s.receive_cpp(data, sizeof(data)); m_body = std::string((char *)data, rc); } ESP_LOGD(LOG_TAG, "Size of body: %d", m_body.length()); } // parse
HttpParser::status_t HttpParser::addBytes( const char* bytes, unsigned len ) { if ( _status != Incomplete ) { return _status; } // append the bytes to data. _data.append( bytes, len ); if ( _state < p_content ) { parseHeader(); } if ( _state == p_error ) { _status = Error; } else if ( _state == p_content ) { if ( _contentLength == 0 || _data.length() - _contentStart >= _contentLength ) { if ( parseRequestLine() ) { _status = Done; } else { _status = Error; } } } return _status; }
/** * Process http request headers (until CRLFCRLF) * Check request line and parse headers * @param input lines that form the request line and headers */ void Socket::processHeaders(const string &input){ string line; size_t offset=0; syslog(LOG_DEBUG,"processHeaders: %s",input.c_str()); do line=Util::getLine(input,offset); while(line.size()==0 && offset< input.size()); parseRequestLine(line); while((line=Util::getLine(input,offset)).size()){ parseHeader(line); } }
ApiMock::RequestData ApiMock::RequestParser::parse(const std::string& requestBuffer) { std::vector<std::string> r = projectToCollection(requestBuffer); RequestData request; parseRequestLine(&request, r[0]); for (unsigned i = 1; i < r.size(); ++i) { if (r[i] == "") { parseRequestBody(&request, r, i + 1); break; } parseHeader(&request, r[i]); } return request; }
Http_t Parse_parse (int fd) { http400 = generate400(); getToken(fd, 1); ReqLine_t reqline; Http_t http = 0; reqline = parseRequestLine (fd); parseHeaders(fd); if (token.kind!=TOKEN_CRLF) parseError(fd); parseBody(fd); http = Http_new (HTTP_KIND_REQUEST , reqline , 0 , 0 , 0); if (DEBUG) Http_print (1, http); return http; }
abyss_bool RequestRead(TSession * const sessionP) { uint16_t httpErrorCode; /* zero for no error */ char * requestLine; readRequestLine(sessionP, &requestLine, &httpErrorCode); if (!httpErrorCode) { TMethod httpMethod; const char * host; const char * path; const char * query; unsigned short port; abyss_bool moreHeaders=false; parseRequestLine(requestLine, &httpMethod, &sessionP->version, &host, &port, &path, &query, &moreHeaders, &httpErrorCode); if (!httpErrorCode) initRequestInfo(&sessionP->request_info, sessionP->version, strdup(requestLine), httpMethod, host, port, path, query); while (moreHeaders && !httpErrorCode) { char * p; abyss_bool succeeded; succeeded = ConnReadHeader(sessionP->conn, &p); if (!succeeded) httpErrorCode = 408; /* Request Timeout */ else { if (!*p) /* We have reached the empty line so all the request was read. */ moreHeaders = FALSE; else { char * fieldName; getFieldNameToken(&p, &fieldName, &httpErrorCode); if (!httpErrorCode) { char * fieldValue; NextToken((const char **)&p); fieldValue = p; TableAdd(&sessionP->request_headers, fieldName, fieldValue); processHeader(fieldName, fieldValue, sessionP, &httpErrorCode); } } } } } if (httpErrorCode) ResponseStatus(sessionP, httpErrorCode); else sessionP->validRequest = true; return !httpErrorCode; }
// received a character from UART void GSwifi::parseByte(uint8_t dat) { static uint8_t next_token; // split each byte into tokens (cid,ip,port,length,data) static bool escape = false; char temp[GS_MAX_PATH_LENGTH+1]; if (dat == ESCAPE) { // 0x1B : Escape GSLOG_PRINT("e< "); } else { // if (next_token != NEXT_TOKEN_DATA) { GSLOG_WRITE(dat); } if (gs_mode_ == GSMODE_COMMAND) { if (escape) { // esc switch (dat) { case 'O': case 'F': // ignore break; case 'Z': case 'H': gs_mode_ = GSMODE_DATA_RX_BULK; next_token = NEXT_TOKEN_CID; break; default: // GSLOG_PRINT("!E1 "); GSLOG_PRINTLN2(dat,HEX); break; } escape = false; } else { if (dat == ESCAPE) { escape = true; } else if (dat == '\n') { // end of line parseLine(); } else if (dat != '\r') { if ( ! ring_isfull(_buf_cmd) ) { ring_put(_buf_cmd, dat); } else { GSLOG_PRINTLN("!E2"); } } } return; } else if (gs_mode_ != GSMODE_DATA_RX_BULK) { return; } static uint16_t len; static char len_chars[5]; static int8_t current_cid; static GSREQUESTSTATE request_state; if (next_token == NEXT_TOKEN_CID) { // dat is cid current_cid = x2i(dat); ASSERT((0 <= current_cid) && (current_cid <= 16)); next_token = NEXT_TOKEN_LENGTH; len = 0; } else if (next_token == NEXT_TOKEN_LENGTH) { // Data Length is 4 ascii char represents decimal value i.e. 1400 byte (0x31 0x34 0x30 0x30) len_chars[ len ++ ] = dat; if (len >= 4) { len_chars[ len ] = 0; len = atoi(len_chars); // length of data next_token = NEXT_TOKEN_DATA; if (content_lengths_[ current_cid ] > 0) { // this is our 2nd bulk message from GS for this response // we already swallowed HTTP response headers, // following should be body request_state = GSREQUESTSTATE_BODY; } else { request_state = GSREQUESTSTATE_HEAD1; } ring_clear( _buf_cmd ); // reuse _buf_cmd to store HTTP request } } else if (next_token == NEXT_TOKEN_DATA) { len --; if (cidIsRequest(current_cid)) { // request against us static uint16_t error_code; static int8_t routeid; switch (request_state) { case GSREQUESTSTATE_HEAD1: if (dat != '\n') { if ( ! ring_isfull(_buf_cmd) ) { ring_put( _buf_cmd, dat ); } // ignore overflowed } else { // end of request line // reuse "temp" buffer to parse method and path int8_t result = parseRequestLine((char*)temp, 7); GSMETHOD method = GSMETHOD_UNKNOWN; if ( result == 0 ) { method = x2method(temp); result = parseRequestLine((char*)temp, GS_MAX_PATH_LENGTH); } if ( result != 0 ) { // couldn't detect method or path request_state = GSREQUESTSTATE_ERROR; error_code = 400; ring_clear(_buf_cmd); break; } routeid = router(method, temp); if ( routeid < 0 ) { request_state = GSREQUESTSTATE_ERROR; error_code = 404; ring_clear(_buf_cmd); break; } request_state = GSREQUESTSTATE_HEAD2; continuous_newlines_ = 0; content_lengths_[ current_cid ] = 0; has_requested_with_ = false; ring_clear(_buf_cmd); } break; case GSREQUESTSTATE_HEAD2: if(0 == parseHead2(dat, current_cid)) { request_state = GSREQUESTSTATE_BODY; // dispatched once, at start of body dispatchRequestHandler(current_cid, routeid, GSREQUESTSTATE_BODY_START); } break; case GSREQUESTSTATE_BODY: if (content_lengths_[ current_cid ] > 0) { content_lengths_[ current_cid ] --; } if (ring_isfull(_buf_cmd)) { dispatchRequestHandler(current_cid, routeid, request_state); // POST, user callback should write() } ring_put(_buf_cmd, dat); break; case GSREQUESTSTATE_ERROR: // skip until received whole request break; case GSREQUESTSTATE_RECEIVED: default: break; } // end of bulk transfered data if (len == 0) { gs_mode_ = GSMODE_COMMAND; if ( request_state == GSREQUESTSTATE_ERROR ) { writeHead( current_cid, error_code ); writeEnd(); ring_put( &commands, COMMAND_CLOSE ); ring_put( &commands, current_cid ); } else { if (content_lengths_[ current_cid ] == 0) { // if Content-Length header was longer than <ESC>Z length, // we wait til next bulk transfer request_state = GSREQUESTSTATE_RECEIVED; } // user callback should write(), writeEnd() and close() dispatchRequestHandler(current_cid, routeid, request_state); } ring_clear(_buf_cmd); } } else { // is request from us static uint16_t status_code; switch (request_state) { case GSREQUESTSTATE_HEAD1: if (dat != '\n') { if ( ! ring_isfull(_buf_cmd) ) { // ignore if overflowed ring_put( _buf_cmd, dat ); } } else { uint8_t i=0; // skip 9 characters "HTTP/1.1 " while (i++ < 9) { ring_get( _buf_cmd, &temp[0], 1 ); } // copy 3 numbers representing status code into temp buffer temp[ 3 ] = 0; int8_t count = ring_get( _buf_cmd, temp, 3 ); if (count != 3) { // protocol error // we should receive something like: "200 OK", "401 Unauthorized" status_code = 999; request_state = GSREQUESTSTATE_ERROR; break; } status_code = atoi(temp); request_state = GSREQUESTSTATE_HEAD2; continuous_newlines_ = 0; content_lengths_[ current_cid ] = 0; ring_clear(_buf_cmd); } break; case GSREQUESTSTATE_HEAD2: if(0 == parseHead2(dat, current_cid)) { request_state = GSREQUESTSTATE_BODY; // dispatched once, at start of body dispatchResponseHandler(current_cid, status_code, GSREQUESTSTATE_BODY_START); } break; case GSREQUESTSTATE_BODY: if (content_lengths_[ current_cid ] > 0) { content_lengths_[ current_cid ] --; } if (ring_isfull(_buf_cmd)) { dispatchResponseHandler(current_cid, status_code, GSREQUESTSTATE_BODY); } ring_put(_buf_cmd, dat); break; case GSREQUESTSTATE_ERROR: case GSREQUESTSTATE_RECEIVED: default: break; } if (len == 0) { gs_mode_ = GSMODE_COMMAND; if ( request_state == GSREQUESTSTATE_ERROR ) { dispatchResponseHandler(current_cid, status_code, request_state); } else { if (content_lengths_[ current_cid ] == 0) { // if Content-Length header was longer than <ESC>Z length, // we wait til all response body received. // we need to close our clientRequest before handling it. // GS often locks when closing 2 connections in a row // ex: POST /keys from iPhone (cid:1) -> POST /keys to server (cid:2) // response from server arrives -> close(1) -> close(2) -> lock!! // the other way around: close(2) -> close(1) doesn't lock :( request_state = GSREQUESTSTATE_RECEIVED; } dispatchResponseHandler(current_cid, status_code, request_state); } ring_clear( _buf_cmd ); } } // is response } // (next_token == NEXT_TOKEN_DATA) }