<commit_before>﻿using System;
using System.Collections.Immutable;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;

namespace HTTPlease
{
	using Formatters;

	/// <summary>
	///		Extension methods for working with <see cref="HttpRequest"/>s.
	/// </summary>
	public static class FormatterRequestExtensions
    {
		/// <summary>
		///		Create a copy of the <see cref="HttpRequest"/>, configuring it to accept the JSON ("application/json") media type.
		/// </summary>
		/// <param name="request">
		///		The <see cref="HttpRequest"/>.
		/// </param>
		/// <returns>
		///		The new <see cref="HttpRequest"/>.
		/// </returns>
		public static HttpRequest ExpectJson(this HttpRequest request)
		{
			if (request == null)
				throw new ArgumentNullException(nameof(request));

			return request.AcceptMediaType(WellKnownMediaTypes.Json);
		}

		/// <summary>
		///		Create a copy of the <see cref="HttpRequest"/>, configuring it to accept the JSON ("application/json") media type.
		/// </summary>
		/// <typeparam name="TContext">
		///		The type of object used as a context for resolving deferred parameters.
		/// </typeparam>
		/// <param name="request">
		///		The <see cref="HttpRequest"/>.
		/// </param>
		/// <returns>
		///		The new <see cref="HttpRequest"/>.
		/// </returns>
		public static HttpRequest<TContext> ExpectJson<TContext>(this HttpRequest<TContext> request)
		{
			if (request == null)
				throw new ArgumentNullException(nameof(request));

			return request.AcceptMediaType(WellKnownMediaTypes.Json);
		}

		/// <summary>
		///		Create a copy of the <see cref="HttpRequest"/>, configuring it to accept the XML ("application/json") media type.
		/// </summary>
		/// <param name="request">
		///		The <see cref="HttpRequest"/>.
		/// </param>
		/// <returns>
		///		The new <see cref="HttpRequest"/>.
		/// </returns>
		public static HttpRequest ExpectXml(this HttpRequest request)
		{
			if (request == null)
				throw new ArgumentNullException(nameof(request));

			return request.AcceptMediaType(WellKnownMediaTypes.Xml);
		}

		/// <summary>
		///		Create a copy of the <see cref="HttpRequest"/>, configuring it to accept the XML ("application/json") media type.
		/// </summary>
		/// <typeparam name="TContext">
		///		The type of object used as a context for resolving deferred parameters.
		/// </typeparam>
		/// <param name="request">
		///		The <see cref="HttpRequest"/>.
		/// </param>
		/// <returns>
		///		The new <see cref="HttpRequest"/>.
		/// </returns>
		public static HttpRequest<TContext> ExpectXml<TContext>(this HttpRequest<TContext> request)
		{
			if (request == null)
				throw new ArgumentNullException(nameof(request));

			return request.AcceptMediaType(WellKnownMediaTypes.Xml);
		}
		
		/// <summary>
		///		Build an HTTP request message, selecting an appropriate content formatter to serialise its body content.
		/// </summary>
		/// <param name="request">
		///		The <see cref="HttpRequest"/>.
		/// </param>
		/// <param name="httpMethod">
		///		The HTTP request method.
		/// </param>
		/// <param name="bodyContent">
		///		The request body content.
		/// </param>
		/// <param name="mediaType">
		///		The request body media type to use.
		/// </param>
		/// <param name="baseUri">
		///		An optional base URI to use if the request does not already have an absolute request URI.
		/// </param>
		/// <returns>
		///		The configured <see cref="HttpRequestMessage"/>.
		/// </returns>
		public static HttpRequestMessage BuildRequestMessage(this HttpRequest request, HttpMethod httpMethod, object bodyContent, string mediaType, Uri baseUri = null)
		{
			if (request == null)
				throw new ArgumentNullException(nameof(request));

			return request.BuildRequestMessage(httpMethod, bodyContent, mediaType, OutputEncoding.UTF8, baseUri);
		}

