<commit_before>package io.github.daviddenton.fintrospect

import com.twitter.finagle.http.path.Path
import com.twitter.finagle.{Service, SimpleFilter}
import com.twitter.util.Future
import io.github.daviddenton.fintrospect.FintrospectModule._
import io.github.daviddenton.fintrospect.Routing.fromBinding
import io.github.daviddenton.fintrospect.parameters.Requirement._
import io.github.daviddenton.fintrospect.util.ArgoUtil.pretty
import io.github.daviddenton.fintrospect.util.ResponseBuilder._
import org.jboss.netty.handler.codec.http.HttpMethod.GET
import org.jboss.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST
import org.jboss.netty.handler.codec.http.{HttpMethod, HttpRequest, HttpResponse}

import scala.PartialFunction._

object FintrospectModule {

  private type Binding = PartialFunction[(HttpMethod, Path), Service[HttpRequest, HttpResponse]]

  val IDENTIFY_SVC_HEADER = "descriptionServiceId"

  /**
   * Combines many modules
   */
  def combine(modules: FintrospectModule*): Binding = modules.map(_.totalBinding).reduce(_.orElse(_))

  /**
   * Convert a Binding to a Finagle Service
   */
  def toService(binding: Binding): Service[HttpRequest, HttpResponse] = fromBinding(binding)

  /**
   * Create a module using the given base-path and description renderer.
   */
  def apply(basePath: Path, renderer: Renderer): FintrospectModule = {
    new FintrospectModule(basePath, renderer, Nil, empty[(HttpMethod, Path), Service[HttpRequest, HttpResponse]])
  }

  private case class ValidateParams(route: Route) extends SimpleFilter[HttpRequest, HttpResponse]() {
    override def apply(request: HttpRequest, service: Service[HttpRequest, HttpResponse]): Future[HttpResponse] = {
      val paramsAndParseResults = route.describedRoute.params.map(p => (p, p.parseFrom(request)))
      val withoutMissingOptionalParams = paramsAndParseResults.filterNot(pr => pr._1.requirement == Optional && pr._2.isEmpty)
      val missingOrFailed = withoutMissingOptionalParams.filterNot(pr => pr._2.isDefined && pr._2.get.isSuccess)
      val messages = missingOrFailed.flatMap(p => Some(s"${p._1.name} (${p._1.paramType.name})"))
      if (messages.isEmpty) service(request) else Error(BAD_REQUEST, "Missing required parameters: " + messages.mkString(","))
    }
  }

  private case class Identify(route: Route, basePath: Path) extends SimpleFilter[HttpRequest, HttpResponse]() {
    override def apply(request: HttpRequest, service: Service[HttpRequest, HttpResponse]): Future[HttpResponse] = {
      val url = if (route.describeFor(basePath).length == 0) "/" else route.describeFor(basePath)
      request.headers().set(IDENTIFY_SVC_HEADER, request.getMethod + "." + url)
      service(request)
    }
  }

  private case class RoutesContent(descriptionContent: String) extends Service[HttpRequest, HttpResponse]() {
    override def apply(request: HttpRequest): Future[HttpResponse] = Ok(descriptionContent)
  }

}<commit_msg>dave - beefed up 400 message to be nicerer<commit_after>package io.github.daviddenton.fintrospect

import com.twitter.finagle.http.path.Path
import com.twitter.finagle.{Service, SimpleFilter}
import com.twitter.util.Future
import io.github.daviddenton.fintrospect.FintrospectModule._
import io.github.daviddenton.fintrospect.Routing.fromBinding
import io.github.daviddenton.fintrospect.parameters.Requirement._
import io.github.daviddenton.fintrospect.util.ArgoUtil.{pretty, _}
import io.github.daviddenton.fintrospect.util.ResponseBuilder
import io.github.daviddenton.fintrospect.util.ResponseBuilder._
import org.jboss.netty.handler.codec.http.HttpMethod.GET
import org.jboss.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST
import org.jboss.netty.handler.codec.http.{HttpMethod, HttpRequest, HttpResponse}

import scala.PartialFunction._

object FintrospectModule {

  private type Binding = PartialFunction[(HttpMethod, Path), Service[HttpRequest, HttpResponse]]

  val IDENTIFY_SVC_HEADER = "descriptionServiceId"

  /**
   * Combines many modules
   */
  def combine(modules: FintrospectModule*): Binding = modules.map(_.totalBinding).reduce(_.orElse(_))

  /**
   * Convert a Binding to a Finagle Service
   */
  def toService(binding: Binding): Service[HttpRequest, HttpResponse] = fromBinding(binding)

  /**
   * Create a module using the given base-path and description renderer.
   */
  def apply(basePath: Path, renderer: Renderer): FintrospectModule = {
    new FintrospectModule(basePath, renderer, Nil, empty[(HttpMethod, Path), Service[HttpRequest, HttpResponse]])
  }

  private case class ValidateParams(route: Route) extends SimpleFilter[HttpRequest, HttpResponse]() {
    override def apply(request: HttpRequest, service: Service[HttpRequest, HttpResponse]): Future[HttpResponse] = {
      val paramsAndParseResults = route.describedRoute.params.map(p => (p, p.parseFrom(request)))
      val withoutMissingOptionalParams = paramsAndParseResults.filterNot(pr => pr._1.requirement == Optional && pr._2.isEmpty)
      val missingOrFailed = withoutMissingOptionalParams.filterNot(pr => pr._2.isDefined && pr._2.get.isSuccess)
      if (missingOrFailed.isEmpty) service(request)
      else {
        val messages = missingOrFailed.map(p => obj(
          "name" -> string(p._1.name),
          "type" -> string(p._1.where),
          "datatype" -> string(p._1.paramType.name),
          "required" -> boolean(p._1.requirement.required)
        ))
        ResponseBuilder()
          .withCode(BAD_REQUEST)
          .withContent(obj("message" -> string("Missing/invalid parameters"), "params" -> array(messages)))
          .toFuture
      }
    }
  }

  private case class Identify(route: Route, basePath: Path) extends SimpleFilter[HttpRequest, HttpResponse]() {
    override def apply(request: HttpRequest, service: Service[HttpRequest, HttpResponse]): Future[HttpResponse] = {
      val url = if (route.describeFor(basePath).length == 0) "/" else route.describeFor(basePath)
      request.headers().set(IDENTIFY_SVC_HEADER, request.getMethod + "." + url)
      service(request)
    }
  }

  private case class RoutesContent(descriptionContent: String) extends Service[HttpRequest, HttpResponse]() {
    override def apply(request: HttpRequest): Future[HttpResponse] = Ok(descriptionContent)
  }

}
{'fraction_non_alphanumeric': 0.11577770680293836, 'fraction_numerical': 0.0030341743851804537, 'mean_word_length': 4.826046511627907, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 17, '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': '2498947', 'n_tokens_mistral': 1902, 'n_tokens_neox': 1827, 'n_words': 369}