| 195 | } |
| 196 | |
| 197 | bool |
| 198 | InterceptPlugin::doRead() |
| 199 | { |
| 200 | int avail = TSIOBufferReaderAvail(state_->input_.reader_); |
| 201 | if (avail == TS_ERROR) { |
| 202 | LOG_ERROR("Error while getting number of bytes available"); |
| 203 | return false; |
| 204 | } |
| 205 | |
| 206 | int consumed = 0; // consumed is used to update the input buffers |
| 207 | if (avail > 0) { |
| 208 | int64_t num_body_bytes_in_block; |
| 209 | int64_t data_len; // size of all data (header + body) in a block |
| 210 | const char *data, *startptr; |
| 211 | TSIOBufferBlock block = TSIOBufferReaderStart(state_->input_.reader_); |
| 212 | while (block != nullptr) { |
| 213 | startptr = data = TSIOBufferBlockReadStart(block, state_->input_.reader_, &data_len); |
| 214 | num_body_bytes_in_block = 0; |
| 215 | if (!state_->hdr_parsed_) { |
| 216 | const char *endptr = data + data_len; |
| 217 | if (TSHttpHdrParseReq(state_->http_parser_, state_->hdr_buf_, state_->hdr_loc_, &data, endptr) == TS_PARSE_DONE) { |
| 218 | LOG_DEBUG("Parsed header"); |
| 219 | string content_length_str = state_->request_headers_.value("Content-Length"); |
| 220 | if (!content_length_str.empty()) { |
| 221 | const char *start_ptr = content_length_str.data(); |
| 222 | char *end_ptr; |
| 223 | int content_length = strtol(start_ptr, &end_ptr, 10 /* base */); |
| 224 | if ((errno != ERANGE) && (end_ptr != start_ptr) && (*end_ptr == '\0')) { |
| 225 | LOG_DEBUG("Got content length: %d", content_length); |
| 226 | state_->expected_body_size_ = content_length; |
| 227 | } else { |
| 228 | LOG_ERROR("Invalid content length header [%s]; Assuming no content", content_length_str.c_str()); |
| 229 | } |
| 230 | } |
| 231 | if (state_->request_headers_.value("Transfer-Encoding") == "chunked") { |
| 232 | // implementing a "dechunker" is non-trivial and in the real |
| 233 | // world, most browsers don't send chunked requests |
| 234 | LOG_ERROR("Support for chunked request not implemented! Assuming no body"); |
| 235 | } |
| 236 | LOG_DEBUG("Expecting %d bytes of request body", state_->expected_body_size_); |
| 237 | state_->hdr_parsed_ = true; |
| 238 | // remaining data in this block is body; 'data' will be pointing to first byte of the body |
| 239 | num_body_bytes_in_block = endptr - data; |
| 240 | } |
| 241 | consume(string(startptr, data - startptr), InterceptPlugin::REQUEST_HEADER); |
| 242 | } else { |
| 243 | num_body_bytes_in_block = data_len; |
| 244 | } |
| 245 | if (num_body_bytes_in_block) { |
| 246 | state_->num_body_bytes_read_ += num_body_bytes_in_block; |
| 247 | consume(string(data, num_body_bytes_in_block), InterceptPlugin::REQUEST_BODY); |
| 248 | } |
| 249 | consumed += data_len; |
| 250 | block = TSIOBufferBlockNext(block); |
| 251 | } |
| 252 | } |
| 253 | LOG_DEBUG("Consumed %d bytes from input vio", consumed); |
| 254 | TSIOBufferReaderConsume(state_->input_.reader_, consumed); |
nothing calls this directly
no test coverage detected