char *test_parser_thrashing() { glob_t test_files; unsigned int i = 0; int nparsed = 0; int delta = 0; int tests_run = 0; int execs_run = 0; int unfinished = 0; int errors = 0; int rc = glob("tests/and_suite/*", 0, NULL, &test_files); mu_assert(rc == 0, "Failed to glob file sin tests/and_suite/*"); for(i = 0; i < test_files.gl_pathc; i++) { FILE *infile = fopen(test_files.gl_pathv[i], "r"); mu_assert(infile != NULL, "Failed to open test file."); bstring data = bread((bNread)fread, infile); fclose(infile); mu_assert(data != NULL, "Failed to read test file."); tests_run++; http_parser p = setup_parser(); nparsed = 0; delta = 0; while(nparsed < blength(data)) { debug("json PARSING: %d of %d at %s", nparsed, blength(data), bdataofs(data, nparsed)); delta = http_parser_execute(&p, bdata(data), blength(data), nparsed); execs_run++; if(delta == 0) { break; } if(!http_parser_finish(&p)) { unfinished++; } nparsed += delta; if(http_parser_has_error(&p)) { errors++; } debug("TEST %s results: delta %d, has_error: %d, is_finished: %d", test_files.gl_pathv[i], nparsed, http_parser_has_error(&p), http_parser_is_finished(&p)); http_parser_init(&p); // reset for the next try } } debug("HTTP PARSING: tests_run: %d, execs_run: %d, unfinished: %d, errors: %d", tests_run, execs_run, unfinished, errors); return NULL; }
/** * call-seq: * parser.error? -> true/false * * Tells you whether the parser is in an error state. */ VALUE HttpParser_has_error(VALUE self) { http_parser *http = NULL; DATA_GET(self, http_parser, http); return http_parser_has_error(http) ? Qtrue : Qfalse; }
/** * call-seq: * parser.execute(req_hash, data, start) -> Integer * * Takes a Hash and a String of data, parses the String of data filling in the Hash * returning an Integer to indicate how much of the data has been read. No matter * what the return value, you should call HttpParser#finished? and HttpParser#error? * to figure out if it's done parsing or there was an error. * * This function now throws an exception when there is a parsing error. This makes * the logic for working with the parser much easier. You can still test for an * error, but now you need to wrap the parser with an exception handling block. * * The third argument allows for parsing a partial request and then continuing * the parsing from that position. It needs all of the original data as well * so you have to append to the data buffer as you read. */ VALUE HttpParser_execute(VALUE self, VALUE req_hash, VALUE data, VALUE start) { http_parser *http = NULL; int from = 0; char *dptr = NULL; long dlen = 0; DATA_GET(self, http_parser, http); from = FIX2INT(start); dptr = RSTRING_PTR(data); dlen = RSTRING_LEN(data); if(from >= dlen) { rb_raise(eHttpParserError, "Requested start is after data buffer end."); } else { http->data = (void *)req_hash; http_parser_execute(http, dptr, dlen, from); VALIDATE_MAX_LENGTH(http_parser_nread(http), HEADER); if(http_parser_has_error(http)) { rb_raise(eHttpParserError, "Invalid HTTP format, parsing fails."); } else { return INT2FIX(http_parser_nread(http)); } } }
static PyObject * HttpParserObject_has_error(HttpParserObject* self) { if (http_parser_has_error(self->http)) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } }
char *test_http11_parser_basics() { http_parser p = setup_parser(); int rc = 0; rc = http_parser_finish(&p); mu_assert(rc == 0, "Should NOT be finished if nothing parsed."); rc = http_parser_has_error(&p); mu_assert(rc == 0, "Should not have an error at the beginning."); rc = http_parser_is_finished(&p); mu_assert(rc == 0, "Should not be finished since never handed anything."); return NULL; }
static void on_read_cb(uv_stream_t *stream, ssize_t nread, uv_buf_t buf) { Connection *conn = (Connection*) stream; assert(conn->read_clear == false); if (nread < 0) { // // XXX: Do we have to call uv_read_stop(), or is it implicit? // // on_read_cb will never be called again for this connection, so we don't // have to reset anything. // uv_close((uv_handle_t*) conn, on_close_cb); } else if (nread > 0) { conn->read_buffer.increase_size(nread); conn->read_clear = true; if (conn->in_body) { // We are reading in the body. No need to call the parser! handle_http_body(conn); } else { conn->parse_offset = http_parser_run(&conn->parser, &conn->req, conn->read_buffer.data(), conn->read_buffer.size(), conn->parse_offset); if (http_parser_is_finished(&conn->parser)) { handle_http_header_parsed(conn); } else if (http_parser_has_error(&conn->parser)) { handle_http_error(conn); } } } else { // // This happens when libuv calls alloc_read_buffer, but does not need the buffer. // We don't have to free the buffer, as it is part of the connection. // assert(nread == 0); conn->read_clear = true; } }
int http_parser_finish(http_parser *parser) { int cs = parser->cs; #line 1202 "http11_parser.c" #line 134 "http11_parser.rl" parser->cs = cs; if (http_parser_has_error(parser) ) { return -1; } else if (http_parser_is_finished(parser) ) { return 1; } else { return 0; } }
int HTTPParser_parseErrorOccured(HTTPParser *self) { return http_parser_has_error(self->parser); }