private ODataBatchOperationHeaders ValidatePartHeaders(ODataBatchOperationHeaders headers, out bool isChangeSetPart) { string str; if (!headers.TryGetValue("Content-Type", out str)) { throw new ODataException(Strings.ODataBatchReaderStream_MissingContentTypeHeader); } if (MediaTypeUtils.MediaTypeAndSubtypeAreEqual(str, "application/http")) { string str2; isChangeSetPart = false; if (!headers.TryGetValue("Content-Transfer-Encoding", out str2) || (string.Compare(str2, "binary", StringComparison.OrdinalIgnoreCase) != 0)) { throw new ODataException(Strings.ODataBatchReaderStream_MissingOrInvalidContentEncodingHeader("Content-Transfer-Encoding", "binary")); } return(headers); } if (!MediaTypeUtils.MediaTypeStartsWithTypeAndSubtype(str, "multipart/mixed")) { throw new ODataException(Strings.ODataBatchReaderStream_InvalidContentTypeSpecified("Content-Type", str, "multipart/mixed", "application/http")); } isChangeSetPart = true; if (this.changesetBoundary != null) { throw new ODataException(Strings.ODataBatchReaderStream_NestedChangesetsAreNotSupported); } return(headers); }
/// <summary> /// Creates a batch operation stream from the specified batch stream. /// </summary> /// <param name="batchReaderStream">The batch stream to create the operation read stream for.</param> /// <param name="headers">The headers of the current part; based on the header we create different, optimized stream implementations.</param> /// <param name="operationListener">The operation listener to be passed to the newly created read stream.</param> /// <returns>A new <see cref="ODataBatchOperationReadStream"/> instance.</returns> internal static ODataBatchOperationReadStream CreateBatchOperationReadStream( ODataBatchReaderStream batchReaderStream, ODataBatchOperationHeaders headers, IODataBatchOperationListener operationListener) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(batchReaderStream != null, "batchReaderStream != null"); Debug.Assert(operationListener != null, "operationListener != null"); // See whether we have a Content-Length header string contentLengthValue; if (headers.TryGetValue(ODataConstants.ContentLengthHeader, out contentLengthValue)) { int length = Int32.Parse(contentLengthValue, CultureInfo.InvariantCulture); if (length < 0) { throw new ODataException(Strings.ODataBatchReaderStream_InvalidContentLengthSpecified(contentLengthValue)); } return(ODataBatchOperationReadStream.Create(batchReaderStream, operationListener, length)); } return(ODataBatchOperationReadStream.Create(batchReaderStream, operationListener)); }
private ODataBatchOperationRequestMessage CreateOperationRequestMessageImplementation() { string str2; Uri uri; string str3; this.operationState = OperationState.MessageCreated; string requestLine = this.batchStream.ReadLine(); while (requestLine.Length == 0) { requestLine = this.batchStream.ReadLine(); } this.ParseRequestLine(requestLine, out str2, out uri); ODataBatchOperationHeaders headers = this.batchStream.ReadHeaders(); ODataBatchOperationRequestMessage message = ODataBatchOperationRequestMessage.CreateReadMessage(this.batchStream, str2, uri, headers, this, this.urlResolver); if (headers.TryGetValue("Content-ID", out str3)) { if ((str3 != null) && this.urlResolver.ContainsContentId(str3)) { throw new ODataException(Strings.ODataBatchReader_DuplicateContentIDsNotAllowed(str3)); } this.contentIdToAddOnNextRead = str3; } return(message); }
/// <summary> /// Validates the headers that have been read for a part. /// </summary> /// <param name="headers">The set of headers to validate.</param> /// <param name="isChangeSetPart">true if the headers indicate a changset part; otherwise false.</param> /// <returns>The set of validated headers.</returns> /// <remarks> /// An operation part is required to have content type 'application/http' and content transfer /// encoding 'binary'. A changeset is required to have content type 'multipart/mixed'. /// Note that we allow additional headers for batch parts; clients of the library can choose /// to be more strict. /// </remarks> private ODataBatchOperationHeaders ValidatePartHeaders(ODataBatchOperationHeaders headers, out bool isChangeSetPart) { string contentType; if (!headers.TryGetValue(ODataConstants.ContentTypeHeader, out contentType)) { throw new ODataException(Strings.ODataBatchReaderStream_MissingContentTypeHeader); } if (MediaTypeUtils.MediaTypeAndSubtypeAreEqual(contentType, MimeConstants.MimeApplicationHttp)) { isChangeSetPart = false; // An operation part is required to have application/http content type and // binary content transfer encoding. string transferEncoding; if (!headers.TryGetValue(ODataConstants.ContentTransferEncoding, out transferEncoding) || string.Compare(transferEncoding, ODataConstants.BatchContentTransferEncoding, StringComparison.OrdinalIgnoreCase) != 0) { throw new ODataException(Strings.ODataBatchReaderStream_MissingOrInvalidContentEncodingHeader( ODataConstants.ContentTransferEncoding, ODataConstants.BatchContentTransferEncoding)); } } else if (MediaTypeUtils.MediaTypeStartsWithTypeAndSubtype(contentType, MimeConstants.MimeMultipartMixed)) { isChangeSetPart = true; if (this.changesetBoundary != null) { // Nested changesets are not supported throw new ODataException(Strings.ODataBatchReaderStream_NestedChangesetsAreNotSupported); } } else { throw new ODataException(Strings.ODataBatchReaderStream_InvalidContentTypeSpecified( ODataConstants.ContentTypeHeader, contentType, MimeConstants.MimeMultipartMixed, MimeConstants.MimeApplicationHttp)); } return(headers); }
internal static ODataBatchOperationReadStream CreateBatchOperationReadStream(ODataBatchReaderStream batchReaderStream, ODataBatchOperationHeaders headers, IODataBatchOperationListener operationListener) { string str; if (!headers.TryGetValue("Content-Length", out str)) { return(ODataBatchOperationReadStream.Create(batchReaderStream, operationListener)); } int length = int.Parse(str, CultureInfo.InvariantCulture); if (length < 0) { throw new ODataException(Strings.ODataBatchReaderStream_InvalidContentLengthSpecified(str)); } return(ODataBatchOperationReadStream.Create(batchReaderStream, operationListener, length)); }
/// <summary> /// Returns the cached <see cref="ODataBatchOperationRequestMessage"/> for reading the content of an operation /// in a batch request. /// </summary> /// <returns>The message that can be used to read the content of the batch request operation from.</returns> private ODataBatchOperationRequestMessage CreateOperationRequestMessageImplementation() { this.operationState = OperationState.MessageCreated; // Read and parse the request line (skip all empty lines) string requestLine = this.batchStream.ReadLine(); while (requestLine.Length == 0) { requestLine = this.batchStream.ReadLine(); } string httpMethod; Uri requestUri; this.ParseRequestLine(requestLine, out httpMethod, out requestUri); // Read all headers and create the request message ODataBatchOperationHeaders headers = this.batchStream.ReadHeaders(); ODataBatchOperationRequestMessage requestMessage = ODataBatchOperationRequestMessage.CreateReadMessage( this.batchStream, httpMethod, requestUri, headers, /*operationListener*/ this, this.urlResolver); // Add a potential Content-ID header to the URL resolver so that it will be available // to subsequent operations. string contentId; if (headers.TryGetValue(ODataConstants.ContentIdHeader, out contentId)) { Debug.Assert(this.contentIdToAddOnNextRead == null, "Must not have a content ID to be added to a part."); if (contentId != null && this.urlResolver.ContainsContentId(contentId)) { throw new ODataException(Strings.ODataBatchReader_DuplicateContentIDsNotAllowed(contentId)); } this.contentIdToAddOnNextRead = contentId; } return(requestMessage); }