Exemplo n.º 1
0
        /// <summary>
        /// For mocking a TransportClient response/
        /// </summary>
        /// <param name="request">The <see cref="DocumentServiceRequest"/> instance.</param>
        /// <returns>A <see cref="StoreResponse"/> instance.</returns>
        public static StoreResponse GetStoreResponse(DocumentServiceRequest request)
        {
            DictionaryNameValueCollection headers = new DictionaryNameValueCollection();

            if (request.OperationType == OperationType.Read)
            {
                headers.Add(WFConstants.BackendHeaders.LSN, "1");
                if (request.ResourceAddress.EndsWith(Constants.ValidOperationId))
                {
                    return(new StoreResponse()
                    {
                        ResponseBody = new MemoryStream(MockRequestHelper.testPayload),
                        Status = (int)System.Net.HttpStatusCode.OK,
                        Headers = headers,
                    });
                }

                return(new StoreResponse()
                {
                    ResponseBody = Stream.Null,
                    Status = (int)System.Net.HttpStatusCode.NotFound,
                    Headers = headers,
                });
            }

            if (request.OperationType == OperationType.Delete)
            {
                if (request.ResourceAddress.EndsWith(Constants.ValidOperationId))
                {
                    return(new StoreResponse()
                    {
                        ResponseBody = new MemoryStream(MockRequestHelper.testPayload),
                        Status = (int)System.Net.HttpStatusCode.OK,
                        Headers = headers,
                    });
                }

                return(new StoreResponse()
                {
                    ResponseBody = Stream.Null,
                    Status = (int)System.Net.HttpStatusCode.NotFound,
                    Headers = headers,
                });
            }

            if (request.OperationType == OperationType.Create ||
                request.OperationType == OperationType.Replace ||
                request.OperationType == OperationType.Upsert ||
                request.OperationType == OperationType.Patch)
            {
                return(new StoreResponse()
                {
                    ResponseBody = new MemoryStream(MockRequestHelper.testPayload),
                    Status = (int)System.Net.HttpStatusCode.OK,
                    Headers = headers,
                });
            }

            return(null);
        }
Exemplo n.º 2
0
        public static StoreResponse ReturnThrottledStoreResponseOnItemOperation(
            Uri physicalAddress,
            ResourceOperation resourceOperation,
            DocumentServiceRequest request,
            Guid activityId,
            string errorMessage)
        {
            if (request.ResourceType == ResourceType.Document)
            {
                DictionaryNameValueCollection headers = new DictionaryNameValueCollection();
                headers.Add(HttpConstants.HttpHeaders.ActivityId, activityId.ToString());
                headers.Add(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.WriteForbidden).ToString(CultureInfo.InvariantCulture));
                headers.Add(HttpConstants.HttpHeaders.RetryAfterInMilliseconds, TimeSpan.FromMilliseconds(100).TotalMilliseconds.ToString(CultureInfo.InvariantCulture));
                headers.Add(HttpConstants.HttpHeaders.RequestCharge, ((double)9001).ToString(CultureInfo.InvariantCulture));

                StoreResponse storeResponse = new StoreResponse()
                {
                    Status       = 429,
                    Headers      = headers,
                    ResponseBody = new MemoryStream(Encoding.UTF8.GetBytes(errorMessage))
                };

                return(storeResponse);
            }

            return(null);
        }
        private async Task GatewayStoreModel_Exception_UpdateSessionTokenOnKnownException(Exception ex)
        {
            const string originalSessionToken = "0:1#100#1=20#2=5#3=30";
            const string updatedSessionToken  = "0:1#100#1=20#2=5#3=31";

            Func <HttpRequestMessage, Task <HttpResponseMessage> > sendFunc = request =>
            {
                throw ex;
            };

            Mock <IDocumentClientInternal> mockDocumentClient = new Mock <IDocumentClientInternal>();

            mockDocumentClient.Setup(client => client.ServiceEndpoint).Returns(new Uri("https://foo"));

            GlobalEndpointManager     endpointManager  = new GlobalEndpointManager(mockDocumentClient.Object, new ConnectionPolicy());
            SessionContainer          sessionContainer = new SessionContainer(string.Empty);
            DocumentClientEventSource eventSource      = DocumentClientEventSource.Instance;
            HttpMessageHandler        messageHandler   = new MockMessageHandler(sendFunc);
            GatewayStoreModel         storeModel       = new GatewayStoreModel(
                endpointManager,
                sessionContainer,
                TimeSpan.FromSeconds(5),
                ConsistencyLevel.Eventual,
                eventSource,
                null,
                new UserAgentContainer(),
                ApiType.None,
                messageHandler);

            INameValueCollection headers = new DictionaryNameValueCollection();

            headers.Set(HttpConstants.HttpHeaders.ConsistencyLevel, ConsistencyLevel.Session.ToString());
            headers.Set(HttpConstants.HttpHeaders.SessionToken, originalSessionToken);
            headers.Set(WFConstants.BackendHeaders.PartitionKeyRangeId, "0");

            using (new ActivityScope(Guid.NewGuid()))
            {
                using (DocumentServiceRequest request = DocumentServiceRequest.Create(
                           OperationType.Read,
                           ResourceType.Document,
                           "dbs/OVJwAA==/colls/OVJwAOcMtA0=/docs/OVJwAOcMtA0BAAAAAAAAAA==/",
                           AuthorizationTokenType.PrimaryMasterKey,
                           headers))
                {
                    request.UseStatusCodeFor429      = true;
                    request.UseStatusCodeForFailures = true;
                    try
                    {
                        DocumentServiceResponse response = await storeModel.ProcessMessageAsync(request);

                        Assert.Fail("Should had thrown exception");
                    }
                    catch (Exception)
                    {
                        // Expecting exception
                    }
                    Assert.AreEqual(updatedSessionToken, sessionContainer.GetSessionToken("dbs/OVJwAA==/colls/OVJwAOcMtA0="));
                }
            }
        }
