void httpClient_RecvBody(HttpResponse httpResp) { this.body.Clear(); int read = 0; // HTTP client calls this callback more times until response body finished if ((read = httpResp.Body.Read(this.buffer, 0, BUFFER_SIZE)) > 0) { body.Append(Encoding.UTF8.GetChars(this.buffer, 0, read)); } }
/// <summary> /// Raise receving body event /// </summary> /// <param name="httpResp">HTTP response for reading body</param> private void OnReceivingBody(HttpResponse httpResp) { if (this.ReceivingBody != null) this.ReceivingBody(httpResp); }
/// <summary> /// Constructor /// </summary> internal HttpResponseParser() { // initialize parser state this.state = HttpResponseParserState.ResponseLine; this.lineState = HttpResponseLineState.Idle; #if !MF_FRAMEWORK_VERSION_V4_1 this.lineBuilder = new StringBuilder(); #else this.lineBuilder = String.Empty; #endif // create HTTP response object and assign read method for body response this.response = new HttpResponse(); this.response.Body.Read = this.ReadBody; }
/// <summary> /// Execute HTTP response parsing /// </summary> /// <param name="buffer">Buffer with HTTP response bytes</param> /// <param name="size">Number of bytes</param> /// <returns>Parsing result</returns> internal HttpResponseParserResult Parse(byte[] buffer, int size) { this.result = HttpResponseParserResult.NotCompleted; this.parsed = 0; this.remaining = 0; this.buffer = buffer; this.size = size; // entire size is remaining bytes to parser this.remaining = this.size; while (this.remaining > 0) { switch (this.state) { // waiting for response line, start of HTTP response case HttpResponseParserState.ResponseLine: this.parsed += this.ExtractLine(this.buffer, this.parsed, this.size); // response line extracted if (this.lineState == HttpResponseLineState.End) { try { string[] token = this.lineBuilder.ToString().Split(HttpBase.RESPONSE_LINE_SEPARATOR); // set HTTP protocol, status code and reason phrase this.response.HttpProtocol = token[0]; this.response.StatusCode = (HttpStatusCode)Convert.ToInt32(token[1]); if (token.Length == 3) this.response.ReasonPhrase = token[2]; else { this.response.ReasonPhrase = string.Empty; for (int i = 2; i < token.Length; i++) this.response.ReasonPhrase += token[i]; } // change parser state for waiting headers this.state = HttpResponseParserState.Headers; // reset extract line parser state this.lineState = HttpResponseLineState.Idle; #if !MF_FRAMEWORK_VERSION_V4_1 this.lineBuilder.Clear(); #else this.lineBuilder = String.Empty; #endif } catch { this.result = HttpResponseParserResult.Malformed; } } this.remaining = (this.size - this.parsed); break; // receiving HTTP headers case HttpResponseParserState.Headers: this.parsed += this.ExtractLine(this.buffer, this.parsed, this.size); // line extracted if (this.lineState == HttpResponseLineState.End) { // header line if (this.lineBuilder.Length > 0) { string headerLine = this.lineBuilder.ToString(); // add header to response (key and value) this.response.Headers.Add( headerLine.Substring(0, headerLine.IndexOf(HttpBase.HEADER_VALUE_SEPARATOR)).Trim(), headerLine.Substring(headerLine.IndexOf(HttpBase.HEADER_VALUE_SEPARATOR) + 1).Trim() ); } // empty line, headers end else { // body chunked or not if ((this.response.ContentLength > 0) || (this.response.TransferEncoding != null)) { this.bodyRemaining = (this.response.ContentLength > 0) ? this.response.ContentLength : 0; if (this.response.TransferEncoding != null) this.isChunked = (this.response.TransferEncoding.Equals(HttpBase.TRANSFER_ENCODING_CHUNKED)); this.state = HttpResponseParserState.Body; } // no body, HTTP response end else { this.result = HttpResponseParserResult.Completed; this.state = HttpResponseParserState.ResponseLine; } } // reset extract line parser state this.lineState = HttpResponseLineState.Idle; #if !MF_FRAMEWORK_VERSION_V4_1 this.lineBuilder.Clear(); #else this.lineBuilder = String.Empty; #endif } this.remaining = (this.size - this.parsed); break; // receiving body case HttpResponseParserState.Body: // body chunked and no chunk size already found if ((this.isChunked) && (this.bodyRemaining == 0)) { this.parsed += this.ExtractLine(this.buffer, this.parsed, this.size); // line extracted if (this.lineState == HttpResponseLineState.End) { // line contains chunk size if (this.lineBuilder.Length > 0) { this.bodyRemaining = Convert.ToInt32(this.lineBuilder.ToString(), 16); } // empty line, body chunked end else { this.result = HttpResponseParserResult.Completed; this.state = HttpResponseParserState.ResponseLine; } // reset extract line parser state this.lineState = HttpResponseLineState.Idle; #if !MF_FRAMEWORK_VERSION_V4_1 this.lineBuilder.Clear(); #else this.lineBuilder = String.Empty; #endif } this.remaining = (this.size - this.parsed); } // read body or chunk else { // raise event for allow client to read body response this.OnReceivingBody(this.response); this.remaining = (this.size - this.parsed); } break; default: break; } // HTTP response malfomerd, break if (this.result == HttpResponseParserResult.Malformed) { this.response = null; break; } } return this.result; }
void parser_ReceivingBody(HttpResponse httpResp) { // receiving body response from parse, raise event to the client this.OnRecvBody(httpResp); }