public async Task StreamWriteAsyncTest() { byte[] buffer = GetRandomBuffer(1 * 1024 * 1024); MemoryStream stream1 = new MemoryStream(buffer); MemoryStream stream2 = new MemoryStream(); OperationContext tempOperationContext = new OperationContext(); RESTCommand<NullType> cmd = new RESTCommand<NullType>(TestBase.StorageCredentials, null); ExecutionState<NullType> tempExecutionState = new ExecutionState<NullType>(cmd, null, tempOperationContext); // Test basic write await stream1.WriteToAsync(stream2, null, null, false, tempExecutionState, null, CancellationToken.None); stream1.Position = 0; TestHelper.AssertStreamsAreEqual(stream1, stream2); stream2.Dispose(); stream2 = new MemoryStream(); await TestHelper.ExpectedExceptionAsync<ArgumentException>( async () => await stream1.WriteToAsync(stream2, 1024, 1024, false, tempExecutionState, null, CancellationToken.None), "Parameters copyLength and maxLength cannot be passed simultaneously."); stream1.Dispose(); stream2.Dispose(); }
private static RESTCommand<TableQuerySegment> QueryImpl(TableQuery query, TableContinuationToken token, CloudTableClient client, string tableName, TableRequestOptions requestOptions) { UriQueryBuilder builder = query.GenerateQueryBuilder(); if (token != null) { token.ApplyToUriQueryBuilder(builder); } StorageUri tempUriList = NavigationHelper.AppendPathToUri(client.StorageUri, tableName); RESTCommand<TableQuerySegment> queryCmd = new RESTCommand<TableQuerySegment>(client.Credentials, tempUriList); requestOptions.ApplyToStorageCommand(queryCmd); queryCmd.CommandLocationMode = CommonUtility.GetListingLocationMode(token); queryCmd.RetrieveResponseStream = true; queryCmd.Handler = client.AuthenticationHandler; queryCmd.BuildClient = HttpClientFactory.BuildHttpClient; queryCmd.Builder = builder; queryCmd.BuildRequest = (cmd, uri, queryBuilder, cnt, serverTimeout, ctx) => TableOperationHttpRequestMessageFactory.BuildRequestForTableQuery(uri, builder, serverTimeout, cnt, ctx); queryCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp.StatusCode, null /* retVal */, cmd, ex); queryCmd.PostProcessResponse = async (cmd, resp, ctx) => { TableQuerySegment resSeg = await TableOperationHttpResponseParsers.TableQueryPostProcess(cmd.ResponseStream, resp, ctx); if (resSeg.ContinuationToken != null) { resSeg.ContinuationToken.TargetLocation = cmd.CurrentResult.TargetLocation; } return resSeg; }; return queryCmd; }
public void StreamWriteSyncTestCopyLengthBoundary() { byte[] buffer = GetRandomBuffer(1 * 1024 * 1024); MemoryStream stream1 = new MemoryStream(buffer); MemoryStream stream2 = new MemoryStream(); MemoryStream stream3 = new MemoryStream(); OperationContext tempOperationContext = new OperationContext(); RESTCommand<NullType> cmd = new RESTCommand<NullType>(TestBase.StorageCredentials, null); ExecutionState<NullType> tempExecutionState = new ExecutionState<NullType>(cmd, null, tempOperationContext); // Test write with exact number of bytes stream1.WriteToSync(stream2, stream1.Length, null, true, false, tempExecutionState, null); stream1.Position = 0; stream1.WriteToSync(stream3, stream1.Length, null, true, true, tempExecutionState, null); stream1.Position = 0; TestHelper.AssertStreamsAreEqual(stream1, stream2); TestHelper.AssertStreamsAreEqual(stream1, stream3); stream2.Dispose(); stream2 = new MemoryStream(); stream3.Dispose(); stream3 = new MemoryStream(); // Test write with one less byte stream1.WriteToSync(stream2, stream1.Length - 1, null, true, false, tempExecutionState, null); stream1.Position = 0; stream1.WriteToSync(stream3, stream1.Length - 1, null, true, true, tempExecutionState, null); stream1.Position = 0; Assert.AreEqual(stream1.Length - 1, stream2.Length); Assert.AreEqual(stream1.Length - 1, stream3.Length); TestHelper.AssertStreamsAreEqualAtIndex(stream1, stream2, 0, 0, (int)stream1.Length - 1); TestHelper.AssertStreamsAreEqualAtIndex(stream1, stream3, 0, 0, (int)stream1.Length - 1); stream2.Dispose(); stream2 = new MemoryStream(); stream3.Dispose(); stream3 = new MemoryStream(); // Test with copyLength greater than length TestHelper.ExpectedException<ArgumentOutOfRangeException>( () => stream1.WriteToSync(stream2, stream1.Length + 1, null, true, false, tempExecutionState, null), "The given stream does not contain the requested number of bytes from its given position."); stream1.Position = 0; TestHelper.ExpectedException<ArgumentOutOfRangeException>( () => stream1.WriteToSync(stream3, stream1.Length + 1, null, true, true, tempExecutionState, null), "The given stream does not contain the requested number of bytes from its given position."); stream1.Position = 0; stream1.Dispose(); stream2.Dispose(); stream3.Dispose(); }
/// <summary> /// Implements the FetchAttributes method. The attributes are updated immediately. /// </summary> /// <param name="blob">The blob.</param> /// <param name="attributes">The attributes.</param> /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the condition that must be met in order for the request to proceed. If <c>null</c>, no condition is used.</param> /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies additional options for the request.</param> /// <returns> /// A <see cref="RESTCommand{T}"/> that fetches the attributes. /// </returns> internal static RESTCommand <NullType> FetchAttributesImpl(ICloudBlob blob, BlobAttributes attributes, AccessCondition accessCondition, BlobRequestOptions options) { RESTCommand <NullType> getCmd = new RESTCommand <NullType>(blob.ServiceClient.Credentials, attributes.StorageUri); options.ApplyToStorageCommand(getCmd); getCmd.CommandLocationMode = CommandLocationMode.PrimaryOrSecondary; getCmd.BuildRequestDelegate = (uri, builder, serverTimeout, useVersionHeader, ctx) => BlobHttpWebRequestFactory.GetProperties(uri, serverTimeout, attributes.SnapshotTime, accessCondition, useVersionHeader, ctx); getCmd.SignRequest = blob.ServiceClient.AuthenticationHandler.SignRequest; getCmd.PreProcessResponse = (cmd, resp, ex, ctx) => { HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, NullType.Value, cmd, ex); CloudBlobSharedImpl.UpdateAfterFetchAttributes(attributes, resp, false); return(NullType.Value); }; return(getCmd); }
/// <summary> /// Generates a <see cref="RESTCommand{T}"/> for releasing a lease. /// </summary> /// <param name="accessCondition">An object that represents the access conditions for the blob. If null, no condition is used.</param> /// <param name="options">An object that specifies any additional options for the request.</param> /// <returns>A <see cref="RESTCommand{T}"/> implementing the release lease operation.</returns> internal static RESTCommand <NullType> ReleaseLeaseImpl(ICloudBlob blob, BlobAttributes attributes, AccessCondition accessCondition, BlobRequestOptions options) { CommonUtils.AssertNotNull("accessCondition", accessCondition); if (accessCondition.LeaseId == null) { throw new ArgumentException(SR.MissingLeaseIDReleasing, "accessCondition"); } RESTCommand <NullType> putCmd = new RESTCommand <NullType>(blob.ServiceClient.Credentials, attributes.Uri); putCmd.ApplyRequestOptions(options); putCmd.BuildRequestDelegate = (uri, builder, serverTimeout, ctx) => BlobHttpWebRequestFactory.Lease(uri, serverTimeout, LeaseAction.Release, null /* proposedLeaseId */, null /* leaseDuration */, null /* leaseBreakPeriod */, accessCondition, ctx); putCmd.SignRequest = blob.ServiceClient.AuthenticationHandler.SignRequest; putCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, NullType.Value, cmd, ex, ctx); return(putCmd); }
internal Task <TableQuerySegment <TResult> > ExecuteQuerySegmentedAsync <TResult>(TableContinuationToken token, CloudTableClient client, string tableName, EntityResolver <TResult> resolver, TableRequestOptions requestOptions, OperationContext operationContext, CancellationToken cancellationToken) { CommonUtility.AssertNotNullOrEmpty("tableName", tableName); CommonUtility.AssertNotNull("resolver", resolver); TableRequestOptions modifiedOptions = TableRequestOptions.ApplyDefaults(requestOptions, client); operationContext = operationContext ?? new OperationContext(); RESTCommand <TableQuerySegment <TResult> > cmdToExecute = QueryImpl(this, token, client, tableName, resolver, modifiedOptions); return(Executor.ExecuteAsync( cmdToExecute, modifiedOptions.RetryPolicy, operationContext, cancellationToken)); }
private static RESTCommand <IList <TableResult> > BatchImpl(TableBatchOperation batch, CloudTableClient client, string tableName, TableRequestOptions requestOptions) { RESTCommand <IList <TableResult> > batchCmd = new RESTCommand <IList <TableResult> >(client.Credentials, client.BaseUri); requestOptions.ApplyToStorageCommand(batchCmd); List <TableResult> results = new List <TableResult>(); batchCmd.RetrieveResponseStream = true; batchCmd.Handler = client.AuthenticationHandler; batchCmd.BuildClient = HttpClientFactory.BuildHttpClient; batchCmd.BuildRequest = (cmd, cnt, ctx) => TableOperationHttpRequestMessageFactory.BuildRequestForTableBatchOperation(cmd.Uri, cmd.ServerTimeoutInSeconds, client.BaseUri, tableName, batch, ctx); batchCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.Accepted, resp.StatusCode, results, cmd, ex, ctx); batchCmd.PostProcessResponse = (cmd, resp, ex, ctx) => TableOperationHttpResponseParsers.TableBatchOperationPostProcess(results, batch, cmd, resp, ctx); return(batchCmd); }
/// <summary> /// Implementation for the SetProperties method. /// </summary> /// <param name="accessCondition">An object that represents the access conditions for the blob. If null, no condition is used.</param> /// <param name="options">An object that specifies any additional options for the request.</param> /// <returns>A <see cref="RESTCommand{T}"/> that sets the metadata.</returns> internal static RESTCommand <NullType> SetPropertiesImpl(ICloudBlob blob, BlobAttributes attributes, AccessCondition accessCondition, BlobRequestOptions options) { RESTCommand <NullType> putCmd = new RESTCommand <NullType>(blob.ServiceClient.Credentials, attributes.Uri); putCmd.ApplyRequestOptions(options); putCmd.BuildRequestDelegate = (uri, builder, serverTimeout, ctx) => BlobHttpWebRequestFactory.SetProperties(uri, serverTimeout, attributes.Properties, accessCondition, ctx); putCmd.SetHeaders = (r, ctx) => BlobHttpWebRequestFactory.AddMetadata(r, attributes.Metadata); putCmd.SignRequest = blob.ServiceClient.AuthenticationHandler.SignRequest; putCmd.PreProcessResponse = (cmd, resp, ex, ctx) => { HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, NullType.Value, cmd, ex, ctx); CloudBlobSharedImpl.ParseSizeAndLastModified(attributes, resp); return(NullType.Value); }; return(putCmd); }
private RESTCommand <ServiceStats> GetServiceStatsImpl(QueueRequestOptions requestOptions) { if (RetryPolicies.LocationMode.PrimaryOnly == requestOptions.LocationMode) { throw new InvalidOperationException(SR.GetServiceStatsInvalidOperation); } RESTCommand <ServiceStats> retCmd = new RESTCommand <ServiceStats>(this.Credentials, this.StorageUri); requestOptions.ApplyToStorageCommand(retCmd); retCmd.CommandLocationMode = CommandLocationMode.PrimaryOrSecondary; retCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => QueueHttpRequestMessageFactory.GetServiceStats(uri, serverTimeout, ctx, this.GetCanonicalizer(), this.Credentials); retCmd.RetrieveResponseStream = true; retCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex); retCmd.PostProcessResponseAsync = (cmd, resp, ctx, ct) => QueueHttpResponseParsers.ReadServiceStatsAsync(cmd.ResponseStream, ct); return(retCmd); }
/// <summary> /// Implements the FetchAttributes method. The attributes are updated immediately. /// </summary> /// <param name="accessCondition">An object that represents the access conditions for the blob. If null, no condition is used.</param> /// <param name="options">An object that specifies any additional options for the request.</param> /// <returns>A <see cref="RESTCommand"/> that fetches the attributes.</returns> internal static RESTCommand <NullType> FetchAttributesImpl(ICloudBlob blob, BlobAttributes attributes, AccessCondition accessCondition, BlobRequestOptions options) { RESTCommand <NullType> getCmd = new RESTCommand <NullType>(blob.ServiceClient.Credentials, attributes.Uri); getCmd.ApplyRequestOptions(options); getCmd.Handler = blob.ServiceClient.AuthenticationHandler; getCmd.BuildClient = HttpClientFactory.BuildHttpClient; getCmd.BuildRequest = (cmd, cnt, ctx) => BlobHttpRequestMessageFactory.GetProperties(cmd.Uri, cmd.ServerTimeoutInSeconds, attributes.SnapshotTime, accessCondition, cnt, ctx); getCmd.PreProcessResponse = (cmd, resp, ex, ctx) => { HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, NullType.Value, cmd, ex, ctx); CloudBlobSharedImpl.UpdateAfterFetchAttributes(attributes, resp, false); return(NullType.Value); }; return(getCmd); }
/// <summary> /// Implementation for the FetchAttributes method. /// </summary> /// <param name="accessCondition">An object that represents the access conditions for the share. If null, no condition is used.</param> /// <param name="options">An object that specifies additional options for the request.</param> /// <returns>A <see cref="RESTCommand"/> that fetches the attributes.</returns> private RESTCommand <NullType> FetchAttributesImpl(AccessCondition accessCondition, FileRequestOptions options) { RESTCommand <NullType> getCmd = new RESTCommand <NullType>(this.ServiceClient.Credentials, this.StorageUri); options.ApplyToStorageCommand(getCmd); getCmd.CommandLocationMode = CommandLocationMode.PrimaryOrSecondary; getCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => ShareHttpRequestMessageFactory.GetProperties(uri, serverTimeout, accessCondition, cnt, ctx, this.ServiceClient.GetCanonicalizer(), this.ServiceClient.Credentials); getCmd.PreProcessResponse = (cmd, resp, ex, ctx) => { HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, NullType.Value, cmd, ex); this.Properties = ShareHttpResponseParsers.GetProperties(resp); this.Metadata = ShareHttpResponseParsers.GetMetadata(resp); return(NullType.Value); }; return(getCmd); }
/// <summary> /// Implementation for the SetProperties method. /// </summary> /// <param name="blob">The blob.</param> /// <param name="attributes">The attributes.</param> /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the condition that must be met in order for the request to proceed. If <c>null</c>, no condition is used.</param> /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies additional options for the request.</param> /// <returns> /// A <see cref="RESTCommand{T}"/> that sets the properties. /// </returns> internal static RESTCommand <NullType> SetPropertiesImpl(ICloudBlob blob, BlobAttributes attributes, AccessCondition accessCondition, BlobRequestOptions options) { RESTCommand <NullType> putCmd = new RESTCommand <NullType>(blob.ServiceClient.Credentials, attributes.StorageUri); options.ApplyToStorageCommand(putCmd); putCmd.BuildRequestDelegate = (uri, builder, serverTimeout, useVersionHeader, ctx) => BlobHttpWebRequestFactory.SetProperties(uri, serverTimeout, attributes.Properties, accessCondition, useVersionHeader, ctx); putCmd.SetHeaders = (r, ctx) => BlobHttpWebRequestFactory.AddMetadata(r, attributes.Metadata); putCmd.SignRequest = blob.ServiceClient.AuthenticationHandler.SignRequest; putCmd.PreProcessResponse = (cmd, resp, ex, ctx) => { HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, NullType.Value, cmd, ex); CloudBlobSharedImpl.UpdateETagLMTLengthAndSequenceNumber(attributes, resp, false); return(NullType.Value); }; return(putCmd); }
/// <summary> /// Implements the FetchAttributes method. The attributes are updated immediately. /// </summary> /// <param name="blobUri">The URI of the blob.</param> /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the access conditions for the blob. If <c>null</c>, no condition is used.</param> /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies additional options for the request.</param> /// <returns>A <see cref="RESTCommand"/> that fetches the attributes.</returns> private RESTCommand <ICloudBlob> GetBlobReferenceImpl(StorageUri blobUri, AccessCondition accessCondition, BlobRequestOptions options) { // If the blob Uri contains SAS credentials, we need to use those // credentials instead of this service client's stored credentials. StorageCredentials parsedCredentials; DateTimeOffset? parsedSnapshot; blobUri = NavigationHelper.ParseBlobQueryAndVerify(blobUri, out parsedCredentials, out parsedSnapshot); CloudBlobClient client = parsedCredentials != null ? new CloudBlobClient(this.StorageUri, parsedCredentials) : this; RESTCommand <ICloudBlob> getCmd = new RESTCommand <ICloudBlob>(client.Credentials, blobUri); options.ApplyToStorageCommand(getCmd); getCmd.CommandLocationMode = CommandLocationMode.PrimaryOrSecondary; getCmd.Handler = client.AuthenticationHandler; getCmd.BuildClient = HttpClientFactory.BuildHttpClient; getCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => BlobHttpRequestMessageFactory.GetProperties(uri, serverTimeout, parsedSnapshot, accessCondition, cnt, ctx); getCmd.PreProcessResponse = (cmd, resp, ex, ctx) => { HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex); BlobAttributes attributes = new BlobAttributes() { StorageUri = blobUri, SnapshotTime = parsedSnapshot, }; CloudBlob.UpdateAfterFetchAttributes(attributes, resp, false); switch (attributes.Properties.BlobType) { case BlobType.BlockBlob: return(new CloudBlockBlob(attributes, client)); case BlobType.PageBlob: return(new CloudPageBlob(attributes, client)); case BlobType.AppendBlob: return(new CloudAppendBlob(attributes, client)); default: throw new InvalidOperationException(); } }; return(getCmd); }
private static RESTCommand <TableQuerySegment <RESULT_TYPE> > QueryImpl <RESULT_TYPE>(TableQuery query, TableContinuationToken token, CloudTableClient client, CloudTable table, EntityResolver <RESULT_TYPE> resolver, TableRequestOptions requestOptions) { UriQueryBuilder builder = query.GenerateQueryBuilder(requestOptions.ProjectSystemProperties); if (token != null) { token.ApplyToUriQueryBuilder(builder); } StorageUri tempUri = NavigationHelper.AppendPathToUri(client.StorageUri, table.Name); RESTCommand <TableQuerySegment <RESULT_TYPE> > queryCmd = new RESTCommand <TableQuerySegment <RESULT_TYPE> >(client.Credentials, tempUri); requestOptions.ApplyToStorageCommand(queryCmd); queryCmd.CommandLocationMode = CommonUtility.GetListingLocationMode(token); queryCmd.RetrieveResponseStream = true; queryCmd.SignRequest = client.AuthenticationHandler.SignRequest; queryCmd.Builder = builder; queryCmd.ParseError = ODataErrorHelper.ReadFromStreamUsingODataLib; queryCmd.BuildRequestDelegate = (uri, queryBuilder, timeout, useVersionHeader, ctx) => TableOperationHttpWebRequestFactory.BuildRequestForTableQuery(uri, queryBuilder, timeout, useVersionHeader, ctx, requestOptions.PayloadFormat.Value); queryCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp != null ? resp.StatusCode : HttpStatusCode.Unused, null /* retVal */, cmd, ex); queryCmd.PostProcessResponse = (cmd, resp, ctx) => { ResultSegment <RESULT_TYPE> resSeg = TableOperationHttpResponseParsers.TableQueryPostProcessGeneric <RESULT_TYPE, DynamicTableEntity>(cmd.ResponseStream, resolver.Invoke, resp, requestOptions, ctx); if (resSeg.ContinuationToken != null) { resSeg.ContinuationToken.TargetLocation = cmd.CurrentResult.TargetLocation; } return(new TableQuerySegment <RESULT_TYPE>(resSeg)); }; queryCmd.PostProcessResponseAsync = async(cmd, resp, ctx) => { ResultSegment <RESULT_TYPE> resSeg = await TableOperationHttpResponseParsers.TableQueryPostProcessGenericAsync <RESULT_TYPE, DynamicTableEntity>(cmd.ResponseStream, resolver.Invoke, resp, requestOptions, ctx); if (resSeg.ContinuationToken != null) { resSeg.ContinuationToken.TargetLocation = cmd.CurrentResult.TargetLocation; } return(new TableQuerySegment <RESULT_TYPE>(resSeg)); }; return(queryCmd); }
public async Task WriteToMultiBufferMemoryStreamTestAsync() { OperationContext tempOperationContext = new OperationContext(); RESTCommand <NullType> cmd = new RESTCommand <NullType>(TestBase.StorageCredentials, null); ExecutionState <NullType> tempExecutionState = new ExecutionState <NullType>(cmd, null, tempOperationContext); byte[] buffer = GetRandomBuffer(1 * 1024 * 1024); MemoryStream stream1 = new MemoryStream(buffer); MultiBufferMemoryStream stream2 = new MultiBufferMemoryStream(null /* bufferManager */); await stream1.WriteToAsync(stream2, null, null, false, tempExecutionState, null, CancellationToken.None); stream1.Seek(0, SeekOrigin.Begin); stream2.Seek(0, SeekOrigin.Begin); TestHelper.AssertStreamsAreEqual(stream1, stream2); MultiBufferMemoryStream stream3 = new MultiBufferMemoryStream(null /* bufferManager */); await TestHelper.ExpectedExceptionAsync <TimeoutException>( () => stream2.FastCopyToAsync(stream3, DateTime.Now.AddMinutes(-1)), "Past expiration time should immediately fail"); stream2.Seek(0, SeekOrigin.Begin); stream3.Seek(0, SeekOrigin.Begin); await stream2.FastCopyToAsync(stream3, DateTime.Now.AddHours(1)); stream2.Seek(0, SeekOrigin.Begin); stream3.Seek(0, SeekOrigin.Begin); TestHelper.AssertStreamsAreEqual(stream2, stream3); MultiBufferMemoryStream stream4 = new MultiBufferMemoryStream(null /* bufferManager */, 12345); await stream3.FastCopyToAsync(stream4, null); stream3.Seek(0, SeekOrigin.Begin); stream4.Seek(0, SeekOrigin.Begin); TestHelper.AssertStreamsAreEqual(stream3, stream4); MemoryStream stream5 = new MemoryStream(); await stream4.WriteToAsync(stream5, null, null, false, tempExecutionState, null, CancellationToken.None); stream4.Seek(0, SeekOrigin.Begin); stream5.Seek(0, SeekOrigin.Begin); TestHelper.AssertStreamsAreEqual(stream4, stream5); TestHelper.AssertStreamsAreEqual(stream1, stream5); }
private static RESTCommand <TableResult> DeleteImpl(TableOperation operation, CloudTableClient client, string tableName, TableRequestOptions requestOptions) { RESTCommand <TableResult> deleteCmd = new RESTCommand <TableResult>(client.Credentials, operation.GenerateRequestURI(client.BaseUri, tableName)); deleteCmd.ApplyRequestOptions(requestOptions); TableResult result = new TableResult() { Result = operation.Entity }; deleteCmd.RetrieveResponseStream = false; deleteCmd.SignRequest = client.AuthenticationHandler.SignRequest; deleteCmd.BuildRequestDelegate = (uri, builder, timeout, ctx) => TableOperationHttpWebRequestFactory.BuildRequestForTableOperation(uri, builder, client.BufferManager, timeout, operation, ctx).Item1; deleteCmd.PreProcessResponse = (cmd, resp, ex, ctx) => TableOperationHttpResponseParsers.TableOperationPreProcess(result, operation, resp, ex, cmd); return(deleteCmd); }
private RESTCommand <ServiceProperties> GetServicePropertiesImpl(QueueRequestOptions requestOptions) { RESTCommand <ServiceProperties> retCmd = new RESTCommand <ServiceProperties>(this.Credentials, this.StorageUri); retCmd.CommandLocationMode = CommandLocationMode.PrimaryOrSecondary; retCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => QueueHttpRequestMessageFactory.GetServiceProperties(uri, serverTimeout, ctx, this.GetCanonicalizer(), this.Credentials); retCmd.RetrieveResponseStream = true; retCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex); retCmd.PostProcessResponse = (cmd, resp, ctx) => { return(Task.FromResult(QueueHttpResponseParsers.ReadServiceProperties(cmd.ResponseStream))); }; requestOptions.ApplyToStorageCommand(retCmd); return(retCmd); }
private static RESTCommand <TableResult> ReplaceImpl(TableOperation operation, CloudTableClient client, string tableName, TableRequestOptions requestOptions) { RESTCommand <TableResult> replaceCmd = new RESTCommand <TableResult>(client.Credentials, operation.GenerateRequestURI(client.StorageUri, tableName)); requestOptions.ApplyToStorageCommand(replaceCmd); TableResult result = new TableResult() { Result = operation.Entity }; replaceCmd.RetrieveResponseStream = false; replaceCmd.ParseError = StorageExtendedErrorInformation.ReadFromStreamUsingODataLib; replaceCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => TableOperationHttpRequestMessageFactory.BuildRequestForTableOperation(cmd, uri, builder, serverTimeout, operation, client, cnt, ctx, requestOptions.PayloadFormat.Value, client.GetCanonicalizer(), client.Credentials); replaceCmd.PreProcessResponse = (cmd, resp, ex, ctx) => TableOperationHttpResponseParsers.TableOperationPreProcess(result, operation, resp, ex, cmd, ctx); return(replaceCmd); }
private static RESTCommand <IList <TableResult> > BatchImpl(TableBatchOperation batch, CloudTableClient client, string tableName, TableRequestOptions requestOptions) { RESTCommand <IList <TableResult> > batchCmd = new RESTCommand <IList <TableResult> >(client.Credentials, client.StorageUri); requestOptions.ApplyToStorageCommand(batchCmd); List <TableResult> results = new List <TableResult>(); batchCmd.CommandLocationMode = batch.ContainsWrites ? CommandLocationMode.PrimaryOnly : CommandLocationMode.PrimaryOrSecondary; batchCmd.RetrieveResponseStream = true; batchCmd.ParseError = StorageExtendedErrorInformation.ReadFromStreamUsingODataLib; batchCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => TableOperationHttpRequestMessageFactory.BuildRequestForTableBatchOperation(cmd, uri, builder, serverTimeout, tableName, batch, client, cnt, ctx, requestOptions.PayloadFormat.Value, client.GetCanonicalizer(), client.Credentials); batchCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.Accepted, resp.StatusCode, results, cmd, ex); batchCmd.PostProcessResponse = (cmd, resp, ctx) => TableOperationHttpResponseParsers.TableBatchOperationPostProcess(results, batch, cmd, resp, ctx, requestOptions, client.AccountName); batchCmd.RecoveryAction = (cmd, ex, ctx) => results.Clear(); return(batchCmd); }
private RESTCommand <ServiceStats> GetServiceStatsImpl(TableRequestOptions requestOptions) { if (RetryPolicies.LocationMode.PrimaryOnly == requestOptions.LocationMode) { throw new InvalidOperationException(SR.GetServiceStatsInvalidOperation); } RESTCommand <ServiceStats> retCmd = new RESTCommand <ServiceStats>(this.Credentials, this.StorageUri); requestOptions.ApplyToStorageCommand(retCmd); retCmd.CommandLocationMode = CommandLocationMode.PrimaryOrSecondary; retCmd.BuildRequestDelegate = TableHttpWebRequestFactory.GetServiceStats; retCmd.SignRequest = this.AuthenticationHandler.SignRequest; retCmd.RetrieveResponseStream = true; retCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex); retCmd.PostProcessResponse = (cmd, resp, ctx) => TableHttpWebResponseParsers.ReadServiceStats(cmd.ResponseStream); return(retCmd); }
/// <summary> /// Gets the close handles implementation. /// </summary> /// <param name="token">Continuation token for closing many files.</param> /// <param name="handleId">Id of the handle, "*" if all handles on the file.</param> /// <param name="recursive">Whether to recurse through this directory's files and subfolders.</param> /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the access conditions for the file. If <c>null</c>, no condition is used.</param> /// <param name="options">An <see cref="FileRequestOptions"/> object that specifies additional options for the request.</param> /// <returns>A <see cref="RESTCommand{T}"/> for closing the handles.</returns> private RESTCommand <CloseFileHandleResultSegment> CloseHandleImpl(FileContinuationToken token, string handleId, bool?recursive, AccessCondition accessCondition, FileRequestOptions options) { RESTCommand <CloseFileHandleResultSegment> putCmd = new RESTCommand <CloseFileHandleResultSegment>(this.ServiceClient.Credentials, this.StorageUri, this.ServiceClient.HttpClient); options.ApplyToStorageCommand(putCmd); putCmd.CommandLocationMode = CommandLocationMode.PrimaryOrSecondary; putCmd.RetrieveResponseStream = true; putCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => { StorageRequestMessage msg = FileHttpRequestMessageFactory.CloseHandle(uri, serverTimeout, handleId, recursive, token, accessCondition, cnt, ctx, this.ServiceClient.GetCanonicalizer(), this.ServiceClient.Credentials); FileHttpRequestMessageFactory.AddMetadata(msg, this.Metadata); return(msg); }; putCmd.PreProcessResponse = (cmd, resp, ex, ctx) => { CloseFileHandleResultSegment res = HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex); int handlesClosed; if (!int.TryParse(resp.Headers.GetHeaderSingleValueOrDefault(Constants.HeaderConstants.NumHandlesClosed), out handlesClosed)) { handlesClosed = -1; } FileContinuationToken continuation = null; string marker; if ((marker = resp.Headers.GetHeaderSingleValueOrDefault(Constants.HeaderConstants.Marker)) != "") { continuation = new FileContinuationToken() { NextMarker = marker }; } return(new CloseFileHandleResultSegment() { NumHandlesClosed = handlesClosed, ContinuationToken = continuation }); }; return(putCmd); }
private static RESTCommand <TableQuerySegment <RESULT_TYPE> > QueryImpl <T, RESULT_TYPE>(TableQuery <T> query, TableContinuationToken token, CloudTableClient client, CloudTable table, EntityResolver <RESULT_TYPE> resolver, TableRequestOptions requestOptions) { requestOptions.AssertPolicyIfRequired(); // If encryption policy is set, then add the encryption metadata column to Select columns in order to be able to decrypt properties. if (requestOptions.EncryptionPolicy != null && query.SelectColumns != null && query.SelectColumns.Count() > 0) { query.SelectColumns.Add(Constants.EncryptionConstants.TableEncryptionKeyDetails); query.SelectColumns.Add(Constants.EncryptionConstants.TableEncryptionPropertyDetails); } UriQueryBuilder builder = query.GenerateQueryBuilder(requestOptions.ProjectSystemProperties); if (token != null) { token.ApplyToUriQueryBuilder(builder); } StorageUri tempUri = NavigationHelper.AppendPathToUri(client.StorageUri, table.Name); RESTCommand <TableQuerySegment <RESULT_TYPE> > queryCmd = new RESTCommand <TableQuerySegment <RESULT_TYPE> >(client.Credentials, tempUri); requestOptions.ApplyToStorageCommand(queryCmd); queryCmd.CommandLocationMode = CommonUtility.GetListingLocationMode(token); queryCmd.RetrieveResponseStream = true; queryCmd.SignRequest = client.AuthenticationHandler.SignRequest; queryCmd.Builder = builder; queryCmd.ParseError = ODataErrorHelper.ReadFromStreamUsingODataLib; queryCmd.BuildRequestDelegate = (uri, queryBuilder, timeout, useVersionHeader, ctx) => TableOperationHttpWebRequestFactory.BuildRequestForTableQuery(uri, queryBuilder, timeout, useVersionHeader, ctx, requestOptions.PayloadFormat.Value); queryCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp != null ? resp.StatusCode : HttpStatusCode.Unused, null /* retVal */, cmd, ex); queryCmd.PostProcessResponse = (cmd, resp, ctx) => { ResultSegment <RESULT_TYPE> resSeg = TableOperationHttpResponseParsers.TableQueryPostProcessGeneric <RESULT_TYPE, T>(cmd.ResponseStream, resolver.Invoke, resp, requestOptions, ctx, client.AccountName); if (resSeg.ContinuationToken != null) { resSeg.ContinuationToken.TargetLocation = cmd.CurrentResult.TargetLocation; } return(new TableQuerySegment <RESULT_TYPE>(resSeg)); }; return(queryCmd); }
private static RESTCommand <TableResult> ReplaceImpl(TableOperation operation, CloudTableClient client, string tableName, TableRequestOptions requestOptions) { RESTCommand <TableResult> replaceCmd = new RESTCommand <TableResult>(client.Credentials, operation.GenerateRequestURI(client.BaseUri, tableName)); replaceCmd.ApplyRequestOptions(requestOptions); TableResult result = new TableResult() { Result = operation.Entity }; replaceCmd.RetrieveResponseStream = false; replaceCmd.Handler = client.AuthenticationHandler; replaceCmd.BuildClient = HttpClientFactory.BuildHttpClient; replaceCmd.BuildRequest = (cmd, cnt, ctx) => TableOperationHttpRequestMessageFactory.BuildRequestForTableOperation(cmd, cmd.ServerTimeoutInSeconds, operation, client, ctx); replaceCmd.PreProcessResponse = (cmd, resp, ex, ctx) => TableOperationHttpResponseParsers.TableOperationPreProcess(result, operation, resp, ex, cmd, ctx); return(replaceCmd); }
internal static HttpRequestMessage BuildRequestForTableOperation <T>(RESTCommand <T> cmd, int?timeout, TableOperation operation, CloudTableClient client, OperationContext ctx) { HttpRequestMessage msg = BuildRequestCore(cmd.Uri, operation.HttpMethod, timeout, ctx); if (operation.OperationType == TableOperationType.InsertOrMerge || operation.OperationType == TableOperationType.Merge) { // post tunnelling msg.Headers.Add("X-HTTP-Method", "MERGE"); } // etag if (operation.OperationType == TableOperationType.Delete || operation.OperationType == TableOperationType.Replace || operation.OperationType == TableOperationType.Merge) { msg.Headers.Add("If-Match", operation.Entity.ETag); } if (operation.OperationType == TableOperationType.Insert || operation.OperationType == TableOperationType.Merge || operation.OperationType == TableOperationType.InsertOrMerge || operation.OperationType == TableOperationType.InsertOrReplace || operation.OperationType == TableOperationType.Replace) { // create the writer, indent for readability of the examples. ODataMessageWriterSettings writerSettings = new ODataMessageWriterSettings() { CheckCharacters = false, // sets this flag on the XmlWriter for ATOM Version = ODataVersion.V2 // set the Odata version to use when writing the entry }; HttpRequestAdapterMessage adapterMsg = new HttpRequestAdapterMessage(msg, client.BufferManager, (int)Constants.KB); cmd.StreamToDispose = adapterMsg.GetStream(); ODataMessageWriter odataWriter = new ODataMessageWriter(adapterMsg, writerSettings); ODataWriter writer = odataWriter.CreateODataEntryWriter(); WriteOdataEntity(operation.Entity, operation.OperationType, ctx, writer); return(adapterMsg.GetPopulatedMessage()); } return(msg); }
private static RESTCommand <TableResult> MergeImpl(TableOperation operation, CloudTableClient client, string tableName, TableRequestOptions requestOptions) { RESTCommand <TableResult> mergeCmd = new RESTCommand <TableResult>(client.Credentials, operation.GenerateRequestURI(client.StorageUri, tableName)); requestOptions.ApplyToStorageCommand(mergeCmd); TableResult result = new TableResult() { Result = operation.Entity }; mergeCmd.RetrieveResponseStream = false; mergeCmd.Handler = client.AuthenticationHandler; mergeCmd.BuildClient = HttpClientFactory.BuildHttpClient; mergeCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => TableOperationHttpRequestMessageFactory.BuildRequestForTableOperation(cmd, uri, builder, serverTimeout, operation, client, cnt, ctx); mergeCmd.PreProcessResponse = (cmd, resp, ex, ctx) => TableOperationHttpResponseParsers.TableOperationPreProcess(result, operation, resp, ex, cmd, ctx); return(mergeCmd); }
/// <summary> /// Core implementation for the ListQueues method. /// </summary> /// <param name="prefix">The queue prefix.</param> /// <param name="detailsIncluded">The details included.</param> /// <param name="currentToken">The continuation token.</param> /// <param name="maxResults">A non-negative integer value that indicates the maximum number of results to be returned at a time, up to the /// per-operation limit of 5000. If this value is <c>null</c>, the maximum possible number of results will be returned, up to 5000.</param> /// <returns>A <see cref="TaskSequence"/> that lists the queues.</returns> private RESTCommand <ResultSegment <CloudQueue> > ListQueuesImpl(string prefix, int?maxResults, QueueListingDetails detailsIncluded, QueueRequestOptions options, QueueContinuationToken currentToken) { ListingContext listingContext = new ListingContext(prefix, maxResults) { Marker = currentToken != null ? currentToken.NextMarker : null }; RESTCommand <ResultSegment <CloudQueue> > getCmd = new RESTCommand <ResultSegment <CloudQueue> >(this.Credentials, this.StorageUri); options.ApplyToStorageCommand(getCmd); getCmd.CommandLocationMode = CommonUtility.GetListingLocationMode(currentToken); getCmd.RetrieveResponseStream = true; getCmd.Handler = this.AuthenticationHandler; getCmd.BuildClient = HttpClientFactory.BuildHttpClient; getCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => QueueHttpRequestMessageFactory.List(uri, serverTimeout, listingContext, detailsIncluded, cnt, ctx); getCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex); getCmd.PostProcessResponse = (cmd, resp, ctx) => { return(Task.Factory.StartNew(() => { ListQueuesResponse listQueuesResponse = new ListQueuesResponse(cmd.ResponseStream); List <CloudQueue> queuesList = listQueuesResponse.Queues.Select(item => new CloudQueue(item.Metadata, item.Name, this)).ToList(); QueueContinuationToken continuationToken = null; if (listQueuesResponse.NextMarker != null) { continuationToken = new QueueContinuationToken() { NextMarker = listQueuesResponse.NextMarker, TargetLocation = cmd.CurrentResult.TargetLocation, }; } return new ResultSegment <CloudQueue>(queuesList) { ContinuationToken = continuationToken, }; })); }; return(getCmd); }
private static RESTCommand <TableResult> DeleteImpl(TableOperation operation, CloudTableClient client, CloudTable table, TableRequestOptions requestOptions) { RESTCommand <TableResult> deleteCmd = new RESTCommand <TableResult>(client.Credentials, operation.GenerateRequestURI(client.StorageUri, table.Name)); requestOptions.ApplyToStorageCommand(deleteCmd); TableResult result = new TableResult() { Result = operation.Entity }; deleteCmd.RetrieveResponseStream = false; deleteCmd.SignRequest = client.AuthenticationHandler.SignRequest; deleteCmd.ParseError = StorageExtendedErrorInformation.ReadFromStreamUsingODataLib; deleteCmd.BuildRequestDelegate = (uri, builder, timeout, useVersionHeader, ctx) => TableOperationHttpWebRequestFactory.BuildRequestForTableOperation(uri, builder, client.BufferManager, timeout, operation, useVersionHeader, ctx, requestOptions, client.AccountName).Item1; deleteCmd.PreProcessResponse = (cmd, resp, ex, ctx) => TableOperationHttpResponseParsers.TableOperationPreProcess(result, operation, resp, ex); return(deleteCmd); }
/// <summary> /// Implementation for the Exists method. /// </summary> /// <param name="options">An object that specifies additional options for the request.</param> /// <returns>A <see cref="RESTCommand"/> that checks existence.</returns> private RESTCommand <bool> ExistsImpl(FileRequestOptions options) { RESTCommand <bool> getCmd = new RESTCommand <bool>(this.ServiceClient.Credentials, this.StorageUri); options.ApplyToStorageCommand(getCmd); getCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => DirectoryHttpRequestMessageFactory.GetProperties(uri, serverTimeout, null, cnt, ctx, this.ServiceClient.GetCanonicalizer(), this.ServiceClient.Credentials); getCmd.PreProcessResponse = (cmd, resp, ex, ctx) => { if (resp.StatusCode == HttpStatusCode.NotFound) { return(false); } HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, true, cmd, ex); this.Properties = DirectoryHttpResponseParsers.GetProperties(resp); return(true); }; return(getCmd); }
/// <summary> /// Implementation for the SetMetadata method. /// </summary> /// <param name="accessCondition">An object that represents the access conditions for the directory. If null, no condition is used.</param> /// <param name="options">An object that specifies additional options for the request.</param> /// <returns>A <see cref="RESTCommand"/> that sets the metadata.</returns> private RESTCommand <NullType> SetMetadataImpl(AccessCondition accessCondition, FileRequestOptions options) { RESTCommand <NullType> putCmd = new RESTCommand <NullType>(this.ServiceClient.Credentials, this.StorageUri); options.ApplyToStorageCommand(putCmd); putCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => { StorageRequestMessage msg = DirectoryHttpRequestMessageFactory.SetMetadata(uri, serverTimeout, accessCondition, cnt, ctx, this.ServiceClient.GetCanonicalizer(), this.ServiceClient.Credentials); DirectoryHttpRequestMessageFactory.AddMetadata(msg, this.Metadata); return(msg); }; putCmd.PreProcessResponse = (cmd, resp, ex, ctx) => { HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, NullType.Value, cmd, ex); this.UpdateETagAndLastModified(resp); return(NullType.Value); }; return(putCmd); }
public static HttpClient BuildHttpClient <T>(RESTCommand <T> cmd, HttpMessageHandler handler, OperationContext operationContext) { HttpClient client = handler != null ? new HttpClient(handler, false) : new HttpClient(); client.DefaultRequestHeaders.ExpectContinue = false; client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(Constants.HeaderConstants.UserAgentProductName, Constants.HeaderConstants.UserAgentProductVersion)); client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(Constants.HeaderConstants.UserAgentComment)); client.DefaultRequestHeaders.TryAddWithoutValidation(Constants.HeaderConstants.StorageVersionHeader, Constants.HeaderConstants.TargetStorageVersion); if (operationContext != null && operationContext.UserHeaders != null) { foreach (string key in operationContext.UserHeaders.Keys) { client.DefaultRequestHeaders.Add(key, operationContext.UserHeaders[key]); } } return(client); }
internal IAsyncOperation <IList <TableResult> > ExecuteAsync(CloudTableClient client, string tableName, TableRequestOptions requestOptions, OperationContext operationContext) { TableRequestOptions modifiedOptions = TableRequestOptions.ApplyDefaults(requestOptions, client); operationContext = operationContext ?? new OperationContext(); CommonUtility.AssertNotNullOrEmpty("tableName", tableName); if (this.operations.Count == 0) { throw new InvalidOperationException(SR.EmptyBatchOperation); } RESTCommand <IList <TableResult> > cmdToExecute = BatchImpl(this, client, tableName, modifiedOptions); return(AsyncInfo.Run(async(cancellationToken) => await Executor.ExecuteAsync( cmdToExecute, modifiedOptions.RetryPolicy, operationContext, cancellationToken))); }
private RESTCommand <ServiceProperties> GetServicePropertiesImpl(QueueRequestOptions requestOptions) { RESTCommand <ServiceProperties> retCmd = new RESTCommand <ServiceProperties>(this.Credentials, this.BaseUri); retCmd.BuildRequest = (cmd, cnt, ctx) => QueueHttpRequestMessageFactory.GetServiceProperties(cmd.Uri, cmd.ServerTimeoutInSeconds, ctx); retCmd.RetrieveResponseStream = true; retCmd.Handler = this.AuthenticationHandler; retCmd.BuildClient = HttpClientFactory.BuildHttpClient; retCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(System.Net.HttpStatusCode.OK, resp, null /* retVal */, cmd, ex); retCmd.PostProcessResponse = (cmd, resp, ctx) => { return(Task.Factory.StartNew(() => QueueHttpResponseParsers.ReadServiceProperties(cmd.ResponseStream))); }; retCmd.ApplyRequestOptions(requestOptions); return(retCmd); }
private static RESTCommand <TableResult> RetrieveImpl(TableOperation operation, CloudTableClient client, CloudTable table, TableRequestOptions requestOptions) { requestOptions.AssertPolicyIfRequired(); RESTCommand <TableResult> retrieveCmd = new RESTCommand <TableResult>(client.Credentials, operation.GenerateRequestURI(client.StorageUri, table.Name)); requestOptions.ApplyToStorageCommand(retrieveCmd); TableResult result = new TableResult(); if (operation.SelectColumns != null && operation.SelectColumns.Count > 0) { // If encryption policy is set, then add the encryption metadata column to Select columns in order to be able to decrypt properties. if (requestOptions.EncryptionPolicy != null) { operation.SelectColumns.Add(Constants.EncryptionConstants.TableEncryptionKeyDetails); operation.SelectColumns.Add(Constants.EncryptionConstants.TableEncryptionPropertyDetails); } retrieveCmd.Builder = operation.GenerateQueryBuilder(requestOptions.ProjectSystemProperties); } retrieveCmd.CommandLocationMode = operation.isPrimaryOnlyRetrieve ? CommandLocationMode.PrimaryOnly : CommandLocationMode.PrimaryOrSecondary; retrieveCmd.RetrieveResponseStream = true; retrieveCmd.SignRequest = client.AuthenticationHandler.SignRequest; retrieveCmd.ParseError = StorageExtendedErrorInformation.ReadFromStreamUsingODataLib; retrieveCmd.BuildRequestDelegate = (uri, builder, timeout, useVersionHeader, ctx) => TableOperationHttpWebRequestFactory.BuildRequestForTableOperation(uri, builder, client.BufferManager, timeout, operation, useVersionHeader, ctx, requestOptions, client.AccountName).Item1; retrieveCmd.PreProcessResponse = (cmd, resp, ex, ctx) => TableOperationHttpResponseParsers.TableOperationPreProcess(result, operation, resp, ex); retrieveCmd.PostProcessResponse = (cmd, resp, ctx) => { if (resp.StatusCode == HttpStatusCode.NotFound) { return(result); } result = TableOperationHttpResponseParsers.TableOperationPostProcess(result, operation, cmd, resp, ctx, requestOptions, client.AccountName); return(result); }; return(retrieveCmd); }
public async Task WriteToMultiBufferMemoryStreamTestAsync() { OperationContext tempOperationContext = new OperationContext(); RESTCommand<NullType> cmd = new RESTCommand<NullType>(TestBase.StorageCredentials, null); ExecutionState<NullType> tempExecutionState = new ExecutionState<NullType>(cmd, null, tempOperationContext); byte[] buffer = GetRandomBuffer(1 * 1024 * 1024); MemoryStream stream1 = new MemoryStream(buffer); MultiBufferMemoryStream stream2 = new MultiBufferMemoryStream(null /* bufferManager */); await stream1.WriteToAsync(stream2, null, null, false, tempExecutionState, null, CancellationToken.None); stream1.Seek(0, SeekOrigin.Begin); stream2.Seek(0, SeekOrigin.Begin); TestHelper.AssertStreamsAreEqual(stream1, stream2); MultiBufferMemoryStream stream3 = new MultiBufferMemoryStream(null /* bufferManager */); await TestHelper.ExpectedExceptionAsync<TimeoutException>( () => stream2.FastCopyToAsync(stream3, DateTime.Now.AddMinutes(-1)), "Past expiration time should immediately fail"); stream2.Seek(0, SeekOrigin.Begin); stream3.Seek(0, SeekOrigin.Begin); await stream2.FastCopyToAsync(stream3, DateTime.Now.AddHours(1)); stream2.Seek(0, SeekOrigin.Begin); stream3.Seek(0, SeekOrigin.Begin); TestHelper.AssertStreamsAreEqual(stream2, stream3); MultiBufferMemoryStream stream4 = new MultiBufferMemoryStream(null /* bufferManager */, 12345); await stream3.FastCopyToAsync(stream4, null); stream3.Seek(0, SeekOrigin.Begin); stream4.Seek(0, SeekOrigin.Begin); TestHelper.AssertStreamsAreEqual(stream3, stream4); MemoryStream stream5 = new MemoryStream(); await stream4.WriteToAsync(stream5, null, null, false, tempExecutionState, null, CancellationToken.None); stream4.Seek(0, SeekOrigin.Begin); stream5.Seek(0, SeekOrigin.Begin); TestHelper.AssertStreamsAreEqual(stream4, stream5); TestHelper.AssertStreamsAreEqual(stream1, stream5); }
/// <summary> /// Gets the download block list. /// </summary> /// <param name="typesOfBlocks">The types of blocks.</param> /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the access conditions for the blob. If <c>null</c>, no condition is used.</param> /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies any additional options for the request.</param> /// <returns>A <see cref="RESTCommand{T}"/> that gets the download block list.</returns> internal RESTCommand<IEnumerable<ListBlockItem>> GetBlockListImpl(BlockListingFilter typesOfBlocks, AccessCondition accessCondition, BlobRequestOptions options) { RESTCommand<IEnumerable<ListBlockItem>> getCmd = new RESTCommand<IEnumerable<ListBlockItem>>(this.ServiceClient.Credentials, this.Uri); getCmd.ApplyRequestOptions(options); getCmd.RetrieveResponseStream = true; getCmd.BuildRequestDelegate = (uri, builder, serverTimeout, ctx) => BlobHttpWebRequestFactory.GetBlockList(uri, serverTimeout, this.SnapshotTime, typesOfBlocks, accessCondition, ctx); getCmd.SignRequest = this.ServiceClient.AuthenticationHandler.SignRequest; getCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex); getCmd.PostProcessResponse = (cmd, resp, ctx) => { CloudBlobSharedImpl.UpdateETagLMTAndSequenceNumber(this.attributes, resp); GetBlockListResponse responseParser = new GetBlockListResponse(cmd.ResponseStream); IEnumerable<ListBlockItem> blocks = new List<ListBlockItem>(responseParser.Blocks); return blocks; }; return getCmd; }
/// <summary> /// Uploads the block list. /// </summary> /// <param name="blocks">The blocks to upload.</param> /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the access conditions for the blob. If <c>null</c>, no condition is used.</param> /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies any additional options for the request.</param> /// <returns>A <see cref="RESTCommand{T}"/> that uploads the block list.</returns> internal RESTCommand<NullType> PutBlockListImpl(IEnumerable<PutBlockListItem> blocks, AccessCondition accessCondition, BlobRequestOptions options) { MultiBufferMemoryStream memoryStream = new MultiBufferMemoryStream(this.ServiceClient.BufferManager); BlobRequest.WriteBlockListBody(blocks, memoryStream); memoryStream.Seek(0, SeekOrigin.Begin); #if !WINDOWS_PHONE string contentMD5 = memoryStream.ComputeMD5Hash(); memoryStream.Seek(0, SeekOrigin.Begin); #endif RESTCommand<NullType> putCmd = new RESTCommand<NullType>(this.ServiceClient.Credentials, this.Uri); putCmd.ApplyRequestOptions(options); putCmd.BuildRequestDelegate = (uri, builder, serverTimeout, ctx) => BlobHttpWebRequestFactory.PutBlockList(uri, serverTimeout, this.Properties, accessCondition, ctx); putCmd.SetHeaders = (r, ctx) => { #if !WINDOWS_PHONE r.Headers[HttpRequestHeader.ContentMd5] = contentMD5; #endif BlobHttpWebRequestFactory.AddMetadata(r, this.Metadata); }; putCmd.SendStream = memoryStream; putCmd.RecoveryAction = RecoveryActions.RewindStream; putCmd.SignRequest = this.ServiceClient.AuthenticationHandler.SignRequest; putCmd.PreProcessResponse = (cmd, resp, ex, ctx) => { HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.Created, resp, NullType.Value, cmd, ex); CloudBlobSharedImpl.UpdateETagLMTAndSequenceNumber(this.attributes, resp); this.Properties.Length = -1; return NullType.Value; }; return putCmd; }
/// <summary> /// Uploads the block. /// </summary> /// <param name="source">The source stream.</param> /// <param name="blockId">The block ID.</param> /// <param name="contentMD5">The content MD5.</param> /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the access conditions for the blob. If <c>null</c>, no condition is used.</param> /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies any additional options for the request.</param> /// <returns>A <see cref="RESTCommand{T}"/> that uploads the block.</returns> internal RESTCommand<NullType> PutBlockImpl(Stream source, string blockId, string contentMD5, AccessCondition accessCondition, BlobRequestOptions options) { long offset = source.Position; RESTCommand<NullType> putCmd = new RESTCommand<NullType>(this.ServiceClient.Credentials, this.Uri); putCmd.ApplyRequestOptions(options); putCmd.SendStream = source; putCmd.RecoveryAction = (cmd, ex, ctx) => RecoveryActions.SeekStream(cmd, offset); putCmd.BuildRequestDelegate = (uri, builder, serverTimeout, ctx) => BlobHttpWebRequestFactory.PutBlock(uri, serverTimeout, blockId, accessCondition, ctx); putCmd.SetHeaders = (r, ctx) => { if (!string.IsNullOrEmpty(contentMD5)) { r.Headers[HttpRequestHeader.ContentMd5] = contentMD5; } }; putCmd.SignRequest = this.ServiceClient.AuthenticationHandler.SignRequest; putCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.Created, resp, NullType.Value, cmd, ex); return putCmd; }
/// <summary> /// Uploads the full blob from a seekable stream. /// </summary> /// <param name="stream">The content stream. Must be seekable.</param> /// <param name="length">Number of bytes to upload from the content stream starting at its current position.</param> /// <param name="contentMD5">The content MD5.</param> /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the access conditions for the blob. If <c>null</c>, no condition is used.</param> /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies any additional options for the request.</param> /// <returns>A <see cref="RESTCommand{T}"/> that gets the stream.</returns> private RESTCommand<NullType> PutBlobImpl(Stream stream, long? length, string contentMD5, AccessCondition accessCondition, BlobRequestOptions options) { long offset = stream.Position; this.Properties.ContentMD5 = contentMD5; RESTCommand<NullType> putCmd = new RESTCommand<NullType>(this.ServiceClient.Credentials, this.Uri); putCmd.ApplyRequestOptions(options); putCmd.SendStream = stream; putCmd.SendStreamLength = length ?? stream.Length - offset; putCmd.RecoveryAction = (cmd, ex, ctx) => RecoveryActions.SeekStream(cmd, offset); putCmd.BuildRequestDelegate = (uri, builder, serverTimeout, ctx) => BlobHttpWebRequestFactory.Put(uri, serverTimeout, this.Properties, BlobType.BlockBlob, 0, accessCondition, ctx); putCmd.SetHeaders = (r, ctx) => BlobHttpWebRequestFactory.AddMetadata(r, this.Metadata); putCmd.SignRequest = this.ServiceClient.AuthenticationHandler.SignRequest; putCmd.PreProcessResponse = (cmd, resp, ex, ctx) => { HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.Created, resp, NullType.Value, cmd, ex); CloudBlobSharedImpl.UpdateETagLMTAndSequenceNumber(this.attributes, resp); this.Properties.Length = putCmd.SendStreamLength.Value; return NullType.Value; }; return putCmd; }
/// <summary> /// Implementation for the SetSequenceNumber method. /// </summary> /// <param name="sequenceNumberAction">A value of type <see cref="SequenceNumberAction"/>, indicating the operation to perform on the sequence number.</param> /// <param name="sequenceNumber">The sequence number. Set this parameter to <c>null</c> if this operation is an increment action.</param> /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the access conditions for the blob. If <c>null</c>, no condition is used.</param> /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies additional options for the request.</param> /// <returns>A <see cref="RESTCommand"/> that sets the metadata.</returns> private RESTCommand<NullType> SetSequenceNumberImpl(SequenceNumberAction sequenceNumberAction, long? sequenceNumber, AccessCondition accessCondition, BlobRequestOptions options) { RESTCommand<NullType> putCmd = new RESTCommand<NullType>(this.ServiceClient.Credentials, this.attributes.StorageUri); options.ApplyToStorageCommand(putCmd); putCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => BlobHttpRequestMessageFactory.SetSequenceNumber(uri, serverTimeout, sequenceNumberAction, sequenceNumber, accessCondition, cnt, ctx, this.ServiceClient.GetCanonicalizer(), this.ServiceClient.Credentials); putCmd.PreProcessResponse = (cmd, resp, ex, ctx) => { HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, NullType.Value, cmd, ex); CloudBlob.UpdateETagLMTLengthAndSequenceNumber(attributes, resp, false); return NullType.Value; }; return putCmd; }
/// <summary> /// Implements the Create method. /// </summary> /// <param name="sizeInBytes">The size in bytes.</param> /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the access conditions for the blob. If null, no condition is used.</param> /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies additional options for the request.</param> /// <returns>A <see cref="TaskSequence"/> that creates the blob.</returns> private RESTCommand<NullType> CreateImpl(long sizeInBytes, AccessCondition accessCondition, BlobRequestOptions options) { RESTCommand<NullType> putCmd = new RESTCommand<NullType>(this.ServiceClient.Credentials, this.attributes.StorageUri); options.ApplyToStorageCommand(putCmd); putCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => { StorageRequestMessage msg = BlobHttpRequestMessageFactory.Put(uri, serverTimeout, this.Properties, BlobType.PageBlob, sizeInBytes, accessCondition, cnt, ctx, this.ServiceClient.GetCanonicalizer(), this.ServiceClient.Credentials); BlobHttpRequestMessageFactory.AddMetadata(msg, this.Metadata); return msg; }; putCmd.PreProcessResponse = (cmd, resp, ex, ctx) => { HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.Created, resp, NullType.Value, cmd, ex); CloudBlob.UpdateETagLMTLengthAndSequenceNumber(this.attributes, resp, false); cmd.CurrentResult.IsRequestServerEncrypted = CloudBlob.ParseServerRequestEncrypted(resp); this.Properties.Length = sizeInBytes; return NullType.Value; }; return putCmd; }
/// <summary> /// Implementation method for the WritePage methods. /// </summary> /// <param name="pageData">The page data.</param> /// <param name="startOffset">The start offset.</param> /// <param name="contentMD5">The content MD5.</param> /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the access conditions for the blob. If <c>null</c>, no condition is used.</param> /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies any additional options for the request.</param> /// <returns>A <see cref="RESTCommand{T}"/> that writes the pages.</returns> private RESTCommand<NullType> PutPageImpl(Stream pageData, long startOffset, string contentMD5, AccessCondition accessCondition, BlobRequestOptions options) { if (startOffset % Constants.PageSize != 0) { CommonUtils.ArgumentOutOfRange("startOffset", startOffset); } long offset = pageData.Position; long length = pageData.Length - offset; PageRange pageRange = new PageRange(startOffset, startOffset + length - 1); PageWrite pageWrite = PageWrite.Update; if ((1 + pageRange.EndOffset - pageRange.StartOffset) % Constants.PageSize != 0 || (1 + pageRange.EndOffset - pageRange.StartOffset) == 0) { CommonUtils.ArgumentOutOfRange("pageData", pageData); } RESTCommand<NullType> putCmd = new RESTCommand<NullType>(this.ServiceClient.Credentials, this.Uri); putCmd.ApplyRequestOptions(options); putCmd.SendStream = pageData; putCmd.RecoveryAction = (cmd, ex, ctx) => RecoveryActions.SeekStream(cmd, ex, ctx, offset); putCmd.BuildRequestDelegate = (uri, builder, serverTimeout, ctx) => BlobHttpWebRequestFactory.PutPage(uri, serverTimeout, pageRange, pageWrite, accessCondition, ctx); putCmd.SetHeaders = (r, ctx) => { if (!string.IsNullOrEmpty(contentMD5)) { r.Headers.Set(HttpRequestHeader.ContentMd5, contentMD5); } }; putCmd.SignRequest = this.ServiceClient.AuthenticationHandler.SignRequest; putCmd.PreProcessResponse = (cmd, resp, ex, ctx) => { HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.Created, resp, NullType.Value, cmd, ex, ctx); CloudBlobSharedImpl.ParseSizeAndLastModified(this.attributes, resp); return NullType.Value; }; return putCmd; }
/// <summary> /// Implementation method for the WritePage methods. /// </summary> /// <param name="pageData">The page data.</param> /// <param name="startOffset">The start offset.</param> /// <param name="contentMD5">An optional hash value that will be used to set the <see cref="BlobProperties.ContentMD5"/> property /// on the blob. May be <c>null</c> or an empty string.</param> /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the access conditions for the blob. If <c>null</c>, no condition is used.</param> /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies additional options for the request.</param> /// <returns>A <see cref="RESTCommand"/> that writes the pages.</returns> private RESTCommand<NullType> PutPageImpl(Stream pageData, long startOffset, string contentMD5, AccessCondition accessCondition, BlobRequestOptions options) { if (startOffset % Constants.PageSize != 0) { CommonUtility.ArgumentOutOfRange("startOffset", startOffset); } long offset = pageData.Position; long length = pageData.Length - offset; PageRange pageRange = new PageRange(startOffset, startOffset + length - 1); PageWrite pageWrite = PageWrite.Update; if ((1 + pageRange.EndOffset - pageRange.StartOffset) % Constants.PageSize != 0 || (1 + pageRange.EndOffset - pageRange.StartOffset) == 0) { CommonUtility.ArgumentOutOfRange("pageData", pageData); } RESTCommand<NullType> putCmd = new RESTCommand<NullType>(this.ServiceClient.Credentials, this.attributes.StorageUri); options.ApplyToStorageCommand(putCmd); putCmd.BuildContent = (cmd, ctx) => HttpContentFactory.BuildContentFromStream(pageData, offset, length, contentMD5, cmd, ctx); putCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => BlobHttpRequestMessageFactory.PutPage(uri, serverTimeout, pageRange, pageWrite, accessCondition, cnt, ctx, this.ServiceClient.GetCanonicalizer(), this.ServiceClient.Credentials); putCmd.PreProcessResponse = (cmd, resp, ex, ctx) => { HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.Created, resp, NullType.Value, cmd, ex); CloudBlob.UpdateETagLMTLengthAndSequenceNumber(this.attributes, resp, false); cmd.CurrentResult.IsRequestServerEncrypted = CloudBlob.ParseServerRequestEncrypted(resp); return NullType.Value; }; return putCmd; }
/// <summary> /// Implementation for the GetPageRangesDiff method. /// </summary> /// <param name="previousSnapshotTime">A <see cref="DateTimeOffset"/> representing the snapshot timestamp to use as the starting point for the diff. If this CloudPageBlob represents a snapshot, the previousSnapshotTime parameter must be prior to the current snapshot timestamp.</param> /// <param name="offset">The starting offset of the data range over which to list page ranges, in bytes. Must be a multiple of 512.</param> /// <param name="length">The length of the data range over which to list page ranges, in bytes. Must be a multiple of 512.</param> /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the access conditions for the blob. If <c>null</c>, no condition is used.</param> /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies additional options for the request.</param> /// <returns>A <see cref="RESTCommand"/> for getting the page ranges.</returns> private RESTCommand<IEnumerable<PageDiffRange>> GetPageRangesDiffImpl(DateTimeOffset previousSnapshotTime, long? offset, long? length, AccessCondition accessCondition, BlobRequestOptions options) { RESTCommand<IEnumerable<PageDiffRange>> getCmd = new RESTCommand<IEnumerable<PageDiffRange>>(this.ServiceClient.Credentials, this.attributes.StorageUri); options.ApplyToStorageCommand(getCmd); getCmd.CommandLocationMode = CommandLocationMode.PrimaryOrSecondary; getCmd.RetrieveResponseStream = true; getCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => { StorageRequestMessage msg = BlobHttpRequestMessageFactory.GetPageRangesDiff(uri, serverTimeout, this.SnapshotTime, previousSnapshotTime, offset, length, accessCondition, cnt, ctx, this.ServiceClient.GetCanonicalizer(), this.ServiceClient.Credentials); return msg; }; getCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex); getCmd.PostProcessResponse = (cmd, resp, ctx) => { CloudBlob.UpdateETagLMTLengthAndSequenceNumber(this.attributes, resp, true); return Task.Factory.StartNew(() => { GetPageDiffRangesResponse getPageDiffRangesResponse = new GetPageDiffRangesResponse(cmd.ResponseStream); IEnumerable<PageDiffRange> pageDiffRanges = new List<PageDiffRange>(getPageDiffRangesResponse.PageDiffRanges); return pageDiffRanges; }); }; return getCmd; }
/// <summary> /// Implementation for the CreateSnapshot method. /// </summary> /// <param name="metadata">A collection of name-value pairs defining the metadata of the snapshot, or <c>null</c>.</param> /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the access conditions for the blob. If <c>null</c>, no condition is used.</param> /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies additional options for the request.</param> /// <returns>A <see cref="RESTCommand"/> that creates the snapshot.</returns> /// <remarks>If the <c>metadata</c> parameter is <c>null</c> then no metadata is associated with the request.</remarks> private RESTCommand<CloudPageBlob> CreateSnapshotImpl(IDictionary<string, string> metadata, AccessCondition accessCondition, BlobRequestOptions options) { RESTCommand<CloudPageBlob> putCmd = new RESTCommand<CloudPageBlob>(this.ServiceClient.Credentials, this.attributes.StorageUri); options.ApplyToStorageCommand(putCmd); putCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => { StorageRequestMessage msg = BlobHttpRequestMessageFactory.Snapshot(uri, serverTimeout, accessCondition, cnt, ctx, this.ServiceClient.GetCanonicalizer(), this.ServiceClient.Credentials); if (metadata != null) { BlobHttpRequestMessageFactory.AddMetadata(msg, metadata); } return msg; }; putCmd.PreProcessResponse = (cmd, resp, ex, ctx) => { HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.Created, resp, null /* retVal */, cmd, ex); DateTimeOffset snapshotTime = NavigationHelper.ParseSnapshotTime(BlobHttpResponseParsers.GetSnapshotTime(resp)); CloudPageBlob snapshot = new CloudPageBlob(this.Name, snapshotTime, this.Container); snapshot.attributes.Metadata = new Dictionary<string, string>(metadata ?? this.Metadata); snapshot.attributes.Properties = new BlobProperties(this.Properties); CloudBlob.UpdateETagLMTLengthAndSequenceNumber(snapshot.attributes, resp, false); return snapshot; }; return putCmd; }
private RESTCommand<NullType> SetServicePropertiesImpl(ServiceProperties properties, TableRequestOptions requestOptions) { MultiBufferMemoryStream memoryStream = new MultiBufferMemoryStream(null /* bufferManager */, (int)(1 * Constants.KB)); try { properties.WriteServiceProperties(memoryStream); } catch (InvalidOperationException invalidOpException) { throw new ArgumentException(invalidOpException.Message, "properties"); } RESTCommand<NullType> retCmd = new RESTCommand<NullType>(this.Credentials, this.StorageUri); requestOptions.ApplyToStorageCommand(retCmd); retCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => TableHttpRequestMessageFactory.SetServiceProperties(uri, serverTimeout, cnt, ctx); retCmd.BuildContent = (cmd, ctx) => HttpContentFactory.BuildContentFromStream(memoryStream, 0, memoryStream.Length, null /* md5 */, cmd, ctx); retCmd.Handler = this.AuthenticationHandler; retCmd.BuildClient = HttpClientFactory.BuildHttpClient; retCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.Accepted, resp, null /* retVal */, cmd, ex); requestOptions.ApplyToStorageCommand(retCmd); return retCmd; }
private RESTCommand<ServiceProperties> GetServicePropertiesImpl(BlobRequestOptions requestOptions) { RESTCommand<ServiceProperties> retCmd = new RESTCommand<ServiceProperties>(this.Credentials, this.BaseUri); retCmd.BuildRequestDelegate = BlobHttpWebRequestFactory.GetServiceProperties; retCmd.SignRequest = this.AuthenticationHandler.SignRequest; retCmd.RetrieveResponseStream = true; retCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException( System.Net.HttpStatusCode.OK, resp, null /* retVal */, cmd, ex, ctx); retCmd.PostProcessResponse = (cmd, resp, ex, ctx) => BlobHttpResponseParsers.ReadServiceProperties(cmd.ResponseStream); retCmd.ApplyRequestOptions(requestOptions); return retCmd; }
/// <summary> /// Core implementation for the ListContainers method. /// </summary> /// <param name="prefix">The container prefix.</param> /// <param name="detailsIncluded">The details included.</param> /// <param name="currentToken">The continuation token.</param> /// <param name="maxResults">A non-negative integer value that indicates the maximum number of results to be returned /// in the result segment, up to the per-operation limit of 5000. If this value is null, the maximum possible number of results will be returned, up to 5000.</param> /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies any additional options for the request.</param> /// <returns>A <see cref="ResultSegment{T}"/> that lists the containers.</returns> private RESTCommand<ResultSegment<CloudBlobContainer>> ListContainersImpl(string prefix, ContainerListingDetails detailsIncluded, BlobContinuationToken currentToken, int? maxResults, BlobRequestOptions options) { ListingContext listingContext = new ListingContext(prefix, maxResults) { Marker = currentToken != null ? currentToken.NextMarker : null }; RESTCommand<ResultSegment<CloudBlobContainer>> getCmd = new RESTCommand<ResultSegment<CloudBlobContainer>>(this.Credentials, this.BaseUri); getCmd.ApplyRequestOptions(options); getCmd.RetrieveResponseStream = true; getCmd.BuildRequestDelegate = (uri, builder, serverTimeout, ctx) => ContainerHttpWebRequestFactory.List(uri, serverTimeout, listingContext, detailsIncluded, ctx); getCmd.SignRequest = this.AuthenticationHandler.SignRequest; getCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex, ctx); getCmd.PostProcessResponse = (cmd, resp, ex, ctx) => { ListContainersResponse listContainersResponse = new ListContainersResponse(cmd.ResponseStream); List<CloudBlobContainer> containersList = new List<CloudBlobContainer>( listContainersResponse.Containers.Select(item => new CloudBlobContainer(item.Properties, item.Metadata, item.Name, this))); BlobContinuationToken continuationToken = null; if (listContainersResponse.NextMarker != null) { continuationToken = new BlobContinuationToken() { NextMarker = listContainersResponse.NextMarker, }; } return new ResultSegment<CloudBlobContainer>(containersList) { ContinuationToken = continuationToken, }; }; return getCmd; }
/// <summary> /// Implementation method for the ClearPage methods. /// </summary> /// <param name="startOffset">The start offset. Must be multiples of 512.</param> /// <param name="length">Length of the data range to be cleared. Must be multiples of 512.</param> /// <param name="accessCondition">An object that represents the access conditions for the blob. If <c>null</c>, no condition is used.</param> /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies additional options for the request.</param> /// <returns>A <see cref="RESTCommand"/> that writes the pages.</returns> private RESTCommand<NullType> ClearPageImpl(long startOffset, long length, AccessCondition accessCondition, BlobRequestOptions options) { CommonUtility.AssertNotNull("options", options); if (startOffset < 0 || startOffset % Constants.PageSize != 0) { CommonUtility.ArgumentOutOfRange("startOffset", startOffset); } if (length <= 0 || length % Constants.PageSize != 0) { CommonUtility.ArgumentOutOfRange("length", length); } PageRange pageRange = new PageRange(startOffset, startOffset + length - 1); PageWrite pageWrite = PageWrite.Clear; RESTCommand<NullType> putCmd = new RESTCommand<NullType>(this.ServiceClient.Credentials, this.attributes.StorageUri); options.ApplyToStorageCommand(putCmd); putCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => BlobHttpRequestMessageFactory.PutPage(uri, serverTimeout, pageRange, pageWrite, accessCondition, cnt, ctx, this.ServiceClient.GetCanonicalizer(), this.ServiceClient.Credentials); putCmd.PreProcessResponse = (cmd, resp, ex, ctx) => { HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.Created, resp, NullType.Value, cmd, ex); CloudBlob.UpdateETagLMTLengthAndSequenceNumber(this.attributes, resp, false); return NullType.Value; }; return putCmd; }
/// <summary> /// Implementation for the Resize method. /// </summary> /// <param name="sizeInBytes">The size in bytes.</param> /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the access conditions for the blob. If <c>null</c>, no condition is used.</param> /// <param name="options">An <see cref="BlobRequestOptions"/> object that specifies any additional options for the request.</param> /// <returns>A <see cref="RESTCommand{T}"/> that sets the metadata.</returns> private RESTCommand<NullType> ResizeImpl(long sizeInBytes, AccessCondition accessCondition, BlobRequestOptions options) { RESTCommand<NullType> putCmd = new RESTCommand<NullType>(this.ServiceClient.Credentials, this.Uri); putCmd.ApplyRequestOptions(options); putCmd.BuildRequestDelegate = (uri, builder, serverTimeout, ctx) => BlobHttpWebRequestFactory.Resize(uri, serverTimeout, sizeInBytes, accessCondition, ctx); putCmd.SignRequest = this.ServiceClient.AuthenticationHandler.SignRequest; putCmd.PreProcessResponse = (cmd, resp, ex, ctx) => { HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, NullType.Value, cmd, ex, ctx); CloudBlobSharedImpl.ParseSizeAndLastModified(attributes, resp); this.Properties.Length = sizeInBytes; return NullType.Value; }; return putCmd; }
/// <summary> /// Implementation for the CreateSnapshot method. /// </summary> /// <param name="metadata">A collection of name-value pairs defining the metadata of the snapshot, or null.</param> /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the access conditions for the blob. If <c>null</c>, no condition is used.</param> /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies any additional options for the request.</param> /// <returns>A <see cref="RESTCommand{T}"/> that creates the snapshot.</returns> /// <remarks>If the <c>metadata</c> parameter is <c>null</c> then no metadata is associated with the request.</remarks> private RESTCommand<CloudPageBlob> CreateSnapshotImpl(IDictionary<string, string> metadata, AccessCondition accessCondition, BlobRequestOptions options) { RESTCommand<CloudPageBlob> putCmd = new RESTCommand<CloudPageBlob>(this.ServiceClient.Credentials, this.Uri); putCmd.ApplyRequestOptions(options); putCmd.BuildRequestDelegate = (uri, builder, serverTimeout, ctx) => BlobHttpWebRequestFactory.Snapshot(uri, serverTimeout, accessCondition, ctx); putCmd.SetHeaders = (r, ctx) => { if (metadata != null) { BlobHttpWebRequestFactory.AddMetadata(r, metadata); } }; putCmd.SignRequest = this.ServiceClient.AuthenticationHandler.SignRequest; putCmd.PreProcessResponse = (cmd, resp, ex, ctx) => { HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.Created, resp, null /* retVal */, cmd, ex, ctx); DateTimeOffset snapshotTime = NavigationHelper.ParseSnapshotTime(BlobHttpResponseParsers.GetSnapshotTime(resp)); CloudPageBlob snapshot = new CloudPageBlob(this.Name, snapshotTime, this.Container); snapshot.attributes.Metadata = new Dictionary<string, string>(metadata ?? this.Metadata); snapshot.attributes.Properties = new BlobProperties(this.Properties); CloudBlobSharedImpl.ParseSizeAndLastModified(snapshot.attributes, resp); return snapshot; }; return putCmd; }
/// <summary> /// Gets the page ranges impl. /// </summary> /// <param name="offset">The start offset. Must be multiples of 512.</param> /// <param name="length">Length of the data range to be cleared. Must be multiples of 512.</param> /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the access conditions for the blob. If <c>null</c>, no condition is used.</param> /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies any additional options for the request.</param> /// <returns>A <see cref="RESTCommand{T}"/> for getting the page ranges.</returns> private RESTCommand<IEnumerable<PageRange>> GetPageRangesImpl(long? offset, long? length, AccessCondition accessCondition, BlobRequestOptions options) { RESTCommand<IEnumerable<PageRange>> getCmd = new RESTCommand<IEnumerable<PageRange>>(this.ServiceClient.Credentials, this.Uri); getCmd.ApplyRequestOptions(options); getCmd.RetrieveResponseStream = true; getCmd.BuildRequestDelegate = (uri, builder, serverTimeout, ctx) => BlobHttpWebRequestFactory.GetPageRanges(uri, serverTimeout, this.SnapshotTime, offset, length, accessCondition, ctx); getCmd.SetHeaders = (r, ctx) => BlobHttpWebRequestFactory.AddMetadata(r, this.Metadata); getCmd.SignRequest = this.ServiceClient.AuthenticationHandler.SignRequest; getCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex, ctx); getCmd.PostProcessResponse = (cmd, resp, ex, ctx) => { CloudBlobSharedImpl.ParseSizeAndLastModified(this.attributes, resp); GetPageRangesResponse getPageRangesResponse = new GetPageRangesResponse(cmd.ResponseStream); IEnumerable<PageRange> pageRanges = new List<PageRange>(getPageRangesResponse.PageRanges); return pageRanges; }; return getCmd; }
/// <summary> /// Implementation for the FetchAttributes method. /// </summary> /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the access conditions for the container. If <c>null</c>, no condition is used.</param> /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies additional options for the request.</param> /// <returns>A <see cref="RESTCommand"/> that fetches the attributes.</returns> private RESTCommand<NullType> FetchAttributesImpl(AccessCondition accessCondition, BlobRequestOptions options) { RESTCommand<NullType> getCmd = new RESTCommand<NullType>(this.ServiceClient.Credentials, this.StorageUri); options.ApplyToStorageCommand(getCmd); getCmd.CommandLocationMode = CommandLocationMode.PrimaryOrSecondary; getCmd.Handler = this.ServiceClient.AuthenticationHandler; getCmd.BuildClient = HttpClientFactory.BuildHttpClient; getCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => ContainerHttpRequestMessageFactory.GetProperties(uri, serverTimeout, accessCondition, cnt, ctx); getCmd.PreProcessResponse = (cmd, resp, ex, ctx) => { HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, NullType.Value, cmd, ex); this.Properties = ContainerHttpResponseParsers.GetProperties(resp); this.Metadata = ContainerHttpResponseParsers.GetMetadata(resp); return NullType.Value; }; return getCmd; }
/// <summary> /// Implementation method for the ClearPage methods. /// </summary> /// <param name="startOffset">The start offset. Must be multiples of 512.</param> /// <param name="length">Length of the data range to be cleared. Must be multiples of 512.</param> /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the access conditions for the blob. If <c>null</c>, no condition is used.</param> /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies any additional options for the request.</param> /// <returns>A <see cref="RESTCommand{T}"/> that writes the pages.</returns> private RESTCommand<NullType> ClearPageImpl(long startOffset, long length, AccessCondition accessCondition, BlobRequestOptions options) { CommonUtils.AssertNotNull("options", options); if (startOffset < 0 || startOffset % Constants.PageSize != 0) { CommonUtils.ArgumentOutOfRange("startOffset", startOffset); } if (length <= 0 || length % Constants.PageSize != 0) { CommonUtils.ArgumentOutOfRange("length", length); } PageRange pageRange = new PageRange(startOffset, startOffset + length - 1); PageWrite pageWrite = PageWrite.Clear; RESTCommand<NullType> putCmd = new RESTCommand<NullType>(this.ServiceClient.Credentials, this.Uri); putCmd.ApplyRequestOptions(options); putCmd.BuildRequestDelegate = (uri, builder, serverTimeout, ctx) => BlobHttpWebRequestFactory.PutPage(uri, serverTimeout, pageRange, pageWrite, accessCondition, ctx); putCmd.SignRequest = this.ServiceClient.AuthenticationHandler.SignRequest; putCmd.PreProcessResponse = (cmd, resp, ex, ctx) => { HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.Created, resp, NullType.Value, cmd, ex, ctx); CloudBlobSharedImpl.ParseSizeAndLastModified(this.attributes, resp); return NullType.Value; }; return putCmd; }
/// <summary> /// Implementation for the Exists method. /// </summary> /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies additional options for the request.</param> /// <param name="primaryOnly">If <c>true</c>, the command will be executed against the primary location.</param> /// <returns>A <see cref="RESTCommand"/> that checks existence.</returns> private RESTCommand<bool> ExistsImpl(BlobRequestOptions options, bool primaryOnly) { RESTCommand<bool> getCmd = new RESTCommand<bool>(this.ServiceClient.Credentials, this.StorageUri); options.ApplyToStorageCommand(getCmd); getCmd.CommandLocationMode = primaryOnly ? CommandLocationMode.PrimaryOnly : CommandLocationMode.PrimaryOrSecondary; getCmd.Handler = this.ServiceClient.AuthenticationHandler; getCmd.BuildClient = HttpClientFactory.BuildHttpClient; getCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => ContainerHttpRequestMessageFactory.GetProperties(uri, serverTimeout, null /* accessCondition */, cnt, ctx); getCmd.PreProcessResponse = (cmd, resp, ex, ctx) => { if (resp.StatusCode == HttpStatusCode.NotFound) { return false; } HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, true, cmd, ex); this.Properties = ContainerHttpResponseParsers.GetProperties(resp); this.Metadata = ContainerHttpResponseParsers.GetMetadata(resp); return true; }; return getCmd; }
/// <summary> /// Implements the FetchAttributes method. The attributes are updated immediately. /// </summary> /// <param name="blobUri">The URI of the blob.</param> /// <param name="accessCondition">An object that represents the access conditions for the blob. If <c>null</c>, no condition is used.</param> /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies any additional options for the request.</param> /// <returns>A <see cref="RESTCommand{T}"/> that fetches the attributes.</returns> private RESTCommand<ICloudBlob> GetBlobReferenceImpl(Uri blobUri, AccessCondition accessCondition, BlobRequestOptions options) { // If the blob Uri contains SAS credentials, we need to use those // credentials instead of this service client's stored credentials. StorageCredentials parsedCredentials; DateTimeOffset? parsedSnapshot; blobUri = NavigationHelper.ParseBlobQueryAndVerify(blobUri, out parsedCredentials, out parsedSnapshot); CloudBlobClient client = parsedCredentials != null ? new CloudBlobClient(this.BaseUri, parsedCredentials) : this; RESTCommand<ICloudBlob> getCmd = new RESTCommand<ICloudBlob>(client.Credentials, blobUri); getCmd.ApplyRequestOptions(options); getCmd.BuildRequestDelegate = (uri, builder, serverTimeout, ctx) => BlobHttpWebRequestFactory.GetProperties(uri, serverTimeout, null /* snapshot */, accessCondition, ctx); getCmd.SignRequest = client.AuthenticationHandler.SignRequest; getCmd.PreProcessResponse = (cmd, resp, ex, ctx) => { HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex, ctx); BlobAttributes attributes = new BlobAttributes() { Uri = blobUri, SnapshotTime = parsedSnapshot, }; CloudBlobSharedImpl.UpdateAfterFetchAttributes(attributes, resp, false); switch (attributes.Properties.BlobType) { case BlobType.BlockBlob: return new CloudBlockBlob(attributes, client); case BlobType.PageBlob: return new CloudPageBlob(attributes, client); default: throw new InvalidOperationException(); } }; return getCmd; }
/// <summary> /// Implementation for the SetMetadata method. /// </summary> /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the access conditions for the container. If <c>null</c>, no condition is used.</param> /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies additional options for the request.</param> /// <returns>A <see cref="RESTCommand"/> that sets the metadata.</returns> private RESTCommand<NullType> SetMetadataImpl(AccessCondition accessCondition, BlobRequestOptions options) { RESTCommand<NullType> putCmd = new RESTCommand<NullType>(this.ServiceClient.Credentials, this.StorageUri); options.ApplyToStorageCommand(putCmd); putCmd.Handler = this.ServiceClient.AuthenticationHandler; putCmd.BuildClient = HttpClientFactory.BuildHttpClient; putCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => { HttpRequestMessage msg = ContainerHttpRequestMessageFactory.SetMetadata(uri, serverTimeout, accessCondition, cnt, ctx); ContainerHttpRequestMessageFactory.AddMetadata(msg, this.Metadata); return msg; }; putCmd.PreProcessResponse = (cmd, resp, ex, ctx) => { HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, NullType.Value, cmd, ex); this.UpdateETagAndLastModified(resp); return NullType.Value; }; return putCmd; }
private RESTCommand<NullType> SetServicePropertiesImpl(ServiceProperties properties, BlobRequestOptions requestOptions) { MemoryStream str = new MemoryStream(); try { properties.WriteServiceProperties(str); } catch (InvalidOperationException invalidOpException) { throw new ArgumentException(invalidOpException.Message, "properties"); } str.Seek(0, SeekOrigin.Begin); RESTCommand<NullType> retCmd = new RESTCommand<NullType>(this.Credentials, this.BaseUri); retCmd.SendStream = str; retCmd.BuildRequestDelegate = BlobHttpWebRequestFactory.SetServiceProperties; retCmd.RecoveryAction = RecoveryActions.RewindStream; retCmd.SignRequest = this.AuthenticationHandler.SignRequest; retCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(System.Net.HttpStatusCode.Accepted, resp, NullType.Value, cmd, ex, ctx); retCmd.ApplyRequestOptions(requestOptions); return retCmd; }
/// <summary> /// Implementation for the SetPermissions method. /// </summary> /// <param name="acl">The permissions to set.</param> /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the access conditions for the container. If <c>null</c>, no condition is used.</param> /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies additional options for the request.</param> /// <returns>A <see cref="RESTCommand"/> that sets the permissions.</returns> private RESTCommand<NullType> SetPermissionsImpl(BlobContainerPermissions acl, AccessCondition accessCondition, BlobRequestOptions options) { MultiBufferMemoryStream memoryStream = new MultiBufferMemoryStream(null /* bufferManager */, (int)(1 * Constants.KB)); BlobRequest.WriteSharedAccessIdentifiers(acl.SharedAccessPolicies, memoryStream); RESTCommand<NullType> putCmd = new RESTCommand<NullType>(this.ServiceClient.Credentials, this.StorageUri); options.ApplyToStorageCommand(putCmd); putCmd.Handler = this.ServiceClient.AuthenticationHandler; putCmd.BuildClient = HttpClientFactory.BuildHttpClient; putCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => ContainerHttpRequestMessageFactory.SetAcl(uri, serverTimeout, acl.PublicAccess, accessCondition, cnt, ctx); putCmd.BuildContent = (cmd, ctx) => HttpContentFactory.BuildContentFromStream(memoryStream, 0, memoryStream.Length, null /* md5 */, cmd, ctx); putCmd.PreProcessResponse = (cmd, resp, ex, ctx) => { HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, NullType.Value, cmd, ex); this.UpdateETagAndLastModified(resp); return NullType.Value; }; return putCmd; }
private RESTCommand<ServiceStats> GetServiceStatsImpl(TableRequestOptions requestOptions) { RESTCommand<ServiceStats> retCmd = new RESTCommand<ServiceStats>(this.Credentials, this.StorageUri); requestOptions.ApplyToStorageCommand(retCmd); retCmd.CommandLocationMode = CommandLocationMode.PrimaryOrSecondary; retCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => TableHttpRequestMessageFactory.GetServiceStats(uri, serverTimeout, ctx); retCmd.RetrieveResponseStream = true; retCmd.Handler = this.AuthenticationHandler; retCmd.BuildClient = HttpClientFactory.BuildHttpClient; retCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex); retCmd.PostProcessResponse = (cmd, resp, ctx) => Task.Factory.StartNew(() => HttpResponseParsers.ReadServiceStats(cmd.ResponseStream)); return retCmd; }
/// <summary> /// Implementation for the GetPermissions method. /// </summary> /// <param name="accessCondition">An <see cref="AccessCondition"/> object that represents the access conditions for the container. If <c>null</c>, no condition is used.</param> /// <param name="options">A <see cref="BlobRequestOptions"/> object that specifies additional options for the request.</param> /// <returns>A <see cref="RESTCommand"/> that gets the permissions.</returns> private RESTCommand<BlobContainerPermissions> GetPermissionsImpl(AccessCondition accessCondition, BlobRequestOptions options) { BlobContainerPermissions containerAcl = null; RESTCommand<BlobContainerPermissions> getCmd = new RESTCommand<BlobContainerPermissions>(this.ServiceClient.Credentials, this.StorageUri); options.ApplyToStorageCommand(getCmd); getCmd.CommandLocationMode = CommandLocationMode.PrimaryOrSecondary; getCmd.RetrieveResponseStream = true; getCmd.Handler = this.ServiceClient.AuthenticationHandler; getCmd.BuildClient = HttpClientFactory.BuildHttpClient; getCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => ContainerHttpRequestMessageFactory.GetAcl(uri, serverTimeout, accessCondition, cnt, ctx); getCmd.PreProcessResponse = (cmd, resp, ex, ctx) => { HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex); containerAcl = new BlobContainerPermissions() { PublicAccess = ContainerHttpResponseParsers.GetAcl(resp), }; return containerAcl; }; getCmd.PostProcessResponse = (cmd, resp, ctx) => { this.UpdateETagAndLastModified(resp); return Task.Factory.StartNew(() => { ContainerHttpResponseParsers.ReadSharedAccessIdentifiers(cmd.ResponseStream, containerAcl); return containerAcl; }); }; return getCmd; }