<commit_before>package com.softwaremill.sttp

import java.io.InputStream
import java.nio.ByteBuffer
import java.util.Base64

import com.softwaremill.sttp.internal._

import scala.collection.immutable.Seq
import scala.concurrent.duration.Duration
import scala.language.higherKinds

/**
  * @param response What's the target type to which the response body should
  *                 be read. Needs to be specified upfront so that the response
  *                 is always consumed and hence there are no requirements on
  *                 client code to consume it. An exception to this are
  *                 streaming responses, which need to fully consumed by the
  *                 client if such a response type is requested.
  * @param tags Request-specific tags which can be used by backends for
  *             logging, metrics, etc. Not used by default.
  * @tparam U Specifies if the method & uri are specified. By default can be
  *           either:
  *           * `Empty`, which is a type constructor which always resolves to
  *           `None`. This type of request is aliased to `PartialRequest`:
  *           there's no method and uri specified, and the request cannot be
  *           sent.
  *           * `Id`, which is an identity type constructor. This type of
  *           request is aliased to `Request`: the method and uri are
  *           specified, and the request can be sent.
  */
case class RequestT[U[_], T, +S](
    method: U[Method],
    uri: U[Uri],
    body: RequestBody[S],
    headers: Seq[(String, String)],
    response: ResponseAs[T, S],
    options: RequestOptions,
    tags: Map[String, Any]
) extends RequestTExtensions[U, T, S] {
  def get(uri: Uri): Request[T, S] =
    this.copy[Id, T, S](uri = uri, method = Method.GET)
  def head(uri: Uri): Request[T, S] =
    this.copy[Id, T, S](uri = uri, method = Method.HEAD)
  def post(uri: Uri): Request[T, S] =
    this.copy[Id, T, S](uri = uri, method = Method.POST)
  def put(uri: Uri): Request[T, S] =
    this.copy[Id, T, S](uri = uri, method = Method.PUT)
  def delete(uri: Uri): Request[T, S] =
    this.copy[Id, T, S](uri = uri, method = Method.DELETE)
  def options(uri: Uri): Request[T, S] =
    this.copy[Id, T, S](uri = uri, method = Method.OPTIONS)
  def patch(uri: Uri): Request[T, S] =
    this.copy[Id, T, S](uri = uri, method = Method.PATCH)

  def contentType(ct: String): RequestT[U, T, S] =
    header(HeaderNames.ContentType, ct, replaceExisting = true)
  def contentType(ct: String, encoding: String): RequestT[U, T, S] =
    header(HeaderNames.ContentType, contentTypeWithEncoding(ct, encoding), replaceExisting = true)
  def contentLength(l: Long): RequestT[U, T, S] =
    header(HeaderNames.ContentLength, l.toString, replaceExisting = true)
  def header(k: String, v: String, replaceExisting: Boolean = false): RequestT[U, T, S] = {
    val current =
      if (replaceExisting)
        headers.filterNot(_._1.equalsIgnoreCase(k))
      else headers
    this.copy(headers = current :+ (k -> v))
  }
  def headers(hs: Map[String, String]): RequestT[U, T, S] =
    headers(hs.toSeq: _*)
  def headers(hs: (String, String)*): RequestT[U, T, S] =
    this.copy(headers = headers ++ hs)
  def auth: SpecifyAuthScheme[U, T, S] =
    new SpecifyAuthScheme[U, T, S](HeaderNames.Authorization, this)
  def proxyAuth: SpecifyAuthScheme[U, T, S] =
    new SpecifyAuthScheme[U, T, S](HeaderNames.ProxyAuthorization, this)
  def acceptEncoding(encoding: String): RequestT[U, T, S] =
    header(HeaderNames.AcceptEncoding, encoding)

  /**
    * Uses the `utf-8` encoding.
    *
    * If content type is not yet specified, will be set to `text/plain`
    * with `utf-8` encoding.
    *<commit_msg>Add support for variable request method<commit_after>package com.softwaremill.sttp

import java.io.InputStream
import java.nio.ByteBuffer
import java.util.Base64

import com.softwaremill.sttp.internal._

import scala.collection.immutable.Seq
import scala.concurrent.duration.Duration
import scala.language.higherKinds

/**
  * @param response What's the target type to which the response body should
  *                 be read. Needs to be specified upfront so that the response
  *                 is always consumed and hence there are no requirements on
  *                 client code to consume it. An exception to this are
  *                 streaming responses, which need to fully consumed by the
  *                 client if such a response type is requested.
  * @param tags Request-specific tags which can be used by backends for
  *             logging, metrics, etc. Not used by default.
  * @tparam U Specifies if the method & uri are specified. By default can be
  *           either:
  *           * `Empty`, which is a type constructor which always resolves to
  *           `None`. This type of request is aliased to `PartialRequest`:
  *           there's no method and uri specified, and the request cannot be
  *           sent.
  *           * `Id`, which is an identity type constructor. This type of
  *           request is aliased to `Request`: the method and uri are
  *           specified, and the request can be sent.
  */
case class RequestT[U[_], T, +S](
    method: U[Method],
    uri: U[Uri],
    body: RequestBody[S],
    headers: Seq[(String, String)],
    response: ResponseAs[T, S],
    options: RequestOptions,
    tags: Map[String, Any]
) extends RequestTExtensions[U, T, S] {
  def get(uri: Uri): Request[T, S] =
    this.copy[Id, T, S](uri = uri, method = Method.GET)
  def head(uri: Uri): Request[T, S] =
    this.copy[Id, T, S](uri = uri, method = Method.HEAD)
  def post(uri: Uri): Request[T, S] =
    this.copy[Id, T, S](uri = uri, method = Method.POST)
  def put(uri: Uri): Request[T, S] =
    this.copy[Id, T, S](uri = uri, method = Method.PUT)
  def delete(uri: Uri): Request[T, S] =
    this.copy[Id, T, S](uri = uri, method = Method.DELETE)
  def options(uri: Uri): Request[T, S] =
    this.copy[Id, T, S](uri = uri, method = Method.OPTIONS)
  def patch(uri: Uri): Request[T, S] =
    this.copy[Id, T, S](uri = uri, method = Method.PATCH)
  def method(method: Method, uri: Uri): Request[T, S] =
    this.copy[Id, T, S](uri = uri, method = method)

  def contentType(ct: String): RequestT[U, T, S] =
    header(HeaderNames.ContentType, ct, replaceExisting = true)
  def contentType(ct: String, encoding: String): RequestT[U, T, S] =
    header(HeaderNames.ContentType, contentTypeWithEncoding(ct, encoding), replaceExisting = true)
  def contentLength(l: Long): RequestT[U, T, S] =
    header(HeaderNames.ContentLength, l.toString, replaceExisting = true)
  def header(k: String, v: String, replaceExisting: Boolean = false): RequestT[U, T, S] = {
    val current =
      if (replaceExisting)
        headers.filterNot(_._1.equalsIgnoreCase(k))
      else headers
    this.copy(headers = current :+ (k -> v))
  }
  def headers(hs: Map[String, String]): RequestT[U, T, S] =
    headers(hs.toSeq: _*)
  def headers(hs: (String, String)*): RequestT[U, T, S] =
    this.copy(headers = headers ++ hs)
  def auth: SpecifyAuthScheme[U, T, S] =
    new SpecifyAuthScheme[U, T, S](HeaderNames.Authorization, this)
  def proxyAuth: SpecifyAuthScheme[U, T, S] =
    new SpecifyAuthScheme[U, T, S](HeaderNames.ProxyAuthorization, this)
  def acceptEncoding(encoding: String): RequestT[U, T, S] =
    header(HeaderNames.AcceptEncoding, encoding)

  /**
    * Uses the `utf-8` encoding.
    *
    * If content type is not yet specified, will be set to `text/plain`
    * with `utf-8` encoding.
    *
{'fraction_non_alphanumeric': 0.12065765049058605, 'fraction_numerical': 0.0013259082471492973, 'mean_word_length': 3.0619278406031234, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, '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': '6439106', 'n_tokens_mistral': 2399, 'n_tokens_neox': 2361, 'n_words': 798}