<commit_before>package io.buoyant.router.http

import com.twitter.finagle._
import com.twitter.finagle.transport.Transport
import com.twitter.util.Future
import java.security.MessageDigest
import java.security.cert.X509Certificate
import javax.xml.bind.DatatypeConverter.printHexBinary
import scala.collection.mutable

class ForwardClientCertFilter[Req, H: HeadersLike, Rep](implicit requestLike: RequestLike[Req, H]) extends SimpleFilter[Req, Rep] {

  val GeneralNameTypeUri = 6
  val GeneralNameTypeDns = 2

  val digest: MessageDigest = MessageDigest.getInstance("SHA-256")

  def apply(req: Req, svc: Service[Req, Rep]): Future[Rep] = {
    Transport.peerCertificate.foreach(clientCert => {
      val clientCertHeader = new mutable.StringBuilder(128)

      clientCertHeader ++= s"Hash=${printHexBinary(digest.digest(clientCert.getEncoded))}"

      clientCert match {
        case x509ClientCert: X509Certificate =><commit_msg>Fixes concurrency issue in ForwardClientCertFilter (#1937)<commit_after>package io.buoyant.router.http

import com.twitter.finagle._
import com.twitter.finagle.transport.Transport
import com.twitter.util.Future
import java.security.MessageDigest
import java.security.cert.X509Certificate
import javax.xml.bind.DatatypeConverter.printHexBinary
import scala.collection.mutable

class ForwardClientCertFilter[Req, H: HeadersLike, Rep](implicit requestLike: RequestLike[Req, H]) extends SimpleFilter[Req, Rep] {

  val GeneralNameTypeUri = 6
  val GeneralNameTypeDns = 2

  // MessageDigest is not thread-safe, so using ThreadLocal to avoid concurrency issues.
  val digest = ThreadLocal.withInitial[MessageDigest](() => MessageDigest.getInstance("SHA-256"));

  def apply(req: Req, svc: Service[Req, Rep]): Future[Rep] = {
    Transport.peerCertificate.foreach(clientCert => {
      val clientCertHeader = new mutable.StringBuilder(128)

      clientCertHeader ++= s"Hash=${printHexBinary(digest.get().digest(clientCert.getEncoded))}"

      clientCert match {
        case x509ClientCert: X509Certificate =>
{'fraction_non_alphanumeric': 0.10206084396467124, 'fraction_numerical': 0.018645731108930325, 'mean_word_length': 5.514376996805112, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, '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': '2374679', 'n_tokens_mistral': 628, 'n_tokens_neox': 581, 'n_words': 128}