Exemplo n.º 4
0
        public async Task AddPartitionKeyRangeToContinuationTokenOnNotNullBackendContinuation()
        {
            ResolvedRangeInfo currentPartitionKeyRange = new ResolvedRangeInfo(new PartitionKeyRange {
                Id = "1", MinInclusive = "B", MaxExclusive = "C"
            }, null);
            Mock <IRoutingMapProvider> routingMapProvider = new Mock <IRoutingMapProvider>();

            routingMapProvider.Setup(m => m.TryGetOverlappingRangesAsync(
                                         It.IsAny <string>(),
                                         It.IsAny <Range <string> >(),
                                         It.IsAny <bool>()
                                         )).Returns(Task.FromResult <IReadOnlyList <PartitionKeyRange> >(null)).Verifiable();

            PartitionRoutingHelper        partitionRoutingHelper = new PartitionRoutingHelper();
            DictionaryNameValueCollection headers = new DictionaryNameValueCollection();

            headers.Add(HttpConstants.HttpHeaders.Continuation, "something");
            bool result = await partitionRoutingHelper.TryAddPartitionKeyRangeToContinuationTokenAsync(
                headers,
                null,
                routingMapProvider.Object,
                CollectionId,
                currentPartitionKeyRange,
                RntdbEnumerationDirection.Reverse
                );

            Assert.IsTrue(true);
            routingMapProvider.Verify(m => m.TryGetOverlappingRangesAsync(
                                          It.IsAny <string>(),
                                          It.IsAny <Range <string> >(),
                                          It.IsAny <bool>()
                                          ), Times.Never);
        }
Exemplo n.º 5
0
        private async Task <AccountProperties> GetDatabaseAccountAsync(Uri serviceEndpoint)
        {
            INameValueCollection headers = new DictionaryNameValueCollection(StringComparer.Ordinal);
            string authorizationToken    = string.Empty;

            if (this.hasAuthKeyResourceToken)
            {
                authorizationToken = HttpUtility.UrlEncode(this.authKeyResourceToken);
            }
            else
            {
                // Retrieve the document service properties.
                string xDate = DateTime.UtcNow.ToString("r", CultureInfo.InvariantCulture);
                headers.Set(HttpConstants.HttpHeaders.XDate, xDate);

                authorizationToken = AuthorizationHelper.GenerateKeyAuthorizationSignature(
                    HttpConstants.HttpMethods.Get,
                    serviceEndpoint,
                    headers,
                    this.authKeyHashFunction);
            }

            headers.Set(HttpConstants.HttpHeaders.Authorization, authorizationToken);
            using (HttpResponseMessage responseMessage = await this.httpClient.GetAsync(serviceEndpoint, headers))
            {
                using (DocumentServiceResponse documentServiceResponse = await ClientExtensions.ParseResponseAsync(responseMessage))
                {
                    return(CosmosResource.FromStream <AccountProperties>(documentServiceResponse));
                }
            }
        }
        private void ValidateEmitVerboseTracesInQuery(DocumentClient client, bool isHttps = false)
        {
            // Value not boolean
            INameValueCollection headers = new DictionaryNameValueCollection();

            headers.Add(HttpConstants.HttpHeaders.EmitVerboseTracesInQuery, "Not a boolean");

            try
            {
                var response = ReadDatabaseFeedRequest(client, headers);
                if (isHttps)
                {
                    Assert.Fail("Should throw an exception");
                }
                else
                {
                    // Invalid boolean is treated as false by TCP
                    Assert.IsTrue(response.StatusCode == HttpStatusCode.OK, "Invalid status code");
                }
            }
            catch (Exception ex)
            {
                var innerException = ex.InnerException as DocumentClientException;
                Assert.IsTrue(innerException.StatusCode == HttpStatusCode.BadRequest, "Invalid status code");
            }

            // Valid boolean
            headers = new DictionaryNameValueCollection();
            headers.Add(HttpConstants.HttpHeaders.EmitVerboseTracesInQuery, "true");
            var response2 = ReadDatabaseFeedRequest(client, headers);

            Assert.IsTrue(response2.StatusCode == HttpStatusCode.OK, "Invalid status code");
        }
        private void ValidateIfNonMatch(DocumentClient client)
        {
            // Valid if-match
            var document = CreateDocumentRequest(client, new DictionaryNameValueCollection()).GetResource <Document>();
            var headers  = new DictionaryNameValueCollection();

            headers.Add(HttpConstants.HttpHeaders.IfNoneMatch, document.ETag);
            var response = ReadDocumentRequest(client, document, headers);

            Assert.IsTrue(response.StatusCode == HttpStatusCode.NotModified, "Invalid status code");

            // validateInvalidIfMatch
            AccessCondition condition = new AccessCondition()
            {
                Type = AccessConditionType.IfMatch, Condition = "invalid etag"
            };

            try
            {
                var replacedDoc = client.ReplaceDocumentAsync(document.SelfLink, document, new RequestOptions()
                {
                    AccessCondition = condition
                }).Result.Resource;
                Assert.Fail("should not reach here");
            }
            catch (Exception ex)
            {
                var innerException = ex.InnerException as DocumentClientException;
                Assert.IsTrue(innerException.StatusCode == HttpStatusCode.PreconditionFailed, "Invalid status code");
            }
        }
