Example #1
0
        public void EndpointConstraint_Accept_ForNoRequestType_ReturnsTrueForAllConstraints(string contentType)
        {
            // Arrange
            var constraint1            = new ConsumesAttribute("application/json");
            var endpointWithConstraint = CreateEndpoint(constraint1);

            var constraint2             = new ConsumesAttribute("text/xml");
            var endpointWithConstraint2 = CreateEndpoint(constraint2);

            var endpointWithoutConstraint = CreateEndpoint();

            var context = new EndpointConstraintContext();

            context.Candidates = new List <EndpointSelectorCandidate>()
            {
                new EndpointSelectorCandidate(endpointWithConstraint, new [] { constraint1 }),
                new EndpointSelectorCandidate(endpointWithConstraint2, new [] { constraint2 }),
            };

            context.HttpContext = CreateHttpContext(contentType: contentType);

            // Act & Assert
            context.CurrentCandidate = context.Candidates[0];
            Assert.True(constraint1.Accept(context));
            context.CurrentCandidate = context.Candidates[1];
            Assert.True(constraint2.Accept(context));
        }
Example #2
0
        public void EndpointConstraint_Accept_UnrecognizedMediaType_SelectsTheCandidateWithoutConstraintIfPresent(string contentType)
        {
            // Arrange
            var endpointWithoutConstraint = CreateEndpoint();
            var constraint1            = new ConsumesAttribute("application/json");
            var endpointWithConstraint = CreateEndpoint(constraint1);

            var constraint2             = new ConsumesAttribute("text/xml");
            var endpointWithConstraint2 = CreateEndpoint(constraint2);

            var context = new EndpointConstraintContext();

            context.Candidates = new List <EndpointSelectorCandidate>()
            {
                new EndpointSelectorCandidate(endpointWithConstraint, new [] { constraint1 }),
                new EndpointSelectorCandidate(endpointWithConstraint2, new [] { constraint2 }),
                new EndpointSelectorCandidate(endpointWithoutConstraint, new List <IEndpointConstraint>()),
            };

            context.HttpContext = CreateHttpContext(contentType: contentType);

            // Act & Assert
            context.CurrentCandidate = context.Candidates[0];
            Assert.False(constraint1.Accept(context));

            context.CurrentCandidate = context.Candidates[1];
            Assert.False(constraint2.Accept(context));
        }
Example #3
0
        public void EndpointConstraint_Accept_ForNoMatchingCandidates_SelectsTheFirstCandidate(string contentType)
        {
            // Arrange
            var constraint1 = new ConsumesAttribute("application/json", "text/xml");
            var endpoint1   = CreateEndpoint(constraint1);

            var constraint2 = new Mock <ITestEndpointConsumeConstraint>();
            var endpoint2   = CreateEndpoint(constraint2.Object);

            constraint2.Setup(o => o.Accept(It.IsAny <EndpointConstraintContext>()))
            .Returns(false);

            var context = new EndpointConstraintContext();

            context.Candidates = new List <EndpointSelectorCandidate>()
            {
                new EndpointSelectorCandidate(endpoint1, new [] { constraint1 }),
                new EndpointSelectorCandidate(endpoint2, new [] { constraint2.Object }),
            };

            context.CurrentCandidate = context.Candidates[0];
            context.HttpContext      = CreateHttpContext(contentType: contentType);

            // Act & Assert
            Assert.True(constraint1.Accept(context));
        }
Example #4
0
        private static EndpointConstraintContext CreateEndpointConstraintContext(HttpMethodEndpointConstraint constraint)
        {
            var context = new EndpointConstraintContext();

            var endpointSelectorCandidate = new EndpointSelectorCandidate(new TestEndpoint(EndpointMetadataCollection.Empty, string.Empty), new List <IEndpointConstraint> {
                constraint
            });

            context.Candidates = new List <EndpointSelectorCandidate> {
                endpointSelectorCandidate
            };
            context.CurrentCandidate = context.Candidates[0];

            return(context);
        }
Example #5
0
        public void EndpointConstraint_Accept_MatchesForMachingRequestContentType(string contentType)
        {
            // Arrange
            var constraint = new ConsumesAttribute("application/json", "text/xml");
            var endpoint   = CreateEndpoint(constraint);

            var context = new EndpointConstraintContext();

            context.Candidates = new List <EndpointSelectorCandidate>()
            {
                new EndpointSelectorCandidate(endpoint, new [] { constraint }),
            };

            context.CurrentCandidate = context.Candidates[0];
            context.HttpContext      = CreateHttpContext(contentType: contentType);

            // Act & Assert
            Assert.True(constraint.Accept(context));
        }
Example #6
0
        /// <inheritdoc />
        public bool Accept(EndpointConstraintContext context)
        {
            // If this constraint is not closest to the endpoint, it will be skipped.
            if (!IsApplicable(context.CurrentCandidate.Endpoint))
            {
                // Since the constraint is to be skipped, returning true here
                // will let the current candidate ignore this constraint and will
                // be selected based on other constraints for this endpoint.
                return(true);
            }

            var requestContentType = context.HttpContext.Request.ContentType;

            // If the request content type is null we need to act like pass through.
            // In case there is a single candidate with a constraint it should be selected.
            // If there are multiple endpoints with consumes endpoint constraints this should result in ambiguous exception
            // unless there is another endpoint without a consumes constraint.
            if (requestContentType == null)
            {
                var isEndpointWithoutConsumeConstraintPresent = context.Candidates.Any(
                    candidate => candidate.Constraints == null ||
                    !candidate.Constraints.Any(constraint => constraint is IConsumesEndpointConstraint));

                return(!isEndpointWithoutConsumeConstraintPresent);
            }

            // Confirm the request's content type is more specific than (a media type this endpoint supports e.g. OK
            // if client sent "text/plain" data and this endpoint supports "text/*".
            if (IsSubsetOfAnyContentType(requestContentType))
            {
                return(true);
            }

            var firstCandidate = context.Candidates[0];

            if (firstCandidate.Endpoint != context.CurrentCandidate.Endpoint)
            {
                // If the current candidate is not same as the first candidate,
                // we need not probe other candidates to see if they apply.
                // Only the first candidate is allowed to probe other candidates and based on the result select itself.
                return(false);
            }

            // Run the matching logic for all IConsumesEndpointConstraints we can find, and see what matches.
            // 1). If we have a unique best match, then only that constraint should return true.
            // 2). If we have multiple matches, then all constraints that match will return true
            // , resulting in ambiguity(maybe).
            // 3). If we have no matches, then we choose the first constraint to return true.It will later return a 415
            foreach (var candidate in context.Candidates)
            {
                if (candidate.Endpoint == firstCandidate.Endpoint)
                {
                    continue;
                }

                var tempContext = new EndpointConstraintContext()
                {
                    Candidates       = context.Candidates,
                    HttpContext      = context.HttpContext,
                    CurrentCandidate = candidate
                };

                if (candidate.Constraints == null || candidate.Constraints.Count == 0 ||
                    candidate.Constraints.Any(constraint => constraint is IConsumesEndpointConstraint &&
                                              constraint.Accept(tempContext)))
                {
                    // There is someone later in the chain which can handle the request.
                    // end the process here.
                    return(false);
                }
            }

            // There is no one later in the chain that can handle this content type return a false positive so that
            // later we can detect and return a 415.
            return(true);
        }
Example #7
0
 public bool Accept(EndpointConstraintContext context)
 {
     return(ProcessRequest(context.HttpContext.Request));
 }
 bool IEndpointConstraint.Accept(EndpointConstraintContext context)
 {
     return(AcceptCore());
 }