示例#1
0
        /// <summary>
        /// Converts all occurrences of the 'application/json' media type to 'application/json;odata.metadata=minimal'.
        /// This is necessary because for an accept header 'application/json
        /// we want the result to be 'application/json;odata.metadata=minimal'
        /// </summary>
        /// <param name="specifiedTypes">The parsed acceptable media types.</param>
        private static void ConvertApplicationJsonInAcceptableMediaTypes(IList <KeyValuePair <ODataMediaType, string> > specifiedTypes)
        {
            if (specifiedTypes == null)
            {
                return;
            }

            for (int i = 0; i < specifiedTypes.Count; ++i)
            {
                ODataMediaType mediaType = specifiedTypes[i].Key;
                if (HttpUtils.CompareMediaTypeNames(mediaType.SubType, MimeConstants.MimeJsonSubType) &&
                    HttpUtils.CompareMediaTypeNames(mediaType.Type, MimeConstants.MimeApplicationType))
                {
                    if (mediaType.Parameters == null ||
                        !mediaType.Parameters.Any(p => HttpUtils.CompareMediaTypeParameterNames(p.Key, MimeConstants.MimeMetadataParameterName)))
                    {
                        // application/json detected; convert it to Json Light
                        IList <KeyValuePair <string, string> > existingParams = mediaType.Parameters != null?mediaType.Parameters.ToList() : null;

                        int newCount = existingParams == null ? 1 : existingParams.Count + 1;
                        List <KeyValuePair <string, string> > newParams = new List <KeyValuePair <string, string> >(newCount);
                        newParams.Add(new KeyValuePair <string, string>(MimeConstants.MimeMetadataParameterName, MimeConstants.MimeMetadataParameterValueMinimal));
                        if (existingParams != null)
                        {
                            newParams.AddRange(existingParams);
                        }

                        specifiedTypes[i] = new KeyValuePair <ODataMediaType, string>(new ODataMediaType(mediaType.Type, mediaType.SubType, newParams), specifiedTypes[i].Value);
                    }
                }
            }
        }
示例#2
0
        /// <summary>
        /// Checks whether two media types with subtypes (but without parameters) are equal.
        /// </summary>
        /// <param name="firstTypeAndSubtype">The first media type and subtype.</param>
        /// <param name="secondTypeAndSubtype">The second media type and subtype.</param>
        /// <returns>true if the <paramref name="firstTypeAndSubtype"/> is equal to <paramref name="secondTypeAndSubtype"/>; otherwise false.</returns>
        internal static bool MediaTypeAndSubtypeAreEqual(string firstTypeAndSubtype, string secondTypeAndSubtype)
        {
            ExceptionUtils.CheckArgumentNotNull(firstTypeAndSubtype, "firstTypeAndSubtype");
            ExceptionUtils.CheckArgumentNotNull(secondTypeAndSubtype, "secondTypeAndSubtype");

            return(HttpUtils.CompareMediaTypeNames(firstTypeAndSubtype, secondTypeAndSubtype));
        }
示例#3
0
        /// <summary>
        /// Checks for wildcard characters in the <see cref="ODataMediaType"/>.
        /// </summary>
        /// <param name="mediaType">The <see cref="ODataMediaType"/> to check.</param>
        internal static void CheckMediaTypeForWildCards(ODataMediaType mediaType)
        {
            Debug.Assert(mediaType != null, "mediaType != null");

            if (HttpUtils.CompareMediaTypeNames(MimeConstants.MimeStar, mediaType.Type) ||
                HttpUtils.CompareMediaTypeNames(MimeConstants.MimeStar, mediaType.SubType))
            {
                throw new ODataContentTypeException(Strings.ODataMessageReader_WildcardInContentType(mediaType.FullTypeName));
            }
        }
