private bool ParseBatchPart(bool isResponse, TextReader reader, InMemoryWebRequest part, string boundary, string endboundary) { bool result = false; string line; if (isResponse) { part.ParseResponseStatus(reader); } else { part.ParseRequestVerb(reader); } if (isResponse) { part.ResponseHeaders.Clear(); InMemoryWebRequest.ParseHeaders(reader, part.ResponseHeaders); } else { InMemoryWebRequest.ParseHeaders(reader, part.RequestHeaders); InMemoryWebRequest.ApplyHeadersToProperties(part); } StringBuilder sb = new StringBuilder(); string lastLine = null; while ((line = reader.ReadLine()) != null) { if (line == boundary) { break; } if (line == endboundary) { result = true; break; } if (lastLine != null) { sb.AppendLine(lastLine); } lastLine = line; } // The last line must not end with a newline - the batch adds it there, but it's not actually part of the content sb.Append(lastLine); if (isResponse) { part.SetResponseStream(new MemoryStream(Encoding.UTF8.GetBytes(sb.ToString()))); } else { part.SetRequestStreamAsText(sb.ToString()); } return(result); }
public Stream ProcessRequestForMessage(Stream messageBody) { this.response = new StringBuilder(); WebOperationContext c = WebOperationContext.Current; if (InternalProcessRequestOverride != null) { InMemoryWebRequest request = new InMemoryWebRequest(); InMemoryWebRequest response = null; try { request.HttpMethod = c.IncomingRequest.Method; request.RequestUriString = c.IncomingRequest.UriTemplateMatch.RequestUri.AbsoluteUri.Substring(c.IncomingRequest.UriTemplateMatch.BaseUri.AbsoluteUri.Length); foreach (string headerKey in c.IncomingRequest.Headers.AllKeys) { request.RequestHeaders[headerKey] = c.IncomingRequest.Headers[headerKey]; } InMemoryWebRequest.ApplyHeadersToProperties(request); request.SetRequestStream(messageBody); response = InternalProcessRequestOverride(request); } catch (Exception e) { response = new InMemoryWebRequest(); response.SetResponseStatusCode(500); response.SetResponseStreamAsText(CreateErrorPayload(e)); } c.OutgoingResponse.StatusCode = (HttpStatusCode)response.ResponseStatusCode; foreach (var header in response.ResponseHeaders) { c.OutgoingResponse.Headers[header.Key] = header.Value; } if (response.GetResponseStream() != null) { MemoryStream body = new MemoryStream(); System.Data.Test.Astoria.TestUtil.CopyStream(response.GetResponseStream(), body); body.Position = 0; return(body); } else { return(null); } } if (InternalInspectRequestPayload != null) { MemoryStream ms = new MemoryStream(); test.TestUtil.CopyStream(messageBody, ms); messageBody = ms; messageBody.Position = 0; InternalInspectRequestPayload(messageBody); messageBody.Position = 0; } Append("<error xmlns='http://docs.oasis-open.org/odata/ns/metadata'>"); Append("<message>"); Append(c.IncomingRequest.Method + " " + c.IncomingRequest.UriTemplateMatch.RequestUri.OriginalString); Append("\r\n"); Append(c.IncomingRequest.Headers.ToString()); Append("\r\n"); AppendXmlStream(messageBody); Append("</message>"); Append("</error>"); lastPlayback = this.response.ToString(); string result = lastPlayback; if (InternalOverridingPlayback != null) { result = ProcessOverridingPlayback(c); // For batch request, i need to send the exact content id otherwise the client chokes int startIndex = lastPlayback.IndexOf("Content-ID: "); if (startIndex != -1) { // advance the index to the start of the content id startIndex += "Content-ID: ".Length; int endIndex = lastPlayback.IndexOf(Environment.NewLine, startIndex); int contentID = Int32.Parse(lastPlayback.Substring(startIndex, endIndex - startIndex)); int resultStartIndex = result.IndexOf("Content-ID: ") + "Content-ID: ".Length; int resultEndIndex = result.IndexOf(Environment.NewLine, resultStartIndex); result = result.Substring(0, resultStartIndex) + contentID + result.Substring(resultEndIndex); } } else { if (c.IncomingRequest.ContentType != null) { c.OutgoingResponse.ContentType = c.IncomingRequest.ContentType; } else { // Took a breaking change, since the content type now must be correct. // In V1/V2, astoria client used to parse error payloads even when response content type value was application/atom+xml // After integration, it must be application/xml. c.OutgoingResponse.ContentType = AstoriaUnitTests.Data.SerializationFormatData.Atom.MimeTypes[2]; } if (c.IncomingRequest.Method == "POST") { c.OutgoingResponse.Location = "http://www.microsoft.com/"; } } return((result == null) ? null : new MemoryStream(Encoding.ASCII.GetBytes(result))); }