internal static Encoding EncodingFromAcceptableCharsets(string acceptableCharsets, MediaType mediaType, Encoding utf8Encoding, Encoding defaultEncoding) { Encoding encodingFromCharsetName = null; if (!string.IsNullOrEmpty(acceptableCharsets)) { foreach (KeyValuePair <int, CharsetPart> pair in new List <CharsetPart>(AcceptCharsetParts(acceptableCharsets)).ToArray().StableSort <CharsetPart>((x, y) => y.Quality - x.Quality)) { CharsetPart part = pair.Value; if (part.Quality > 0) { if (string.Compare("utf-8", part.Charset, StringComparison.OrdinalIgnoreCase) == 0) { encodingFromCharsetName = utf8Encoding; break; } encodingFromCharsetName = GetEncodingFromCharsetName(part.Charset); if (encodingFromCharsetName != null) { break; } } } } if (encodingFromCharsetName == null) { encodingFromCharsetName = mediaType.SelectEncoding(); if (encodingFromCharsetName == null) { return(defaultEncoding); } } return(encodingFromCharsetName); }
/// <summary>Gets the best encoding available for the specified charset request.</summary> /// <param name="acceptableCharsets"> /// The Accept-Charset header value (eg: "iso-8859-5, unicode-1-1;q=0.8"). /// </param> /// <param name="mediaType">The media type used to compute the default encoding for the payload.</param> /// <param name="utf8Encoding">The encoding to use for UTF-8 charsets; we use the one without the BOM.</param> /// <param name="defaultEncoding">The encoding to use if no encoding could be computed from the <paramref name="acceptableCharsets"/> or <paramref name="mediaType"/>.</param> /// <returns>An Encoding object appropriate to the specifed charset request.</returns> internal static Encoding EncodingFromAcceptableCharsets(string acceptableCharsets, MediaType mediaType, Encoding utf8Encoding, Encoding defaultEncoding) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(mediaType != null, "mediaType != null"); // Determines the appropriate encoding mapping according to // RFC 2616.14.2 (http://tools.ietf.org/html/rfc2616#section-14.2). Encoding result = null; if (!string.IsNullOrEmpty(acceptableCharsets)) { // PERF: in the future if we find that computing the encoding from the accept charsets is // too expensive we could introduce a cache of original strings to resolved encoding. CharsetPart[] parts = new List <CharsetPart>(AcceptCharsetParts(acceptableCharsets)).ToArray(); // NOTE: List<T>.Sort uses an unstable sort algorithm; if charsets have the same quality value // we want to pick the first one specified so we need a stable sort. KeyValuePair <int, CharsetPart>[] sortedParts = parts.StableSort(delegate(CharsetPart x, CharsetPart y) { return(y.Quality - x.Quality); }); foreach (KeyValuePair <int, CharsetPart> sortedPart in sortedParts) { CharsetPart part = sortedPart.Value; if (part.Quality > 0) { // When UTF-8 is specified, select the version that doesn't use the BOM. if (String.Compare("utf-8", part.Charset, StringComparison.OrdinalIgnoreCase) == 0) { result = utf8Encoding; break; } else { result = GetEncodingFromCharsetName(part.Charset); if (result != null) { break; } // If the charset is not supported it is ignored so other possible charsets are evaluated. } } } } // No Charset was specifed, or if charsets were specified, no valid charset was found. // Returning a different charset is also valid. Get the default encoding for the media type. if (result == null) { result = mediaType.SelectEncoding(); if (result == null) { return(defaultEncoding); } } return(result); }
internal static ODataFormat GetContentTypeFromSettings(ODataMessageWriterSettings settings, ODataPayloadKind payloadKind, MediaTypeResolver mediaTypeResolver, out MediaType mediaType, out Encoding encoding) { ODataFormat format; MediaTypeWithFormat format2; MediaTypeWithFormat[] mediaTypesForPayloadKind = mediaTypeResolver.GetMediaTypesForPayloadKind(payloadKind); if ((mediaTypesForPayloadKind == null) || (mediaTypesForPayloadKind.Length == 0)) { throw new ODataContentTypeException(Microsoft.Data.OData.Strings.MediaTypeUtils_DidNotFindMatchingMediaType(null, settings.AcceptableMediaTypes)); } if (settings.UseFormat == true) { mediaType = GetDefaultMediaType(mediaTypesForPayloadKind, settings.Format, out format); encoding = mediaType.SelectEncoding(); return(format); } IList <KeyValuePair <MediaType, string> > specifiedTypes = HttpUtils.MediaTypesFromString(settings.AcceptableMediaTypes); if (((ODataVersion)settings.Version) == ODataVersion.V3) { specifiedTypes = RemoveApplicationJsonFromAcceptableMediaTypes(specifiedTypes, mediaTypesForPayloadKind, settings.AcceptableMediaTypes); } string str = null; if ((specifiedTypes == null) || (specifiedTypes.Count == 0)) { format2 = mediaTypesForPayloadKind[0]; } else { MediaTypeMatchInfo info = MatchMediaTypes(from kvp in specifiedTypes select kvp.Key, (from smt in mediaTypesForPayloadKind select smt.MediaType).ToArray <MediaType>()); if (info == null) { throw new ODataContentTypeException(Microsoft.Data.OData.Strings.MediaTypeUtils_DidNotFindMatchingMediaType(string.Join(", ", (from mt in mediaTypesForPayloadKind select mt.MediaType.ToText()).ToArray <string>()), settings.AcceptableMediaTypes)); } format2 = mediaTypesForPayloadKind[info.TargetTypeIndex]; KeyValuePair <MediaType, string> pair = specifiedTypes[info.SourceTypeIndex]; str = pair.Value; } format = format2.Format; mediaType = format2.MediaType; string acceptableCharsets = settings.AcceptableCharsets; if (str != null) { acceptableCharsets = (acceptableCharsets == null) ? str : (str + "," + acceptableCharsets); } encoding = GetEncoding(acceptableCharsets, payloadKind, mediaType, true); return(format); }
/// <summary>Gets the best encoding available for the specified charset request.</summary> /// <param name="acceptableCharsets"> /// The Accept-Charset header value (eg: "iso-8859-5, unicode-1-1;q=0.8"). /// </param> /// <param name="mediaType">The media type used to compute the default encoding for the payload.</param> /// <param name="utf8Encoding">The encoding to use for UTF-8 charsets; we use the one without the BOM.</param> /// <param name="defaultEncoding">The encoding to use if no encoding could be computed from the <paramref name="acceptableCharsets"/> or <paramref name="mediaType"/>.</param> /// <returns>An Encoding object appropriate to the specifed charset request.</returns> internal static Encoding EncodingFromAcceptableCharsets(string acceptableCharsets, MediaType mediaType, Encoding utf8Encoding, Encoding defaultEncoding) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(mediaType != null, "mediaType != null"); // Determines the appropriate encoding mapping according to // RFC 2616.14.2 (http://tools.ietf.org/html/rfc2616#section-14.2). Encoding result = null; if (!string.IsNullOrEmpty(acceptableCharsets)) { // PERF: in the future if we find that computing the encoding from the accept charsets is // too expensive we could introduce a cache of original strings to resolved encoding. CharsetPart[] parts = new List<CharsetPart>(AcceptCharsetParts(acceptableCharsets)).ToArray(); // NOTE: List<T>.Sort uses an unstable sort algorithm; if charsets have the same quality value // we want to pick the first one specified so we need a stable sort. KeyValuePair<int, CharsetPart>[] sortedParts = parts.StableSort(delegate(CharsetPart x, CharsetPart y) { return y.Quality - x.Quality; }); foreach (KeyValuePair<int, CharsetPart> sortedPart in sortedParts) { CharsetPart part = sortedPart.Value; if (part.Quality > 0) { // When UTF-8 is specified, select the version that doesn't use the BOM. if (String.Compare("utf-8", part.Charset, StringComparison.OrdinalIgnoreCase) == 0) { result = utf8Encoding; break; } else { result = GetEncodingFromCharsetName(part.Charset); if (result != null) { break; } // If the charset is not supported it is ignored so other possible charsets are evaluated. } } } } // No Charset was specifed, or if charsets were specified, no valid charset was found. // Returning a different charset is also valid. Get the default encoding for the media type. if (result == null) { result = mediaType.SelectEncoding(); if (result == null) { return defaultEncoding; } } return result; }
/// <summary> /// Given the Accept and the Accept-Charset headers of the request message computes the media type, encoding and <see cref="ODataFormat"/> /// to be used for the response message. /// </summary> /// <param name="settings">The message writer settings to use for serializing the response payload.</param> /// <param name="payloadKind">The kind of payload to be serialized as part of the response message.</param> /// <param name="mediaTypeResolver">The media type resolver to use when interpreting the content type.</param> /// <param name="mediaType">The media type to be used in the response message.</param> /// <param name="encoding">The encoding to be used in the response message.</param> /// <returns>The <see cref="ODataFormat"/> used when serializing the response.</returns> internal static ODataFormat GetContentTypeFromSettings( ODataMessageWriterSettings settings, ODataPayloadKind payloadKind, MediaTypeResolver mediaTypeResolver, out MediaType mediaType, out Encoding encoding) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(settings != null, "settings != null"); // compute format, media type and encoding ODataFormat format; // get the supported and default media types for the specified payload kind MediaTypeWithFormat[] supportedMediaTypes = mediaTypeResolver.GetMediaTypesForPayloadKind(payloadKind); if (supportedMediaTypes == null || supportedMediaTypes.Length == 0) { throw new ODataContentTypeException(Strings.MediaTypeUtils_DidNotFindMatchingMediaType(null, settings.AcceptableMediaTypes)); } if (settings.UseFormat == true) { Debug.Assert(settings.AcceptableMediaTypes == null, "settings.AcceptableMediaTypes == null"); Debug.Assert(settings.AcceptableCharsets == null, "settings.AcceptableCharsets == null"); mediaType = GetDefaultMediaType(supportedMediaTypes, settings.Format, out format); // NOTE the default media types don't have any parameters (in particular no 'charset' parameters) encoding = mediaType.SelectEncoding(); } else { // parse the accept header into its parts IList <KeyValuePair <MediaType, string> > specifiedTypes = HttpUtils.MediaTypesFromString(settings.AcceptableMediaTypes); if (settings.Version == ODataVersion.V3) { specifiedTypes = RemoveApplicationJsonFromAcceptableMediaTypes(specifiedTypes, supportedMediaTypes, settings.AcceptableMediaTypes); } MediaTypeWithFormat selectedMediaTypeWithFormat; string specifiedCharset = null; if (specifiedTypes == null || specifiedTypes.Count == 0) { selectedMediaTypeWithFormat = supportedMediaTypes[0]; } else { // match the specified media types against the supported/default ones and get the format MediaTypeMatchInfo matchInfo = MatchMediaTypes(specifiedTypes.Select(kvp => kvp.Key), supportedMediaTypes.Select(smt => smt.MediaType).ToArray()); if (matchInfo == null) { // We're calling the ToArray here since not all platforms support the string.Join which takes IEnumerable. string supportedTypesAsString = string.Join(", ", supportedMediaTypes.Select(mt => mt.MediaType.ToText()).ToArray()); throw new ODataContentTypeException(Strings.MediaTypeUtils_DidNotFindMatchingMediaType(supportedTypesAsString, settings.AcceptableMediaTypes)); } selectedMediaTypeWithFormat = supportedMediaTypes[matchInfo.TargetTypeIndex]; specifiedCharset = specifiedTypes[matchInfo.SourceTypeIndex].Value; } format = selectedMediaTypeWithFormat.Format; mediaType = selectedMediaTypeWithFormat.MediaType; // If a charset was specified with the accept header, consider it for the encoding string acceptableCharsets = settings.AcceptableCharsets; if (specifiedCharset != null) { acceptableCharsets = acceptableCharsets == null ? specifiedCharset : specifiedCharset + "," + acceptableCharsets; } encoding = GetEncoding(acceptableCharsets, payloadKind, mediaType, /*useDefaultEncoding*/ true); } return(format); }
internal static Encoding EncodingFromAcceptableCharsets(string acceptableCharsets, MediaType mediaType, Encoding utf8Encoding, Encoding defaultEncoding) { Encoding encodingFromCharsetName = null; if (!string.IsNullOrEmpty(acceptableCharsets)) { foreach (KeyValuePair<int, CharsetPart> pair in new List<CharsetPart>(AcceptCharsetParts(acceptableCharsets)).ToArray().StableSort<CharsetPart>((x, y) => y.Quality - x.Quality)) { CharsetPart part = pair.Value; if (part.Quality > 0) { if (string.Compare("utf-8", part.Charset, StringComparison.OrdinalIgnoreCase) == 0) { encodingFromCharsetName = utf8Encoding; break; } encodingFromCharsetName = GetEncodingFromCharsetName(part.Charset); if (encodingFromCharsetName != null) { break; } } } } if (encodingFromCharsetName == null) { encodingFromCharsetName = mediaType.SelectEncoding(); if (encodingFromCharsetName == null) { return defaultEncoding; } } return encodingFromCharsetName; }
/// <summary> /// Given the Accept and the Accept-Charset headers of the request message computes the media type, encoding and <see cref="ODataFormat"/> /// to be used for the response message. /// </summary> /// <param name="settings">The message writer settings to use for serializing the response payload.</param> /// <param name="payloadKind">The kind of payload to be serialized as part of the response message.</param> /// <param name="mediaTypeResolver">The media type resolver to use when interpreting the content type.</param> /// <param name="mediaType">The media type to be used in the response message.</param> /// <param name="encoding">The encoding to be used in the response message.</param> /// <returns>The <see cref="ODataFormat"/> used when serializing the response.</returns> internal static ODataFormat GetContentTypeFromSettings( ODataMessageWriterSettings settings, ODataPayloadKind payloadKind, MediaTypeResolver mediaTypeResolver, out MediaType mediaType, out Encoding encoding) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(settings != null, "settings != null"); // compute format, media type and encoding ODataFormat format; // get the supported and default media types for the specified payload kind IList <MediaTypeWithFormat> supportedMediaTypes = mediaTypeResolver.GetMediaTypesForPayloadKind(payloadKind); if (supportedMediaTypes == null || supportedMediaTypes.Count == 0) { throw new ODataContentTypeException(Strings.MediaTypeUtils_DidNotFindMatchingMediaType(null, settings.AcceptableMediaTypes)); } if (settings.UseFormat == true) { Debug.Assert(settings.AcceptableMediaTypes == null, "settings.AcceptableMediaTypes == null"); Debug.Assert(settings.AcceptableCharsets == null, "settings.AcceptableCharsets == null"); mediaType = GetDefaultMediaType(supportedMediaTypes, settings.Format, out format); // NOTE the default media types don't have any parameters (in particular no 'charset' parameters) encoding = mediaType.SelectEncoding(); } else { // parse the accept header into its parts IList <KeyValuePair <MediaType, string> > specifiedTypes = HttpUtils.MediaTypesFromString(settings.AcceptableMediaTypes); // Starting in V3 we replace all occurrences of application/json with application/json;odata=minimalmetadata // before handing the acceptable media types to the conneg code. This is necessary because for an accept // header 'application/json, application/json;odata=verbose' we want to the result to be 'application/json;odata=minimalmetadata' // although this is not compliant with the default conneg rules (where application/json;odata=verbose would win). if (settings.Version >= ODataVersion.V3) { ConvertApplicationJsonInAcceptableMediaTypes(specifiedTypes); } MediaTypeWithFormat selectedMediaTypeWithFormat; string specifiedCharset = null; if (specifiedTypes == null || specifiedTypes.Count == 0) { selectedMediaTypeWithFormat = supportedMediaTypes[0]; } else { // match the specified media types against the supported/default ones and get the format MediaTypeMatchInfo matchInfo = MatchMediaTypes(specifiedTypes.Select(kvp => kvp.Key), supportedMediaTypes.Select(smt => smt.MediaType).ToArray()); if (matchInfo == null) { // We're calling the ToArray here since not all platforms support the string.Join which takes IEnumerable. string supportedTypesAsString = String.Join(", ", supportedMediaTypes.Select(mt => mt.MediaType.ToText()).ToArray()); throw new ODataContentTypeException(Strings.MediaTypeUtils_DidNotFindMatchingMediaType(supportedTypesAsString, settings.AcceptableMediaTypes)); } selectedMediaTypeWithFormat = supportedMediaTypes[matchInfo.TargetTypeIndex]; specifiedCharset = specifiedTypes[matchInfo.SourceTypeIndex].Value; } format = selectedMediaTypeWithFormat.Format; mediaType = selectedMediaTypeWithFormat.MediaType; // If a charset was specified with the accept header, consider it for the encoding string acceptableCharsets = settings.AcceptableCharsets; if (specifiedCharset != null) { acceptableCharsets = acceptableCharsets == null ? specifiedCharset : specifiedCharset + "," + acceptableCharsets; } encoding = GetEncoding(acceptableCharsets, payloadKind, mediaType, /*useDefaultEncoding*/ true); } return(format); }