示例#4
0
        /// <summary>
        /// Detects the payload kind(s) from the message stream.
        /// </summary>
        /// <param name="contentType">The content type of the message.</param>
        /// <returns>An enumerable of zero, one or more payload kinds that were detected from looking at the payload in the message stream.</returns>
        private static IEnumerable <ODataPayloadKind> DetectPayloadKindImplementation(ODataMediaType contentType)
        {
            Debug.Assert(contentType != null, "contentType != null");

            if (HttpUtils.CompareMediaTypeNames(MimeConstants.MimeTextType, contentType.Type) &&
                HttpUtils.CompareMediaTypeNames(MimeConstants.MimeTextPlain, contentType.SubType))
            {
                return(new ODataPayloadKind[] { ODataPayloadKind.Value });
            }

            return(new ODataPayloadKind[] { ODataPayloadKind.BinaryValue });
        }
        /// <summary>
        /// Detects the payload kind(s) from the message stream.
        /// </summary>
        /// <param name="contentType">The content type of the message.</param>
        /// <returns>An enumerable of zero, one or more payload kinds that were detected from looking at the payload in the message stream.</returns>
        private static IEnumerable <ODataPayloadKind> DetectPayloadKindImplementation(ODataMediaType contentType)
        {
            // NOTE: for batch payloads we only use the content type header of the message to detect the payload kind.
            //       We assume a valid batch payload if the content type is multipart/mixed and a boundary parameter exists
            // Require 'multipart/mixed' content type with a boundary parameter to be considered batch.
            if (HttpUtils.CompareMediaTypeNames(MimeConstants.MimeMultipartType, contentType.Type) &&
                HttpUtils.CompareMediaTypeNames(MimeConstants.MimeMixedSubType, contentType.SubType) &&
                contentType.Parameters != null &&
                contentType.Parameters.Any(kvp => HttpUtils.CompareMediaTypeParameterNames(ODataConstants.HttpMultipartBoundary, kvp.Key)))
            {
                return(new ODataPayloadKind[] { ODataPayloadKind.Batch });
            }

            return(Enumerable.Empty <ODataPayloadKind>());
        }
        private static bool IsJsonMetadata(ODataMediaType contentType)
        {
            // by default, it's XML metadata
            if (contentType == null)
            {
                return(false);
            }

            if (HttpUtils.CompareMediaTypeNames(MimeConstants.MimeApplicationType, contentType.Type) &&
                HttpUtils.CompareMediaTypeNames(MimeConstants.MimeJsonSubType, contentType.SubType))
            {
                return(true);
            }

            return(false);
        }
示例#7
0
        /// <summary>
        /// Parse the content type header value to retrieve the boundary and encoding of a changeset.
        /// </summary>
        /// <param name="contentType">The content type to parse.</param>
        private void DetermineChangesetBoundaryAndEncoding(string contentType)
        {
            Debug.Assert(!string.IsNullOrEmpty(contentType), "Should have validated that non-null, non-empty content type header exists.");

            ODataMediaType   mediaType;
            ODataPayloadKind readerPayloadKind;

            MediaTypeUtils.GetFormatFromContentType(
                contentType,
                new ODataPayloadKind[] { ODataPayloadKind.Batch },
                this.mediaTypeResolver,
                out mediaType,
                out this.changesetEncoding,
                out readerPayloadKind,
                out this.changesetBoundary);
            Debug.Assert(readerPayloadKind == ODataPayloadKind.Batch, "Must find batch payload kind.");
            Debug.Assert(this.changesetBoundary != null && this.changesetBoundary.Length > 0, "Boundary string should have been validated by now.");
            Debug.Assert(HttpUtils.CompareMediaTypeNames(MimeConstants.MimeMultipartMixed, mediaType.FullTypeName), "Must be multipart/mixed media type.");
        }
示例#8
0
        /// <summary>
        /// Selects the encoding appropriate for this media type specification
        /// (possibly null).
        /// </summary>
        /// <returns>
        /// The encoding explicitly defined on the media type specification, or
        /// the default encoding for well-known media types.
        /// </returns>
        /// <remarks>
        /// As per http://tools.ietf.org/html/rfc2616#section-3.7, the type,
        /// subtype and parameter name attributes are case-insensitive.
        /// </remarks>
        internal Encoding SelectEncoding()
        {
            if (this.parameters != null)
            {
                foreach (string encodingName in
                         this.parameters.Where(parameter =>
                                               HttpUtils.CompareMediaTypeParameterNames(ODataConstants.Charset, parameter.Key))
                         .Select(parameter => parameter.Value.Trim())
                         .Where(encodingName => encodingName.Length > 0))
                {
                    return(EncodingFromName(encodingName));
                }
            }

            // Select the default encoding for this media type.
            if (HttpUtils.CompareMediaTypeNames(MimeConstants.MimeTextType, this.type))
            {
                // HTTP 3.7.1 Canonicalization and Text Defaults
                // "text" subtypes default to ISO-8859-1
                //
                // Unless the subtype is XML, in which case we should default
                // to us-ascii. Instead we return null, to let the encoding
                // in the <?xml ...?> PI win (http://tools.ietf.org/html/rfc3023#section-3.1)
                return(HttpUtils.CompareMediaTypeNames(MimeConstants.MimeXmlSubType, this.subType) ? null : MediaTypeUtils.MissingEncoding);
            }

            if (HttpUtils.CompareMediaTypeNames(MimeConstants.MimeApplicationType, this.type) &&
                HttpUtils.CompareMediaTypeNames(MimeConstants.MimeJsonSubType, this.subType))
            {
                // http://tools.ietf.org/html/rfc4627#section-3
                // The default encoding is UTF-8.
                return(MediaTypeUtils.FallbackEncoding);
            }

            return(null);
        }
