public static bool ValidateHttpHeaders(HttpPacket packet) { if (!packet.Headers.ContainsKey(CONTENTTYPE)) { throw new HttpProtocolException("Mandatory Content-Type header not found."); } string contentTypeHeader = packet.Headers[CONTENTTYPE]; string[] contentTypeDefinitions = contentTypeHeader.Split(';'); if (contentTypeDefinitions.Length == 0) { throw new HttpProtocolException("Content-Type not defined"); } else { string contentType = contentTypeDefinitions[0]; // todo: remove this? if (StringComparer.InvariantCultureIgnoreCase.Compare(contentType, APPLICATIONSOAPXML) != 0) { //throw new HttpProtocolException(string.Format("Content-Type mismatch; expected: application/soap+xml, actual: {0}", contentType)); } packet.ContentType = contentType; for (int i = 1; i < contentTypeDefinitions.Length; i++) { string[] parameters = contentTypeDefinitions[i].Trim().Split('='); if (parameters.Length > 1) { if (StringComparer.InvariantCultureIgnoreCase.Compare(parameters[0], "charset") == 0) { packet.Encoding = parameters[1].Trim(); if (StringComparer.InvariantCultureIgnoreCase.Compare(packet.Encoding, UTF8) != 0) { throw new HttpProtocolException(string.Format("Charset mismatch. Expected: utf-8, actual: {0}", packet.Encoding)); } } } } } return(true); }
public static bool ContinueReading(MemoryStream responseStream, out HttpPacket header) { System.Diagnostics.Debug.WriteLine("check if we still have to wait for message."); MemoryStream streamCopy = new MemoryStream(responseStream.GetBuffer()); StreamReader rdr = new StreamReader(streamCopy); header = new HttpPacket(); int contentLength = 0; int bodyOffset = 0; bool bFound = false; bool bFirst = true; bool noBodySupposed = false; while (!rdr.EndOfStream) { string nextLine = rdr.ReadLine(); System.Diagnostics.Debug.WriteLine(nextLine); bodyOffset += (2 + nextLine.Length); if (nextLine == null) { System.Diagnostics.Debug.WriteLine("NULL instead of line"); break; } if (bFirst) { // Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF string[] statusParts = nextLine.Split(' '); if (statusParts.Length > 2) { string code = statusParts[1].Trim(); header.HttpVersion = statusParts[0]; header.StatusCode = int.Parse(code); header.StatusDescription = statusParts[2]; if (code == "204" || code == "304" || code.StartsWith("1")) { System.Diagnostics.Debug.WriteLine("No body supposed"); noBodySupposed = true; } } else { throw new HttpProtocolException(string.Format("The first line of a Response message is incorrect: {0}", nextLine)); } bFirst = false; } else { // header: header-field = field-name ":" OWS [ field-value ] OWS // field-name = token // field-value = *( field-content / OWS ) // field-content = *( WSP / VCHAR / obs-text ) int colonPos = nextLine.IndexOf(':'); if (colonPos > 0) { string headerName = nextLine.Substring(0, colonPos).Trim(); string headerValue = nextLine.Substring(colonPos + 1).Trim(); header.Headers.Add(headerName, headerValue); if (StringComparer.InvariantCultureIgnoreCase.Compare(headerName, CONTENTLENGTH) == 0) { System.Diagnostics.Debug.WriteLine(string.Format("Content-Length found: {0}", headerValue)); if (!int.TryParse(headerValue, out contentLength)) { throw new HttpProtocolException(string.Format("Content-Length incorrect: {0}, integer expected", headerValue)); } header.ContentLength = contentLength; } } else { if (string.IsNullOrEmpty(nextLine)) { System.Diagnostics.Debug.WriteLine("Empty line - end of headers"); bFound = true; break; } else { throw new HttpProtocolException(string.Format("Unexpected header format: {0}", nextLine)); } } } } header.BodyOffset = bodyOffset; // empty line found - body can be checked if (bFound) { // message must not have a body; if (noBodySupposed) { System.Diagnostics.Debug.WriteLine("Stop read"); return(false); } else { if (contentLength <= responseStream.Length - bodyOffset) { System.Diagnostics.Debug.WriteLine("Content length OK - stop read"); return(false); } else { System.Diagnostics.Debug.WriteLine("Content length NOT OK, continue reading"); } } } return(true); }
public Message Request(Message message, TimeSpan timeout) { Message message3 = null; // check input parameters if (message == null) { throw new ArgumentNullException("message"); } if (timeout < TimeSpan.Zero) { throw new ArgumentOutOfRangeException("timeout"); } // check if underling stream has not been closed by the server _networkStream.EnsureOpen(); base.ThrowIfDisposedOrNotOpen(); // clear headers message.Headers.Clear(); // send message WriteMessageToStream(message); // Start reading // Wait first byte for timeout.TotalMilliseconds int readTimeout = (int)timeout.TotalMilliseconds; // initialize variables MemoryStream responseStream = new MemoryStream(); int bytes = 0; byte[] responseBuffer = new byte[2048]; bool bContinue = false; HttpPacket header = null; // read response do { IAsyncResult result = _networkStream.BeginRead(responseBuffer, 0, responseBuffer.Length); // wait for bytes receied, stop event or timeout WaitHandle[] handles; if (_executionController != null && _executionController.StopEvent != null) { handles = new WaitHandle[] { result.AsyncWaitHandle, _executionController.StopEvent }; } else { handles = new WaitHandle[] { result.AsyncWaitHandle }; } int handle = System.Threading.WaitHandle.WaitAny(handles, readTimeout); if (handle == WaitHandle.WaitTimeout) { _networkStream.Close(true); throw new IOException("The HTTP request has exceeded the allotted timeout"); } if (handle == 1) { System.Diagnostics.Debug.WriteLine("Stop event"); throw new StopEventException("Stop waiting for the answer"); } bytes = _networkStream.EndRead(result); responseStream.Write(responseBuffer, 0, bytes); // timeout for next part of answer readTimeout = READTIMEOUT; // parse response received by this moment. try { bContinue = HttpHelper.ContinueReading(responseStream, out header); } catch (Exception exc) { // clean resources somehow ? throw new Exception("An error occurred while parsing HTTP packet", exc); } }while (_networkStream.DataAvailable || bContinue); int count = (int)responseStream.Length - header.BodyOffset; if (header.ContentLength < count) { throw new HttpProtocolException( string.Format("An error occurred while receiving packet. Expected length: {0}, received: {1}", header.ContentLength, count)); } // validate headers HttpHelper.ValidateHttpHeaders(header); // check if connection is to be closed if (header.Headers.ContainsKey("Connection")) { string connState = header.Headers["Connection"]; if (connState.ToLower() == "close") { _networkStream.Close(true); } } // parse response string response = Encoding.UTF8.GetString(responseStream.GetBuffer()); foreach (ITrafficListener listener in _listeners) { listener.LogResponse(response); } int start = header.BodyOffset; if (start >= 0) { byte[] buffer = bufferManager.TakeBuffer(count); Array.Copy(responseStream.GetBuffer(), start, buffer, 0, count); message3 = _encoder.ReadMessage(new ArraySegment <byte>(buffer, 0, count), bufferManager); bufferManager.ReturnBuffer(buffer); if (message3.IsFault) { Console.WriteLine("FAULT"); ThrowFaultException(message3); } } else { throw new ProtocolException(string.Format("The server returned unexpected reply: {0} {1}", header.StatusCode, header.StatusDescription)); } return(message3); }