Exemplo n.º 8
0
        private async Task <AccountProperties> GetDatabaseAccountAsync(Uri serviceEndpoint)
        {
            INameValueCollection headers = new DictionaryNameValueCollection(StringComparer.Ordinal);
            string authorizationToken    = string.Empty;

            if (this.hasAuthKeyResourceToken)
            {
                authorizationToken = HttpUtility.UrlEncode(this.authKeyResourceToken);
            }
            else
            {
                // Retrieve the document service properties.
                string xDate = DateTime.UtcNow.ToString("r", CultureInfo.InvariantCulture);
                headers.Set(HttpConstants.HttpHeaders.XDate, xDate);

                authorizationToken = AuthorizationHelper.GenerateKeyAuthorizationSignature(
                    HttpConstants.HttpMethods.Get,
                    serviceEndpoint,
                    headers,
                    this.authKeyHashFunction);
            }

            headers.Set(HttpConstants.HttpHeaders.Authorization, authorizationToken);
            using (HttpResponseMessage responseMessage = await this.httpClient.GetAsync(
                       uri: serviceEndpoint,
                       additionalHeaders: headers,
                       resourceType: ResourceType.DatabaseAccount,
                       diagnosticsContext: null,
                       cancellationToken: default))
        // Verify that for 429 exceptions, session token is not updated
        public async Task GatewayStoreModel_Exception_NotUpdateSessionTokenOnKnownExceptions()
        {
            INameValueCollection headers = new DictionaryNameValueCollection();

            headers.Set(HttpConstants.HttpHeaders.SessionToken, "0:1#100#1=20#2=5#3=30");
            headers.Set(WFConstants.BackendHeaders.LocalLSN, "10");
            await this.GatewayStoreModel_Exception_NotUpdateSessionTokenOnKnownException(new RequestRateTooLargeException("429", headers, new Uri("http://one.com")));
        }
Exemplo n.º 10
0
        private async Task <FeedResource <Address> > GetMasterAddressesViaGatewayAsync(
            DocumentServiceRequest request,
            ResourceType resourceType,
            string resourceAddress,
            string entryUrl,
            bool forceRefresh,
            bool useMasterCollectionResolver)
        {
            INameValueCollection addressQuery = new DictionaryNameValueCollection(StringComparer.Ordinal);

            addressQuery.Add(HttpConstants.QueryStrings.Url, HttpUtility.UrlEncode(entryUrl));

            INameValueCollection headers = new DictionaryNameValueCollection(StringComparer.Ordinal);

            if (forceRefresh)
            {
                headers.Set(HttpConstants.HttpHeaders.ForceRefresh, bool.TrueString);
            }

            if (useMasterCollectionResolver)
            {
                headers.Set(HttpConstants.HttpHeaders.UseMasterCollectionResolver, bool.TrueString);
            }

            if (request.ForceCollectionRoutingMapRefresh)
            {
                headers.Set(HttpConstants.HttpHeaders.ForceCollectionRoutingMapRefresh, bool.TrueString);
            }

            addressQuery.Add(HttpConstants.QueryStrings.Filter, this.protocolFilter);

            string resourceTypeToSign = PathsHelper.GetResourcePath(resourceType);

            headers.Set(HttpConstants.HttpHeaders.XDate, DateTime.UtcNow.ToString("r", CultureInfo.InvariantCulture));
            string token = this.tokenProvider.GetUserAuthorizationToken(
                resourceAddress,
                resourceTypeToSign,
                HttpConstants.HttpMethods.Get,
                headers,
                AuthorizationTokenType.PrimaryMasterKey,
                payload: out _);

            headers.Set(HttpConstants.HttpHeaders.Authorization, token);

            Uri targetEndpoint = UrlUtility.SetQuery(this.addressEndpoint, UrlUtility.CreateQuery(addressQuery));

            string identifier = GatewayAddressCache.LogAddressResolutionStart(request, targetEndpoint);

            using (HttpResponseMessage httpResponseMessage = await this.httpClient.GetAsync(targetEndpoint, headers))
            {
                using (DocumentServiceResponse documentServiceResponse =
                           await ClientExtensions.ParseResponseAsync(httpResponseMessage))
                {
                    GatewayAddressCache.LogAddressResolutionEnd(request, identifier);
                    return(documentServiceResponse.GetResource <FeedResource <Address> >());
                }
            }
        }
Exemplo n.º 11
0
        private async Task <DocumentServiceResponse> GetFeedResponseAsync(string resourceLink, ResourceType resourceType, IDocumentClientRetryPolicy retryPolicyInstance, CancellationToken cancellationToken)
        {
            INameValueCollection headers = new DictionaryNameValueCollection();

            if (this.feedOptions.MaxItemCount.HasValue)
            {
                headers.Set(HttpConstants.HttpHeaders.PageSize, this.feedOptions.MaxItemCount.ToString());
            }

            if (this.feedOptions.SessionToken != null)
            {
                headers.Set(HttpConstants.HttpHeaders.SessionToken, this.feedOptions.SessionToken);
            }

            if (resourceType.IsPartitioned() && this.feedOptions.PartitionKeyRangeId == null && this.feedOptions.PartitionKey == null)
            {
                throw new ForbiddenException(RMResources.PartitionKeyRangeIdOrPartitionKeyMustBeSpecified);
            }

            // On REST level, change feed is using IfNoneMatch/ETag instead of continuation.
            if (this.nextIfNoneMatch != null)
            {
                headers.Set(HttpConstants.HttpHeaders.IfNoneMatch, this.nextIfNoneMatch);
            }

            if (this.ifModifiedSince != null)
            {
                headers.Set(HttpConstants.HttpHeaders.IfModifiedSince, this.ifModifiedSince);
            }

            headers.Set(HttpConstants.HttpHeaders.A_IM, HttpConstants.A_IMHeaderValues.IncrementalFeed);

            if (this.feedOptions.PartitionKey != null)
            {
                PartitionKeyInternal partitionKey = this.feedOptions.PartitionKey.InternalKey;
                headers.Set(HttpConstants.HttpHeaders.PartitionKey, partitionKey.ToJsonString());
            }

            if (this.feedOptions.IncludeTentativeWrites)
            {
                headers.Set(HttpConstants.HttpHeaders.IncludeTentativeWrites, bool.TrueString);
            }

            using (DocumentServiceRequest request = this.client.CreateDocumentServiceRequest(
                       OperationType.ReadFeed,
                       resourceLink,
                       resourceType,
                       headers))
            {
                if (resourceType.IsPartitioned() && this.feedOptions.PartitionKeyRangeId != null)
                {
                    request.RouteTo(new PartitionKeyRangeIdentity(this.feedOptions.PartitionKeyRangeId));
                }

                return(await this.client.ReadFeedAsync(request, retryPolicyInstance, cancellationToken));
            }
        }
        public async Task ValidateRetryOnWriteForbiddenExceptionAsync()
        {
            this.Initialize(
                useMultipleWriteLocations: false,
                enableEndpointDiscovery: true,
                isPreferredLocationsListEmpty: false);

            await this.endpointManager.RefreshLocationAsync(this.databaseAccount);

            ClientRetryPolicy retryPolicy = new ClientRetryPolicy(this.endpointManager, true, new RetryOptions());

            using (DocumentServiceRequest request = this.CreateRequest(isReadRequest: false, isMasterResourceType: false))
            {
                int retryCount = 0;

                await BackoffRetryUtility <bool> .ExecuteAsync(
                    () =>
                {
                    retryCount++;
                    retryPolicy.OnBeforeSendRequest(request);

                    if (retryCount == 1)
                    {
                        this.mockedClient.ResetCalls();

                        Uri expectedEndpoint = LocationCacheTests.EndpointByLocation[this.preferredLocations[0]];

                        Assert.AreEqual(expectedEndpoint, request.RequestContext.LocationEndpointToRoute);

                        DictionaryNameValueCollection headers         = new DictionaryNameValueCollection();
                        headers[WFConstants.BackendHeaders.SubStatus] = ((int)SubStatusCodes.WriteForbidden).ToString();
                        DocumentClientException forbiddenException    = new ForbiddenException(RMResources.Forbidden, headers);

                        throw forbiddenException;
                    }
                    else if (retryCount == 2)
                    {
                        this.mockedClient.Verify(client => client.GetDatabaseAccountInternalAsync(It.IsAny <Uri>(), It.IsAny <CancellationToken>()), Times.Once);

                        // Next request must go to next preferred endpoint
                        Uri expectedEndpoint = LocationCacheTests.EndpointByLocation[this.preferredLocations[1]];
                        Assert.AreEqual(expectedEndpoint, request.RequestContext.LocationEndpointToRoute);

                        return(Task.FromResult(true));
                    }
                    else
                    {
                        Assert.Fail();
                    }

                    return(Task.FromResult(true));
                },
                    retryPolicy);
            }
        }
        // Verify that for known exceptions, session token is updated
        public async Task GatewayStoreModel_Exception_UpdateSessionTokenOnKnownException()
        {
            INameValueCollection headers = new DictionaryNameValueCollection();

            headers.Set(HttpConstants.HttpHeaders.SessionToken, "0:1#100#1=20#2=5#3=31");
            headers.Set(WFConstants.BackendHeaders.LocalLSN, "10");
            await this.GatewayStoreModel_Exception_UpdateSessionTokenOnKnownException(new ConflictException("test", headers, new Uri("http://one.com")));

            await this.GatewayStoreModel_Exception_UpdateSessionTokenOnKnownException(new NotFoundException("test", headers, new Uri("http://one.com")));

            await this.GatewayStoreModel_Exception_UpdateSessionTokenOnKnownException(new PreconditionFailedException("test", headers, new Uri("http://one.com")));
        }
        private static DictionaryNameValueCollection GenerateTestHeaders()
        {
            DictionaryNameValueCollection headers = new DictionaryNameValueCollection();

            for (int i = 0; i < 15; i++)
            {
                string random = Guid.NewGuid().ToString();
                headers[random] = random;
            }

            return(headers);
        }
        private async Task GatewayStoreModel_Exceptionless_NotUpdateSessionTokenOnKnownResponses(ResourceType resourceType, HttpStatusCode httpStatusCode, SubStatusCodes subStatusCode = SubStatusCodes.Unknown)
        {
            const string originalSessionToken = "0:1#100#1=20#2=5#3=30";
            const string updatedSessionToken  = "0:1#100#1=20#2=5#3=31";

            Func <HttpRequestMessage, Task <HttpResponseMessage> > sendFunc = request =>
            {
                HttpResponseMessage response = new HttpResponseMessage(httpStatusCode);
                response.Headers.Add(HttpConstants.HttpHeaders.SessionToken, updatedSessionToken);
                response.Headers.Add(WFConstants.BackendHeaders.SubStatus, subStatusCode.ToString());
                return(Task.FromResult(response));
            };

            Mock <IDocumentClientInternal> mockDocumentClient = new Mock <IDocumentClientInternal>();

            mockDocumentClient.Setup(client => client.ServiceEndpoint).Returns(new Uri("https://foo"));

            GlobalEndpointManager     endpointManager  = new GlobalEndpointManager(mockDocumentClient.Object, new ConnectionPolicy());
            SessionContainer          sessionContainer = new SessionContainer(string.Empty);
            DocumentClientEventSource eventSource      = DocumentClientEventSource.Instance;
            HttpMessageHandler        messageHandler   = new MockMessageHandler(sendFunc);
            GatewayStoreModel         storeModel       = new GatewayStoreModel(
                endpointManager,
                sessionContainer,
                ConsistencyLevel.Eventual,
                eventSource,
                null,
                new HttpClient(messageHandler));

            INameValueCollection headers = new DictionaryNameValueCollection();

            headers.Set(HttpConstants.HttpHeaders.ConsistencyLevel, ConsistencyLevel.Session.ToString());
            headers.Set(HttpConstants.HttpHeaders.SessionToken, originalSessionToken);
            headers.Set(WFConstants.BackendHeaders.PartitionKeyRangeId, "0");

            using (new ActivityScope(Guid.NewGuid()))
            {
                using (DocumentServiceRequest request = DocumentServiceRequest.Create(
                           OperationType.Read,
                           resourceType,
                           "dbs/OVJwAA==/colls/OVJwAOcMtA0=/docs/OVJwAOcMtA0BAAAAAAAAAA==/",
                           AuthorizationTokenType.PrimaryMasterKey,
                           headers))
                {
                    request.UseStatusCodeFor429      = true;
                    request.UseStatusCodeForFailures = true;
                    DocumentServiceResponse response = await storeModel.ProcessMessageAsync(request);

                    Assert.AreEqual(string.Empty, sessionContainer.GetSessionToken("dbs/OVJwAA==/colls/OVJwAOcMtA0="));
                }
            }
        }
Exemplo n.º 16
0
 public void DictionaryPointRead()
 {
     _ = new DictionaryNameValueCollection()
     {
         { HttpConstants.HttpHeaders.Authorization, AuthValue },
         { HttpConstants.HttpHeaders.XDate, Date },
         { HttpConstants.HttpHeaders.ClientRetryAttemptCount, Retry },
         { HttpConstants.HttpHeaders.PartitionKey, Partitionkey },
         { HttpConstants.HttpHeaders.RemainingTimeInMsOnClientRequest, Remaining },
         { HttpConstants.HttpHeaders.TransportRequestID, Transport },
         { WFConstants.BackendHeaders.CollectionRid, Rid }
     };
 }
Exemplo n.º 17
0
        public INameValueCollection Clone()
        {
            INameValueCollection headers = new DictionaryNameValueCollection();

            foreach (KeyValuePair <string, IEnumerable <string> > headerPair in this.AllItems())
            {
                foreach (string val in headerPair.Value)
                {
                    headers.Add(headerPair.Key, val);
                }
            }

            return(headers);
        }
Exemplo n.º 18
0
        public async Task AddPartitionKeyRangeToContinuationTokenOnSplit()
        {
            const string BackendToken = "backendToken";
            DictionaryNameValueCollection     headers = new DictionaryNameValueCollection();
            List <CompositeContinuationToken> compositeContinuationTokensFromSplit = new List <CompositeContinuationToken>
            {
                new CompositeContinuationToken {
                    Token = "someToken", Range = new Range <string>("A", "B", true, false)
                },
                new CompositeContinuationToken {
                    Token = "anotherToken", Range = new Range <string>("B", "C", true, false)
                }
            };

            PartitionRoutingHelper partitionRoutingHelper = new PartitionRoutingHelper();

            //With backend header
            headers.Add(HttpConstants.HttpHeaders.Continuation, BackendToken);
            ResolvedRangeInfo resolvedRangeInfo = new ResolvedRangeInfo(new PartitionKeyRange(), new List <CompositeContinuationToken>(compositeContinuationTokensFromSplit));
            bool result = await partitionRoutingHelper.TryAddPartitionKeyRangeToContinuationTokenAsync(
                headers,
                null,
                null,
                null,
                resolvedRangeInfo,
                RntdbEnumerationDirection.Reverse);

            List <CompositeContinuationToken> compositeContinuationTokens = JsonConvert.DeserializeObject <List <CompositeContinuationToken> >(headers.Get(HttpConstants.HttpHeaders.Continuation));

            Assert.IsTrue(result);
            Assert.AreEqual(compositeContinuationTokensFromSplit.Count, compositeContinuationTokens.Count);
            Assert.AreEqual(BackendToken, compositeContinuationTokens.First().Token);
            Assert.AreNotEqual(BackendToken, compositeContinuationTokens.Last().Token);

            //Without backend header
            headers.Remove(HttpConstants.HttpHeaders.Continuation);
            resolvedRangeInfo = new ResolvedRangeInfo(new PartitionKeyRange(), new List <CompositeContinuationToken>(compositeContinuationTokensFromSplit));
            result            = await partitionRoutingHelper.TryAddPartitionKeyRangeToContinuationTokenAsync(
                headers,
                null,
                null,
                null,
                resolvedRangeInfo,
                RntdbEnumerationDirection.Reverse);

            compositeContinuationTokens = JsonConvert.DeserializeObject <List <CompositeContinuationToken> >(headers.Get(HttpConstants.HttpHeaders.Continuation));
            Assert.IsTrue(result);
            Assert.IsTrue(compositeContinuationTokens.Count == compositeContinuationTokensFromSplit.Count - 1);
            Assert.AreEqual(compositeContinuationTokensFromSplit.Last().Token, compositeContinuationTokens.First().Token);
        }
        private async Task ValidateRetryOnSessionNotAvailabeWithEndpointDiscoveryDisabled(bool isPreferredLocationsListEmpty, bool useMultipleWriteLocations, bool isReadRequest)
        {
            const bool enableEndpointDiscovery = false;

            this.Initialize(
                useMultipleWriteLocations: useMultipleWriteLocations,
                enableEndpointDiscovery: enableEndpointDiscovery,
                isPreferredLocationsListEmpty: isPreferredLocationsListEmpty);

            ClientRetryPolicy retryPolicy = new ClientRetryPolicy(this.endpointManager, enableEndpointDiscovery, new RetryOptions());

            using (DocumentServiceRequest request = this.CreateRequest(isReadRequest: isReadRequest, isMasterResourceType: false))
            {
                int retryCount = 0;

                try
                {
                    await BackoffRetryUtility <bool> .ExecuteAsync(
                        () =>
                    {
                        retryPolicy.OnBeforeSendRequest(request);

                        if (retryCount == 0)
                        {
                            Assert.AreEqual(request.RequestContext.LocationEndpointToRoute, this.endpointManager.ReadEndpoints[0]);
                        }
                        else
                        {
                            Assert.Fail();
                        }

                        retryCount++;

                        DictionaryNameValueCollection headers         = new DictionaryNameValueCollection();
                        headers[WFConstants.BackendHeaders.SubStatus] = ((int)SubStatusCodes.ReadSessionNotAvailable).ToString();
                        DocumentClientException notFoundException     = new NotFoundException(RMResources.NotFound, headers);

                        throw notFoundException;
                    },
                        retryPolicy);

                    Assert.Fail();
                }
                catch (NotFoundException)
                {
                    DefaultTrace.TraceInformation("Received expected notFoundException");
                    Assert.AreEqual(1, retryCount);
                }
            }
        }
        public void AuthorizationBaselineTests()
        {
            string key = "VGhpcyBpcyBhIHNhbXBsZSBzdHJpbmc=";

            for (int i = 0; i < this.AuthorizationBaseline.Length; i++)
            {
                string[] baseline                 = this.AuthorizationBaseline[i];
                string[] baselineResults          = this.AuthorizationBaselineResults[i];
                DictionaryNameValueCollection nvc = new DictionaryNameValueCollection();
                nvc.Add(HttpConstants.HttpHeaders.XDate, baseline[4]);
                Uri    uri           = new Uri(baseline[0]);
                string authorization = AuthorizationHelper.GenerateKeyAuthorizationSignature(
                    verb: baseline[2],
                    uri: uri,
                    headers: nvc,
                    stringHMACSHA256Helper: new StringHMACSHA256Hash(key));

                string authorization2 = AuthorizationHelper.GenerateKeyAuthorizationSignature(
                    verb: baseline[2],
                    resourceId: baseline[1],
                    resourceType: baseline[3],
                    headers: nvc,
                    new StringHMACSHA256Hash(key),
                    out string payload2);

                string authorization3 = AuthorizationHelper.GenerateKeyAuthorizationSignature(
                    verb: baseline[2],
                    resourceId: baseline[1],
                    resourceType: baseline[3],
                    headers: nvc,
                    key);

                Assert.AreEqual(authorization, baselineResults[0]);
                Assert.AreEqual(authorization2, baselineResults[0]);
                Assert.AreEqual(authorization3, baselineResults[0]);
                Assert.AreEqual(payload2.Replace("\n", "[n]"), baselineResults[1]);

                AuthorizationHelper.ParseAuthorizationToken(authorization, out ReadOnlyMemory <char> typeOutput1, out ReadOnlyMemory <char> versionoutput1, out ReadOnlyMemory <char> tokenOutput1);
                Assert.AreEqual("master", typeOutput1.ToString());
                AuthorizationHelper.ParseAuthorizationToken(authorization2, out ReadOnlyMemory <char> typeOutput2, out ReadOnlyMemory <char> versionoutput2, out ReadOnlyMemory <char> tokenOutput2);
                Assert.AreEqual("master", typeOutput2.ToString());
                AuthorizationHelper.ParseAuthorizationToken(authorization3, out ReadOnlyMemory <char> typeOutput3, out ReadOnlyMemory <char> versionoutput3, out ReadOnlyMemory <char> tokenOutput3);
                Assert.AreEqual("master", typeOutput3.ToString());

                Assert.IsTrue(AuthorizationHelper.CheckPayloadUsingKey(tokenOutput1, baseline[2], baseline[1], baseline[3], nvc, key));
                Assert.IsTrue(AuthorizationHelper.CheckPayloadUsingKey(tokenOutput2, baseline[2], baseline[1], baseline[3], nvc, key));
                Assert.IsTrue(AuthorizationHelper.CheckPayloadUsingKey(tokenOutput3, baseline[2], baseline[1], baseline[3], nvc, key));
            }
        }
Exemplo n.º 21
0
        [Ignore] /* TODO: There is a TODO in PartitionRoutingHelper.ExtractPartitionKeyRangeFromContinuationToken that it's refering to some pending deployment */
        public void TestExtractPartitionKeyRangeFromHeaders()
        {
            Func <string, INameValueCollection> getHeadersWithContinuation = (string continuationToken) =>
            {
                INameValueCollection headers = new DictionaryNameValueCollection();
                headers[HttpConstants.HttpHeaders.Continuation] = continuationToken;
                return(headers);
            };

            using (Stream stream = new MemoryStream(Properties.Resources.BaselineTest_PartitionRoutingHelper_ExtractPartitionKeyRangeFromHeaders))
            {
                using (StreamReader reader = new StreamReader(stream))
                {
                    TestSet <ExtractPartitionKeyRangeFromHeadersTestData> testSet = JsonConvert.DeserializeObject <TestSet <ExtractPartitionKeyRangeFromHeadersTestData> >(reader.ReadToEnd());

                    foreach (ExtractPartitionKeyRangeFromHeadersTestData testData in testSet.Postive)
                    {
                        INameValueCollection headers = getHeadersWithContinuation(testData.CompositeContinuationToken);
                        List <CompositeContinuationToken> suppliedTokens;
                        Range <string> range = this.partitionRoutingHelper.ExtractPartitionKeyRangeFromContinuationToken(headers, out suppliedTokens);

                        if (suppliedTokens != null)
                        {
                            Assert.AreEqual(testData.ContinuationToken, headers[HttpConstants.HttpHeaders.Continuation]);

                            Assert.AreEqual(JsonConvert.SerializeObject(testData.PartitionKeyRange), JsonConvert.SerializeObject(range));
                        }
                        else
                        {
                            Assert.IsTrue(testData.ContinuationToken == headers[HttpConstants.HttpHeaders.Continuation] || testData.ContinuationToken == null);
                        }
                    }

                    foreach (ExtractPartitionKeyRangeFromHeadersTestData testData in testSet.Negative)
                    {
                        INameValueCollection headers = getHeadersWithContinuation(testData.CompositeContinuationToken);
                        try
                        {
                            List <CompositeContinuationToken> suppliedTokens;
                            Range <string> rangeOrId = this.partitionRoutingHelper.ExtractPartitionKeyRangeFromContinuationToken(headers, out suppliedTokens);
                            Assert.Fail("Expect BadRequestException");
                        }
                        catch (BadRequestException)
                        {
                        }
                    }
                }
            }
        }
        private async Task <AccountProperties> GetDatabaseAccountAsync(Uri serviceEndpoint)
        {
            INameValueCollection headers = new DictionaryNameValueCollection(StringComparer.Ordinal);

            await this.cosmosAuthorization.AddAuthorizationHeaderAsync(
                headersCollection : headers,
                serviceEndpoint,
                HttpConstants.HttpMethods.Get,
                AuthorizationTokenType.PrimaryMasterKey);

            using (HttpResponseMessage responseMessage = await this.httpClient.GetAsync(
                       uri: serviceEndpoint,
                       additionalHeaders: headers,
                       resourceType: ResourceType.DatabaseAccount,
                       diagnosticsContext: null,
                       cancellationToken: default))
Exemplo n.º 23
0
        public static async Task <ICollection <T> > ListAllAsync <T>(this HttpClient client,
                                                                     Uri collectionUri,
                                                                     INameValueCollection headers = null) where T : Resource, new()
        {
            Collection <T> responseCollection   = new Collection <T>();
            string         responseContinuation = null;

            if (headers == null)
            {
                headers = new DictionaryNameValueCollection();
            }

            do
            {
                if (responseContinuation != null)
                {
                    headers[HttpConstants.HttpHeaders.Continuation] = responseContinuation;
                }

                HttpResponseMessage responseMessage;
                foreach (string header in headers.AllKeys())
                {
                    client.DefaultRequestHeaders.Add(header, headers[header]);
                }

                responseMessage = await client.GetAsync(collectionUri, HttpCompletionOption.ResponseHeadersRead);

                FeedResource <T> feedResource = await responseMessage.ToResourceAsync <FeedResource <T> >();

                foreach (T resource in feedResource)
                {
                    responseCollection.Add(resource);
                }

                if (responseMessage.Headers.TryGetValues(HttpConstants.HttpHeaders.Continuation,
                                                         out IEnumerable <string> continuationToken))
                {
                    responseContinuation = continuationToken.SingleOrDefault();
                }
                else
                {
                    responseContinuation = null;
                }
            } while (!string.IsNullOrEmpty(responseContinuation));

            return(responseCollection);
        }
        private void ValidateIndexingDirective(DocumentClient client)
        {
            //Will keep this as V2 OM, because we can pass invalid IndexingDirective from V3 onwarsds
            // Number out of range.
            INameValueCollection headers = new DictionaryNameValueCollection();

            headers.Add(HttpConstants.HttpHeaders.IndexingDirective, "\"Invalid Value\"");

            try
            {
                CreateDocumentRequest(client, headers);
                Assert.Fail("Should throw an exception");
            }
            catch (Exception ex)
            {
                var innerException = ex.InnerException as DocumentClientException;
                Assert.IsTrue(innerException.StatusCode == HttpStatusCode.BadRequest, "Invalid status code");
            }

            headers = new DictionaryNameValueCollection();
            headers.Add("indexAction", "\"Invalid Value\"");

            try
            {
                CreateDocumentScript(client, headers);
                Assert.Fail("Should throw an exception");
            }
            catch (Exception ex)
            {
                var innerException = ex.InnerException as DocumentClientException;
                Assert.IsTrue(innerException.StatusCode == HttpStatusCode.BadRequest, "Invalid status code");
            }

            // Valid Indexing Directive
            headers = new DictionaryNameValueCollection();
            headers.Add(HttpConstants.HttpHeaders.IndexingDirective, IndexingDirective.Exclude.ToString());
            var response = CreateDocumentRequest(client, headers);

            Assert.IsTrue(response.StatusCode == HttpStatusCode.Created);

            headers = new DictionaryNameValueCollection();
            headers.Add("indexAction", "\"exclude\"");
            var result = CreateDocumentScript(client, headers);

            Assert.IsTrue(result.StatusCode == HttpStatusCode.OK, "Invalid status code");
        }
Exemplo n.º 25
0
        public void CompositeContinuationTokenIsNotPassedToBackend()
        {
            Range <string>             expectedRange = new Range <string>("A", "B", true, false);
            string                     expectedToken = "someToken";
            CompositeContinuationToken compositeContinuationToken = new CompositeContinuationToken {
                Range = expectedRange, Token = expectedToken
            };
            string continuation = JsonConvert.SerializeObject(compositeContinuationToken);
            PartitionRoutingHelper        partitionRoutingHelper = new PartitionRoutingHelper();
            DictionaryNameValueCollection headers = new DictionaryNameValueCollection();

            headers.Add(HttpConstants.HttpHeaders.Continuation, continuation);
            Range <string> range = partitionRoutingHelper.ExtractPartitionKeyRangeFromContinuationToken(headers, out List <CompositeContinuationToken> compositeContinuationTokens);

            Assert.IsTrue(expectedRange.Equals(range));
            Assert.AreEqual(expectedToken, headers.Get(HttpConstants.HttpHeaders.Continuation)); //not a composite token
        }
Exemplo n.º 26
0
        internal static INameValueCollection ExtractResponseHeaders(HttpResponseMessage responseMessage)
        {
            // Use DictionaryNameValueCollection because some Compute scenarios have duplicate headers
            INameValueCollection headers = new DictionaryNameValueCollection();

            foreach (KeyValuePair <string, IEnumerable <string> > headerPair in responseMessage.Headers)
            {
                if (string.Compare(headerPair.Key, HttpConstants.HttpHeaders.OwnerFullName, StringComparison.Ordinal) == 0)
                {
                    foreach (string val in headerPair.Value)
                    {
                        headers.Add(headerPair.Key, Uri.UnescapeDataString(val));
                    }
                }
                else
                {
                    foreach (string val in headerPair.Value)
                    {
                        headers.Add(headerPair.Key, val);
                    }
                }
            }

            if (responseMessage.Content != null)
            {
                foreach (KeyValuePair <string, IEnumerable <string> > headerPair in responseMessage.Content.Headers)
                {
                    if (string.Compare(headerPair.Key, HttpConstants.HttpHeaders.OwnerFullName, StringComparison.Ordinal) == 0)
                    {
                        foreach (string val in headerPair.Value)
                        {
                            headers.Add(headerPair.Key, Uri.UnescapeDataString(val));
                        }
                    }
                    else
                    {
                        foreach (string val in headerPair.Value)
                        {
                            headers.Add(headerPair.Key, val);
                        }
                    }
                }
            }

            return(headers);
        }
        private async Task <AccountProperties> GetDatabaseAccountAsync(Uri serviceEndpoint)
        {
            HttpClient httpClient = this.messageHandler == null ? new HttpClient() : new HttpClient(this.messageHandler);

            httpClient.DefaultRequestHeaders.Add(HttpConstants.HttpHeaders.Version,
                                                 HttpConstants.Versions.CurrentVersion);

            // Send client version.
            httpClient.AddUserAgentHeader(this.connectionPolicy.UserAgentContainer);
            httpClient.AddApiTypeHeader(this.apiType);

            string authorizationToken = string.Empty;

            if (this.hasAuthKeyResourceToken)
            {
                authorizationToken = HttpUtility.UrlEncode(this.authKeyResourceToken);
            }
            else
            {
                // Retrieve the document service properties.
                string xDate = DateTime.UtcNow.ToString("r", CultureInfo.InvariantCulture);
                httpClient.DefaultRequestHeaders.Add(HttpConstants.HttpHeaders.XDate, xDate);

                INameValueCollection headersCollection = new DictionaryNameValueCollection();
                headersCollection.Add(HttpConstants.HttpHeaders.XDate, xDate);

                authorizationToken = AuthorizationHelper.GenerateKeyAuthorizationSignature(
                    HttpConstants.HttpMethods.Get,
                    serviceEndpoint,
                    headersCollection,
                    this.authKeyHashFunction);
            }

            httpClient.DefaultRequestHeaders.Add(HttpConstants.HttpHeaders.Authorization, authorizationToken);

            using (HttpResponseMessage responseMessage = await httpClient.GetHttpAsync(
                       serviceEndpoint))
            {
                using (DocumentServiceResponse documentServiceResponse = await ClientExtensions.ParseResponseAsync(responseMessage))
                {
                    return(CosmosResource.FromStream <AccountProperties>(documentServiceResponse));
                }
            }
        }
        public static void ThrowForbiddendExceptionOnItemOperation(
            Uri physicalAddress,
            DocumentServiceRequest request,
            string activityId,
            string errorMessage)
        {
            if (request.ResourceType == ResourceType.Document)
            {
                DictionaryNameValueCollection headers = new DictionaryNameValueCollection();
                headers.Add(HttpConstants.HttpHeaders.ActivityId, activityId.ToString());
                headers.Add(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.WriteForbidden).ToString(CultureInfo.InvariantCulture));

                ForbiddenException forbiddenException = new ForbiddenException(
                    errorMessage,
                    headers,
                    physicalAddress);

                throw forbiddenException;
            }
        }
        public void AuthorizationGenerateAndCheckKeyAuthSignature()
        {
            Random r = new Random();

            byte[] hashKey = new byte[16];
            r.NextBytes(hashKey);
            string key = Convert.ToBase64String(hashKey);

            foreach (string method in this.HttpMethods)
            {
                foreach (string resourceType in this.ResourceTypesArray)
                {
                    foreach (string resourceName in this.ResourceNameValues)
                    {
                        DictionaryNameValueCollection nvc = new DictionaryNameValueCollection();
                        nvc.Add(HttpConstants.HttpHeaders.XDate, new DateTime(2020, 02, 01, 10, 00, 00).ToString("r"));
                        string authorizationKey = AuthorizationHelper.GenerateKeyAuthorizationSignature(
                            method,
                            resourceName,
                            resourceType,
                            nvc,
                            new StringHMACSHA256Hash(key),
                            out string payload);

                        AuthorizationHelper.ParseAuthorizationToken(authorizationKey,
                                                                    out ReadOnlyMemory <char> typeOutput,
                                                                    out ReadOnlyMemory <char> versionOutput,
                                                                    out ReadOnlyMemory <char> tokenOutput);
                        Assert.AreEqual("master", typeOutput.ToString());

                        Assert.IsTrue(AuthorizationHelper.CheckPayloadUsingKey(
                                          tokenOutput,
                                          method,
                                          resourceName,
                                          resourceType,
                                          nvc,
                                          key));
                    }
                }
            }
        }
        private void ValidateCosistencyLevel(DocumentClient client)
        {
            //this is can be only tested with V2 OM, V3 doesnt allow to set invalid consistencty
            Database database = client.CreateDatabaseAsync(new Database {
                Id = Guid.NewGuid().ToString()
            }).Result;
            PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition {
                Paths = new System.Collections.ObjectModel.Collection <string>(new[] { "/id" }), Kind = PartitionKind.Hash
            };
            DocumentCollection collection = client.CreateDocumentCollectionAsync(database.SelfLink, new DocumentCollection
            {
                Id           = Guid.NewGuid().ToString(),
                PartitionKey = partitionKeyDefinition,
            }).Result;

            // Value not supported
            INameValueCollection headers = new DictionaryNameValueCollection();

            headers.Add(HttpConstants.HttpHeaders.ConsistencyLevel, "Not a valid value");

            try
            {
                ReadDocumentFeedRequest(client, collection.ResourceId, headers);
                Assert.Fail("Should throw an exception");
            }
            catch (Exception ex)
            {
                var innerException = ex.InnerException as DocumentClientException;
                Assert.IsTrue(innerException.StatusCode == HttpStatusCode.BadRequest, "invalid status code");
            }

            // Supported value
            headers = new DictionaryNameValueCollection();
            headers.Add(HttpConstants.HttpHeaders.ConsistencyLevel, ConsistencyLevel.Eventual.ToString());
            var response = ReadDocumentFeedRequest(client, collection.ResourceId, headers);

            Assert.IsTrue(response.StatusCode == HttpStatusCode.OK, "Invalid status code");
        }