示例#9
0
            /// <summary>
            /// Matches the source type against the media type.
            /// </summary>
            /// <param name="sourceType">The source <see cref="ODataMediaType"/> to match against the target type.</param>
            /// <param name="targetType">The target <see cref="ODataMediaType"/> to match against the source type.</param>
            private void MatchTypes(ODataMediaType sourceType, ODataMediaType targetType)
            {
                this.MatchingTypeNamePartCount = -1;

                if (sourceType.Type == "*")
                {
                    this.MatchingTypeNamePartCount = 0;
                }
                else
                {
                    if (HttpUtils.CompareMediaTypeNames(sourceType.Type, targetType.Type))
                    {
                        if (sourceType.SubType == "*")
                        {
                            // only type matches
                            this.MatchingTypeNamePartCount = 1;
                        }
                        else if (HttpUtils.CompareMediaTypeNames(sourceType.SubType, targetType.SubType))
                        {
                            // both type and subtype match
                            this.MatchingTypeNamePartCount = 2;
                        }
                    }
                }

                this.QualityValue = DefaultQualityValue;
                this.SourceTypeParameterCountForMatching = 0;
                this.MatchingParameterCount = 0;

                IList <KeyValuePair <string, string> > sourceParameters = sourceType.Parameters != null?sourceType.Parameters.ToList() : null;

                IList <KeyValuePair <string, string> > targetParameters = targetType.Parameters != null?targetType.Parameters.ToList() : null;

                bool targetHasParams = targetParameters != null && targetParameters.Count > 0;
                bool sourceHasParams = sourceParameters != null && sourceParameters.Count > 0;

                if (sourceHasParams)
                {
                    for (int i = 0; i < sourceParameters.Count; ++i)
                    {
                        string parameterName = sourceParameters[i].Key;
                        if (IsQualityValueParameter(parameterName))
                        {
                            // once we hit the q-value in the parameters we know that only accept-params will follow
                            // that don't contribute to the matching. Parse the quality value but don't continue processing
                            // parameters.
                            this.QualityValue = ParseQualityValue(sourceParameters[i].Value.Trim());
                            break;
                        }

                        this.SourceTypeParameterCountForMatching = i + 1;

                        if (targetHasParams)
                        {
                            // find the current parameter name in the set of parameters of the candidate and compare the value;
                            // if they match increase the result count
                            // NOTE: according to RFC 2045, Section 2, parameter values are case sensitive per default (while
                            //       type values, subtype values and parameter names are case-insensitive); however, we
                            //       are more relaxed in ODL and allow case insensitive values.
                            string parameterValue;
                            if (TryFindMediaTypeParameter(targetParameters, parameterName, out parameterValue) &&
                                String.Compare(sourceParameters[i].Value.Trim(), parameterValue.Trim(), StringComparison.OrdinalIgnoreCase) == 0)
                            {
                                this.MatchingParameterCount++;
                            }
                        }
                    }
                }

                // if the source does not have parameters or it only has accept extensions
                // (parameters after the q value) or we match all the parameters we
                // have a perfect parameter match.
                if (!sourceHasParams ||
                    this.SourceTypeParameterCountForMatching == 0 ||
                    this.MatchingParameterCount == this.SourceTypeParameterCountForMatching)
                {
                    this.MatchingParameterCount = -1;
                }
            }