		/// <summary>
		///		Build an HTTP request message, selecting an appropriate content formatter to serialise its body content.
		/// </summary>
		/// <param name="request">
		///		The <see cref="HttpRequest"/>.
		/// </param>
		/// <param name="httpMethod">
		///		The HTTP request method.
		/// </param>
		/// <param name="bodyContent">
		///		The request body content.
		/// </param>
		/// <param name="mediaType">
		///		The request body media type to use.
		/// </param>
		/// <param name="encoding">
		///		The request body encoding to use.
		/// </param>
		/// <param name="baseUri">
		///		An optional base URI to use if the request does not already have an absolute request URI.
		/// </param>
		/// <returns>
		///		The configured <see cref="HttpRequestMessage"/>.
		/// </returns>
		public static HttpRequestMessage BuildRequestMessage(this HttpRequest request, HttpMethod httpMethod, object bodyContent, string mediaType, Encoding encoding, Uri baseUri = null)
		{
			if (request == null)
				throw new ArgumentNullException(nameof(request));

			HttpContent httpContent = bodyContent as HttpContent;
			if (httpContent == null && bodyContent != null)
			{
				httpContent.Headers.ContentType = new MediaTypeHeaderValue(mediaType);

				IFormatterCollection formatters = request.CreateFormatterCollection();

				OutputFormatterContext writeContext = new OutputFormatterContext(bodyContent, bodyContent.GetType(), mediaType, encoding);
				IOutputFormatter writeFormatter = formatters.FindOutputFormatter(writeContext);
				if (writeFormatter == null)
					throw new HttpRequestException($"None of the supplied formatters can write data of type '{writeContext.DataType.FullName}' to media type '{writeContext.MediaType}'.");

				httpContent = new FormattedObjectContent(writeFormatter, writeContext);
			}

			return request.BuildRequestMessage(httpMethod, httpContent, baseUri);
		}

