/// <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); } } } }
/// <summary> /// Checks whether the specified media type has a parameter with the expected value. /// </summary> /// <param name="mediaType">The media type to check the parameters for.</param> /// <param name="parameterName">The name of the expected parameter.</param> /// <param name="parameterValue">The value of the expected parameter.</param> /// <returns>true if the <paramref name="mediaType"/> has a parameter called <paramref name="parameterName"/> /// with value <paramref name="parameterValue"/>; otherwise false.</returns> internal static bool MediaTypeHasParameterWithValue(this ODataMediaType mediaType, string parameterName, string parameterValue) { Debug.Assert(mediaType != null, "mediaType != null"); Debug.Assert(parameterName != null, "parameterName != null"); if (mediaType.Parameters == null) { return(false); } return(mediaType.Parameters.Any(p => HttpUtils.CompareMediaTypeParameterNames(p.Key, parameterName) && String.Compare(p.Value, parameterValue, StringComparison.OrdinalIgnoreCase) == 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) { // 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>()); }
/// <summary> /// Converts the current <see cref="ODataMediaType"/> to a string representation suitable for use in a content-type header. /// </summary> /// <param name="encoding">The encoding to use when converting the media type into text.</param> /// <returns>The string representation of the current media type.</returns> internal string ToText(Encoding encoding) { // TODO: for now we include all the parameters since we know that we will not have accept parameters (after the quality value) // that needed to be ignored. if (this.parameters == null || !this.parameters.Any()) { string typeName = this.FullTypeName; if (encoding != null) { typeName = string.Concat(typeName, ";", ODataConstants.Charset, "=", encoding.WebName); } return(typeName); } StringBuilder builder = new StringBuilder(this.FullTypeName); foreach (KeyValuePair <string, string> parameter in this.parameters) { // ignore the char set if specified in the parameters; we write the one from the encoding if (HttpUtils.CompareMediaTypeParameterNames(ODataConstants.Charset, parameter.Key)) { continue; } builder.Append(";"); builder.Append(parameter.Key); builder.Append("="); builder.Append(parameter.Value); } // write the encoding (if any) if (encoding != null) { builder.Append(";"); builder.Append(ODataConstants.Charset); builder.Append("="); builder.Append(encoding.WebName); } return(builder.ToString()); }
/// <summary> /// Tries to find a parameter with the specified <paramref name="parameterName"/> in the given list <paramref name="parameters"/> of parameters. /// Does not include accept extensions (i.e., parameters after the q quality value parameter) /// </summary> /// <param name="parameters">The list of parameters to search.</param> /// <param name="parameterName">The name of the parameter to find.</param> /// <param name="parameterValue">The parameter value of the parameter with the specified <paramref name="parameterName"/>.</param> /// <returns>True if a parameter with the specified <paramref name="parameterName"/> was found; otherwise false.</returns> private static bool TryFindMediaTypeParameter(IList <KeyValuePair <string, string> > parameters, string parameterName, out string parameterValue) { Debug.Assert(!String.IsNullOrEmpty(parameterName), "!string.IsNullOrEmpty(parameterName)"); parameterValue = null; if (parameters != null) { for (int i = 0; i < parameters.Count; ++i) { string candidateParameterName = parameters[i].Key; if (HttpUtils.CompareMediaTypeParameterNames(parameterName, candidateParameterName)) { parameterValue = parameters[i].Value; return(true); } } } return(false); }
/// <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); }
/// <summary> /// Returns a flag indicating whether a given media type parameter name is the Http quality value parameter. /// </summary> /// <param name="parameterName">The parameter name to check.</param> /// <returns>True if the parameter name is for the quality value; otherwise false.</returns> private static bool IsQualityValueParameter(string parameterName) { return(HttpUtils.CompareMediaTypeParameterNames(ODataConstants.HttpQValueParameter, parameterName)); }