internal static ODataBatchOperationResponseMessage CreateReadMessage(ODataBatchReaderStream batchReaderStream, int statusCode, ODataBatchOperationHeaders headers, IODataBatchOperationListener operationListener, IODataUrlResolver urlResolver) { return(new ODataBatchOperationResponseMessage(() => ODataBatchUtils.CreateBatchOperationReadStream(batchReaderStream, headers, operationListener), headers, operationListener, urlResolver, false) { statusCode = statusCode }); }
/// <summary> /// Creates an operation response message that can be used to write the operation content to. /// </summary> /// <param name="outputStream">The output stream underlying the operation message.</param> /// <param name="operationListener">The operation listener.</param> /// <param name="urlResolver">The (optional) URL resolver for the message to create.</param> /// <returns>An <see cref="ODataBatchOperationResponseMessage"/> that can be used to write the operation content.</returns> internal static ODataBatchOperationResponseMessage CreateWriteMessage( Stream outputStream, IODataBatchOperationListener operationListener, IODataUrlResolver urlResolver) { DebugUtils.CheckNoExternalCallers(); Func <Stream> streamCreatorFunc = () => ODataBatchUtils.CreateBatchOperationWriteStream(outputStream, operationListener); return(new ODataBatchOperationResponseMessage(streamCreatorFunc, /*headers*/ null, operationListener, urlResolver, /*writing*/ true)); }
/// <summary> /// Creates an operation request message that can be used to write the operation content to. /// </summary> /// <param name="outputStream">The output stream underlying the operation message.</param> /// <param name="method">The HTTP method to use for the message to create.</param> /// <param name="requestUrl">The request URL for the message to create.</param> /// <param name="operationListener">The operation listener.</param> /// <param name="urlResolver">The (optional) URL resolver for the message to create.</param> /// <returns>An <see cref="ODataBatchOperationRequestMessage"/> to write the request content to.</returns> internal static ODataBatchOperationRequestMessage CreateWriteMessage( Stream outputStream, string method, Uri requestUrl, IODataBatchOperationListener operationListener, IODataUrlResolver urlResolver) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(outputStream != null, "outputStream != null"); Debug.Assert(operationListener != null, "operationListener != null"); Func <Stream> streamCreatorFunc = () => ODataBatchUtils.CreateBatchOperationWriteStream(outputStream, operationListener); return(new ODataBatchOperationRequestMessage(streamCreatorFunc, method, requestUrl, /*headers*/ null, operationListener, urlResolver, /*writing*/ true)); }
/// <summary> /// Creates an operation request message that can be used to read the operation content from. /// </summary> /// <param name="batchReaderStream">The batch stream underyling the operation response message.</param> /// <param name="method">The HTTP method to use for the message to create.</param> /// <param name="requestUrl">The request URL for the message to create.</param> /// <param name="headers">The headers to use for the operation request message.</param> /// <param name="operationListener">The operation listener.</param> /// <param name="urlResolver">The (optional) URL resolver for the message to create.</param> /// <returns>An <see cref="ODataBatchOperationRequestMessage"/> to read the request content from.</returns> internal static ODataBatchOperationRequestMessage CreateReadMessage( ODataBatchReaderStream batchReaderStream, string method, Uri requestUrl, ODataBatchOperationHeaders headers, IODataBatchOperationListener operationListener, IODataUrlResolver urlResolver) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(batchReaderStream != null, "batchReaderStream != null"); Debug.Assert(operationListener != null, "operationListener != null"); Func <Stream> streamCreatorFunc = () => ODataBatchUtils.CreateBatchOperationReadStream(batchReaderStream, headers, operationListener); return(new ODataBatchOperationRequestMessage(streamCreatorFunc, method, requestUrl, headers, operationListener, urlResolver, /*writing*/ false)); }
/// <summary> /// Creates an operation response message that can be used to read the operation content from. /// </summary> /// <param name="batchReaderStream">The batch stream underyling the operation response message.</param> /// <param name="statusCode">The status code to use for the operation response message.</param> /// <param name="headers">The headers to use for the operation response message.</param> /// <param name="operationListener">The operation listener.</param> /// <param name="urlResolver">The (optional) URL resolver for the message to create.</param> /// <returns>An <see cref="ODataBatchOperationResponseMessage"/> that can be used to read the operation content.</returns> internal static ODataBatchOperationResponseMessage CreateReadMessage( ODataBatchReaderStream batchReaderStream, int statusCode, ODataBatchOperationHeaders headers, IODataBatchOperationListener operationListener, IODataUrlResolver urlResolver) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(batchReaderStream != null, "batchReaderStream != null"); Debug.Assert(operationListener != null, "operationListener != null"); Func <Stream> streamCreatorFunc = () => ODataBatchUtils.CreateBatchOperationReadStream(batchReaderStream, headers, operationListener); ODataBatchOperationResponseMessage responseMessage = new ODataBatchOperationResponseMessage(streamCreatorFunc, headers, operationListener, urlResolver, /*writing*/ false); responseMessage.statusCode = statusCode; return(responseMessage); }
private void ParseRequestLine(string requestLine, out string httpMethod, out Uri requestUri) { int index = requestLine.IndexOf(' '); if ((index <= 0) || ((requestLine.Length - 3) <= index)) { throw new ODataException(Strings.ODataBatchReaderStream_InvalidRequestLine(requestLine)); } int num2 = requestLine.LastIndexOf(' '); if (((num2 < 0) || (((num2 - index) - 1) <= 0)) || ((requestLine.Length - 1) <= num2)) { throw new ODataException(Strings.ODataBatchReaderStream_InvalidRequestLine(requestLine)); } httpMethod = requestLine.Substring(0, index); string uriString = requestLine.Substring(index + 1, (num2 - index) - 1); string strB = requestLine.Substring(num2 + 1); if (string.CompareOrdinal("HTTP/1.1", strB) != 0) { throw new ODataException(Strings.ODataBatchReaderStream_InvalidHttpVersionSpecified(strB, "HTTP/1.1")); } HttpUtils.ValidateHttpMethod(httpMethod); if (this.batchStream.ChangeSetBoundary == null) { if (string.CompareOrdinal(httpMethod, "GET") != 0) { throw new ODataException(Strings.ODataBatch_InvalidHttpMethodForQueryOperation(httpMethod)); } } else if (string.CompareOrdinal(httpMethod, "GET") == 0) { throw new ODataException(Strings.ODataBatch_InvalidHttpMethodForChangeSetRequest(httpMethod)); } requestUri = new Uri(uriString, UriKind.RelativeOrAbsolute); requestUri = ODataBatchUtils.CreateOperationRequestUri(requestUri, this.inputContext.MessageReaderSettings.BaseUri, this.urlResolver); }
private ODataBatchOperationRequestMessage CreateOperationRequestMessageImplementation(string method, Uri uri) { if (this.changeSetBoundary == null) { this.InterceptException(new Action(this.IncreaseBatchSize)); } else { this.InterceptException(new Action(this.IncreaseChangeSetSize)); } this.WritePendingMessageData(true); if (this.currentOperationContentId != null) { this.urlResolver.AddContentId(this.currentOperationContentId); } this.InterceptException(delegate { uri = ODataBatchUtils.CreateOperationRequestUri(uri, this.rawOutputContext.MessageWriterSettings.BaseUri, this.urlResolver); }); this.CurrentOperationRequestMessage = ODataBatchOperationRequestMessage.CreateWriteMessage(this.rawOutputContext.OutputStream, method, uri, this, this.urlResolver); this.SetState(BatchWriterState.OperationCreated); this.WriteStartBoundaryForOperation(); ODataBatchWriterUtils.WriteRequestPreamble(this.rawOutputContext.TextWriter, method, uri); return(this.CurrentOperationRequestMessage); }
internal static ODataBatchOperationResponseMessage CreateWriteMessage(Stream outputStream, IODataBatchOperationListener operationListener, IODataUrlResolver urlResolver) { return(new ODataBatchOperationResponseMessage(() => ODataBatchUtils.CreateBatchOperationWriteStream(outputStream, operationListener), null, operationListener, urlResolver, true)); }
/// <summary> /// Parses the request line of a batch operation request. /// </summary> /// <param name="requestLine">The request line as a string.</param> /// <param name="httpMethod">The parsed HTTP method of the request.</param> /// <param name="requestUri">The parsed <see cref="Uri"/> of the request.</param> private void ParseRequestLine(string requestLine, out string httpMethod, out Uri requestUri) { Debug.Assert(!this.inputContext.ReadingResponse, "Must only be called for requests."); // Batch Request: POST /Customers HTTP/1.1 // Since the uri can contain spaces, the only way to read the request url, is to // check for first space character and last space character and anything between // them. int firstSpaceIndex = requestLine.IndexOf(' '); // Check whether there are enough characters after the first space for the 2nd and 3rd segments // (and a whitespace in between) if (firstSpaceIndex <= 0 || requestLine.Length - 3 <= firstSpaceIndex) { // only 1 segment or empty first segment or not enough left for 2nd and 3rd segments throw new ODataException(Strings.ODataBatchReaderStream_InvalidRequestLine(requestLine)); } int lastSpaceIndex = requestLine.LastIndexOf(' '); if (lastSpaceIndex < 0 || lastSpaceIndex - firstSpaceIndex - 1 <= 0 || requestLine.Length - 1 <= lastSpaceIndex) { // only 2 segments or empty 2nd or 3rd segments // only 1 segment or empty first segment or not enough left for 2nd and 3rd segments throw new ODataException(Strings.ODataBatchReaderStream_InvalidRequestLine(requestLine)); } httpMethod = requestLine.Substring(0, firstSpaceIndex); // Request - Http method string uriSegment = requestLine.Substring(firstSpaceIndex + 1, lastSpaceIndex - firstSpaceIndex - 1); // Request - Request uri string httpVersionSegment = requestLine.Substring(lastSpaceIndex + 1); // Request - Http version // Validate HttpVersion if (string.CompareOrdinal(ODataConstants.HttpVersionInBatching, httpVersionSegment) != 0) { throw new ODataException(Strings.ODataBatchReaderStream_InvalidHttpVersionSpecified(httpVersionSegment, ODataConstants.HttpVersionInBatching)); } // NOTE: this method will throw if the method is not recognized. HttpUtils.ValidateHttpMethod(httpMethod); // Validate the HTTP method when reading a request if (this.batchStream.ChangeSetBoundary == null) { // only allow GET requests for query operations if (!HttpUtils.IsQueryMethod(httpMethod)) { throw new ODataException(Strings.ODataBatch_InvalidHttpMethodForQueryOperation(httpMethod)); } } else { // allow all methods except for GET if (HttpUtils.IsQueryMethod(httpMethod)) { throw new ODataException(Strings.ODataBatch_InvalidHttpMethodForChangeSetRequest(httpMethod)); } } requestUri = new Uri(uriSegment, UriKind.RelativeOrAbsolute); requestUri = ODataBatchUtils.CreateOperationRequestUri(requestUri, this.inputContext.MessageReaderSettings.BaseUri, this.urlResolver); }
internal string ReadLine() { int numberOfBytesInBuffer = 0; byte[] lineBuffer = this.lineBuffer; ODataBatchReaderStreamScanResult noMatch = ODataBatchReaderStreamScanResult.NoMatch; while (noMatch != ODataBatchReaderStreamScanResult.Match) { int num2; int num3; int num4; noMatch = this.batchBuffer.ScanForLineEnd(out num3, out num4); switch (noMatch) { case ODataBatchReaderStreamScanResult.NoMatch: { num2 = this.batchBuffer.NumberOfBytesInBuffer; if (num2 > 0) { ODataBatchUtils.EnsureArraySize(ref lineBuffer, numberOfBytesInBuffer, num2); Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, lineBuffer, numberOfBytesInBuffer, num2); numberOfBytesInBuffer += num2; } if (this.underlyingStreamExhausted) { noMatch = ODataBatchReaderStreamScanResult.Match; this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + num2); } else { this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, 0x1f40); } continue; } case ODataBatchReaderStreamScanResult.PartialMatch: { num2 = num3 - this.batchBuffer.CurrentReadPosition; if (num2 > 0) { ODataBatchUtils.EnsureArraySize(ref lineBuffer, numberOfBytesInBuffer, num2); Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, lineBuffer, numberOfBytesInBuffer, num2); numberOfBytesInBuffer += num2; } if (this.underlyingStreamExhausted) { noMatch = ODataBatchReaderStreamScanResult.Match; this.batchBuffer.SkipTo(num3 + 1); } else { this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, num3); } continue; } case ODataBatchReaderStreamScanResult.Match: { num2 = num3 - this.batchBuffer.CurrentReadPosition; if (num2 > 0) { ODataBatchUtils.EnsureArraySize(ref lineBuffer, numberOfBytesInBuffer, num2); Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, lineBuffer, numberOfBytesInBuffer, num2); numberOfBytesInBuffer += num2; } this.batchBuffer.SkipTo(num4 + 1); continue; } } throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStream_ReadLine)); } if (lineBuffer == null) { return(string.Empty); } return(this.CurrentEncoding.GetString(lineBuffer, 0, numberOfBytesInBuffer)); }
/// <summary> /// Reads a line (all bytes until a line feed) from the underlying stream. /// </summary> /// <returns>Returns the string that was read from the underyling stream (not including a terminating line feed).</returns> internal string ReadLine() { DebugUtils.CheckNoExternalCallers(); Debug.Assert(this.batchEncoding != null, "Batch encoding should have been established on first call to SkipToBoundary."); Debug.Assert(this.lineBuffer != null && this.lineBuffer.Length == LineBufferLength, "Line buffer should have been created."); // The number of bytes in the line buffer that make up the line. int lineBufferSize = 0; // Start with the pre-allocated line buffer array. byte[] bytesForString = this.lineBuffer; ODataBatchReaderStreamScanResult scanResult = ODataBatchReaderStreamScanResult.NoMatch; while (scanResult != ODataBatchReaderStreamScanResult.Match) { int byteCount, lineEndStartPosition, lineEndEndPosition; scanResult = this.batchBuffer.ScanForLineEnd(out lineEndStartPosition, out lineEndEndPosition); switch (scanResult) { case ODataBatchReaderStreamScanResult.NoMatch: // Copy all the bytes in the batchBuffer into the result byte[] and then continue byteCount = this.batchBuffer.NumberOfBytesInBuffer; if (byteCount > 0) { ODataBatchUtils.EnsureArraySize(ref bytesForString, lineBufferSize, byteCount); Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, bytesForString, lineBufferSize, byteCount); lineBufferSize += byteCount; } if (this.underlyingStreamExhausted) { // Nothing more to read; stop looping scanResult = ODataBatchReaderStreamScanResult.Match; this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + byteCount); } else { this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, /*preserveFrom*/ ODataBatchReaderStreamBuffer.BufferLength); } break; case ODataBatchReaderStreamScanResult.PartialMatch: // We found the start of a line end in the buffer but could not verify whether we saw all of it. // This can happen if a line end is represented as \r\n and we found \r at the very last position in the buffer. // In this case we copy the bytes into the result byte[] and continue at the start of the line end; this will guarantee // that the next scan will find the full line end, not find any additional bytes and then skip the full line end. // It is safe to copy the string right here because we will also accept \r as a line end; we are just not sure whether there // will be a subsequent \n. // This can also happen if the last byte in the stream is \r. byteCount = lineEndStartPosition - this.batchBuffer.CurrentReadPosition; if (byteCount > 0) { ODataBatchUtils.EnsureArraySize(ref bytesForString, lineBufferSize, byteCount); Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, bytesForString, lineBufferSize, byteCount); lineBufferSize += byteCount; } if (this.underlyingStreamExhausted) { // Nothing more to read; stop looping scanResult = ODataBatchReaderStreamScanResult.Match; this.batchBuffer.SkipTo(lineEndStartPosition + 1); } else { this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, /*preserveFrom*/ lineEndStartPosition); } break; case ODataBatchReaderStreamScanResult.Match: // We found a line end in the buffer Debug.Assert(lineEndStartPosition >= this.batchBuffer.CurrentReadPosition, "Line end must be at or after current position."); Debug.Assert(lineEndEndPosition < this.batchBuffer.CurrentReadPosition + this.batchBuffer.NumberOfBytesInBuffer, "Line end must finish withing buffer range."); byteCount = lineEndStartPosition - this.batchBuffer.CurrentReadPosition; if (byteCount > 0) { ODataBatchUtils.EnsureArraySize(ref bytesForString, lineBufferSize, byteCount); Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, bytesForString, lineBufferSize, byteCount); lineBufferSize += byteCount; } this.batchBuffer.SkipTo(lineEndEndPosition + 1); break; default: throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStream_ReadLine)); } } if (bytesForString == null) { return(string.Empty); } return(this.CurrentEncoding.GetString(bytesForString, 0, lineBufferSize)); }
internal static ODataBatchOperationRequestMessage CreateWriteMessage(Stream outputStream, string method, Uri requestUrl, IODataBatchOperationListener operationListener, IODataUrlResolver urlResolver) { return(new ODataBatchOperationRequestMessage(() => ODataBatchUtils.CreateBatchOperationWriteStream(outputStream, operationListener), method, requestUrl, null, operationListener, urlResolver, true)); }
internal static ODataBatchOperationRequestMessage CreateReadMessage(ODataBatchReaderStream batchReaderStream, string method, Uri requestUrl, ODataBatchOperationHeaders headers, IODataBatchOperationListener operationListener, IODataUrlResolver urlResolver) { return(new ODataBatchOperationRequestMessage(() => ODataBatchUtils.CreateBatchOperationReadStream(batchReaderStream, headers, operationListener), method, requestUrl, headers, operationListener, urlResolver, false)); }