		/// <summary>
		///		Create a copy of the <see cref="HttpRequest"/>, adding the specified content formatter.
		/// </summary>
		/// <param name="request">
		///		The <see cref="HttpRequest"/>.
		/// </param>
		/// <param name="formatter">
		///		The content formatter to add.
		/// </param>
		/// <returns>
		///		The new <see cref="HttpRequest"/>.
		/// </returns>
		public static HttpRequest WithFormatter(this HttpRequest request, IFormatter formatter)
		{
			if (request == null)
				throw new ArgumentNullException(nameof(request));
<commit_msg>Fix NullReferenceException in FormatterRequestExtensions.BuildRequestMessage<commit_after>﻿using System;
using System.Collections.Immutable;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;

namespace HTTPlease
{
	using Formatters;

	/// <summary>
	///		Extension methods for working with <see cref="HttpRequest"/>s.
	/// </summary>
	public static class FormatterRequestExtensions
    {
		/// <summary>
		///		Create a copy of the <see cref="HttpRequest"/>, configuring it to accept the JSON ("application/json") media type.
		/// </summary>
		/// <param name="request">
		///		The <see cref="HttpRequest"/>.
		/// </param>
		/// <returns>
		///		The new <see cref="HttpRequest"/>.
		/// </returns>
		public static HttpRequest ExpectJson(this HttpRequest request)
		{
			if (request == null)
				throw new ArgumentNullException(nameof(request));

			return request.AcceptMediaType(WellKnownMediaTypes.Json);
		}

		/// <summary>
		///		Create a copy of the <see cref="HttpRequest"/>, configuring it to accept the JSON ("application/json") media type.
		/// </summary>
		/// <typeparam name="TContext">
		///		The type of object used as a context for resolving deferred parameters.
		/// </typeparam>
		/// <param name="request">
		///		The <see cref="HttpRequest"/>.
		/// </param>
		/// <returns>
		///		The new <see cref="HttpRequest"/>.
		/// </returns>
		public static HttpRequest<TContext> ExpectJson<TContext>(this HttpRequest<TContext> request)
		{
			if (request == null)
				throw new ArgumentNullException(nameof(request));

			return request.AcceptMediaType(WellKnownMediaTypes.Json);
		}

		/// <summary>
		///		Create a copy of the <see cref="HttpRequest"/>, configuring it to accept the XML ("application/json") media type.
		/// </summary>
		/// <param name="request">
		///		The <see cref="HttpRequest"/>.
		/// </param>
		/// <returns>
		///		The new <see cref="HttpRequest"/>.
		/// </returns>
		public static HttpRequest ExpectXml(this HttpRequest request)
		{
			if (request == null)
				throw new ArgumentNullException(nameof(request));

			return request.AcceptMediaType(WellKnownMediaTypes.Xml);
		}

		/// <summary>
		///		Create a copy of the <see cref="HttpRequest"/>, configuring it to accept the XML ("application/json") media type.
		/// </summary>
		/// <typeparam name="TContext">
		///		The type of object used as a context for resolving deferred parameters.
		/// </typeparam>
		/// <param name="request">
		///		The <see cref="HttpRequest"/>.
		/// </param>
		/// <returns>
		///		The new <see cref="HttpRequest"/>.
		/// </returns>
		public static HttpRequest<TContext> ExpectXml<TContext>(this HttpRequest<TContext> request)
		{
			if (request == null)
				throw new ArgumentNullException(nameof(request));

			return request.AcceptMediaType(WellKnownMediaTypes.Xml);
		}
		
		/// <summary>
		///		Build an HTTP request message, selecting an appropriate content formatter to serialise its body content.
		/// </summary>
		/// <param name="request">
		///		The <see cref="HttpRequest"/>.
		/// </param>
		/// <param name="httpMethod">
		///		The HTTP request method.
		/// </param>
		/// <param name="bodyContent">
		///		The request body content.
		/// </param>
		/// <param name="mediaType">
		///		The request body media type to use.
		/// </param>
		/// <param name="baseUri">
		///		An optional base URI to use if the request does not already have an absolute request URI.
		/// </param>
		/// <returns>
		///		The configured <see cref="HttpRequestMessage"/>.
		/// </returns>
		public static HttpRequestMessage BuildRequestMessage(this HttpRequest request, HttpMethod httpMethod, object bodyContent, string mediaType, Uri baseUri = null)
		{
			if (request == null)
				throw new ArgumentNullException(nameof(request));

			return request.BuildRequestMessage(httpMethod, bodyContent, mediaType, OutputEncoding.UTF8, baseUri);
		}

		/// <summary>
		///		Build an HTTP request message, selecting an appropriate content formatter to serialise its body content.
		/// </summary>
		/// <param name="request">
		///		The <see cref="HttpRequest"/>.
		/// </param>
		/// <param name="httpMethod">
		///		The HTTP request method.
		/// </param>
		/// <param name="bodyContent">
		///		The request body content.
		/// </param>
		/// <param name="mediaType">
		///		The request body media type to use.
		/// </param>
		/// <param name="encoding">
		///		The request body encoding to use.
		/// </param>
		/// <param name="baseUri">
		///		An optional base URI to use if the request does not already have an absolute request URI.
		/// </param>
		/// <returns>
		///		The configured <see cref="HttpRequestMessage"/>.
		/// </returns>
		public static HttpRequestMessage BuildRequestMessage(this HttpRequest request, HttpMethod httpMethod, object bodyContent, string mediaType, Encoding encoding, Uri baseUri = null)
		{
			if (request == null)
				throw new ArgumentNullException(nameof(request));

			HttpContent httpContent = bodyContent as HttpContent;
			if (httpContent == null && bodyContent != null)
			{
				IFormatterCollection formatters = request.CreateFormatterCollection();

				OutputFormatterContext writeContext = new OutputFormatterContext(bodyContent, bodyContent.GetType(), mediaType, encoding);
				IOutputFormatter writeFormatter = formatters.FindOutputFormatter(writeContext);
				if (writeFormatter == null)
					throw new HttpRequestException($"None of the supplied formatters can write data of type '{writeContext.DataType.FullName}' to media type '{writeContext.MediaType}'.");

				httpContent = new FormattedObjectContent(writeFormatter, writeContext)
				{
					Headers =
					{
						ContentType = new MediaTypeHeaderValue(mediaType)
					}
				};
			}

			return request.BuildRequestMessage(httpMethod, httpContent, baseUri);
		}

		/// <summary>
		///		Create a copy of the <see cref="HttpRequest"/>, adding the specified content formatter.
		/// </summary>
		/// <param name="request">
		///		The <see cref="HttpRequest"/>.
		/// </param>
		/// <param name="formatter">
		///		The content formatter to add.
		/// </param>
		/// <returns>
		///		The new <see cref="HttpRequest"/>.
		/// </returns>
		public static HttpRequest WithFormatter(this HttpRequest request, IFormatter formatter)
		{
			if (request == null)
				throw new ArgumentNullException(nameof(request));

{'fraction_non_alphanumeric': 0.15040392840171077, 'fraction_numerical': 0.0001584032947885316, 'mean_word_length': 3.1278195488721803, 'pattern_counts': {'":': 0, '<': 191, '<?xml version=': 0, '>': 191, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '412236', 'n_tokens_mistral': 4083, 'n_tokens_neox': 3617, 'n_words': 1084}