All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.gatling.http.action.sync.HttpTx.scala Maven / Gradle / Ivy

There is a newer version: 3.13.1
Show newest version
/**
 * Copyright 2011-2016 GatlingCorp (http://gatling.io)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.gatling.http.action.sync

import scala.concurrent.duration._

import io.gatling.commons.stats.OK
import io.gatling.commons.util.ClockSingleton._
import io.gatling.core.action.Action
import io.gatling.core.session.Session
import io.gatling.core.util.NameGen
import io.gatling.http.ahc.{ AsyncHandler, HttpEngine }
import io.gatling.http.cache.{ ContentCacheEntry, HttpCaches }
import io.gatling.http.fetch.RegularResourceFetched
import io.gatling.http.request.HttpRequest
import io.gatling.http.response._

import akka.actor.{ ActorRef, ActorRefFactory, Props }
import com.typesafe.scalalogging.StrictLogging
import org.asynchttpclient.{ AsyncHttpClient, Request }

object HttpTx extends NameGen with StrictLogging {

  def silent(request: HttpRequest, root: Boolean): Boolean = {

    val requestPart = request.config.httpComponents.httpProtocol.requestPart

      def silentBecauseProtocolSilentURI: Boolean = requestPart.silentURI match {
        case Some(silentUri) => silentUri.matcher(request.ahcRequest.getUrl).matches
        case None            => false
      }

      def silentBecauseProtocolSilentResources = !root && requestPart.silentResources

    request.config.silent match {
      case None         => silentBecauseProtocolSilentURI || silentBecauseProtocolSilentResources
      case Some(silent) => silent
    }
  }

  private def startWithCache(origTx: HttpTx, actorRefFactory: ActorRefFactory, httpEngine: HttpEngine, httpCaches: HttpCaches)(f: HttpTx => Unit): Unit = {
    val tx = httpCaches.applyPermanentRedirect(origTx)
    val ahcRequest = tx.request.ahcRequest
    val uri = ahcRequest.getUri

    httpCaches.contentCacheEntry(tx.session, ahcRequest) match {

      case None | Some(ContentCacheEntry(None, _, _)) =>
        f(tx)

      case Some(ContentCacheEntry(Some(expire), _, _)) if unpreciseNowMillis > expire =>
        val newTx = tx.copy(session = httpCaches.clearContentCache(tx.session, ahcRequest))
        f(newTx)

      case _ =>
        httpEngine.resourceFetcherActorForCachedPage(uri, tx) match {
          case Some(resourceFetcherActor) =>
            logger.info(s"Fetching resources of cached page request=${tx.request.requestName} uri=$uri: scenario=${tx.session.scenario}, userId=${tx.session.userId}")
            actorRefFactory.actorOf(Props(resourceFetcherActor()), genName("resourceFetcher"))

          case None =>
            logger.info(s"Skipping cached request=${tx.request.requestName} uri=$uri: scenario=${tx.session.scenario}, userId=${tx.session.userId}")
            tx.resourceFetcher match {
              case None                  => tx.next ! tx.session
              case Some(resourceFetcher) => resourceFetcher ! RegularResourceFetched(uri, OK, Session.Identity, tx.silent)
            }
        }
    }
  }

  private def executeRequest(client: AsyncHttpClient, ahcRequest: Request, handler: AsyncHandler): Unit =
    if (!client.isClosed) {
      handler.start()
      client.executeRequest(ahcRequest, handler)
    }

  def start(origTx: HttpTx)(implicit actorRefFactory: ActorRefFactory): Unit = {

    import origTx.request.config.httpComponents._

    startWithCache(origTx, actorRefFactory, httpEngine, httpCaches) { tx =>

      logger.debug(s"Sending request=${tx.request.requestName} uri=${tx.request.ahcRequest.getUri}: scenario=${tx.session.scenario}, userId=${tx.session.userId}")

      httpEngine.httpClient(tx.session, httpProtocol) match {
        case (newSession, client) =>
          val newTx = tx.copy(session = newSession)
          val ahcRequest = newTx.request.ahcRequest
          val handler = new AsyncHandler(newTx, responseProcessor)

          if (tx.request.config.throttled)
            origTx.request.config.coreComponents.throttler.throttle(tx.session.scenario, () => executeRequest(client, ahcRequest, handler))
          else
            executeRequest(client, ahcRequest, handler)

        case _ => // client has been shutdown, ignore
      }
    }
  }
}

case class HttpTx(
    session:                Session,
    request:                HttpRequest,
    responseBuilderFactory: ResponseBuilderFactory,
    next:                   Action,
    resourceFetcher:        Option[ActorRef]       = None,
    redirectCount:          Int                    = 0,
    update:                 Session => Session     = Session.Identity
) {
  lazy val silent: Boolean = HttpTx.silent(request, resourceFetcher.isEmpty)

  lazy val fullRequestName =
    if (redirectCount > 0)
      s"${request.requestName} Redirect ${redirectCount}"
    else
      request.requestName
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy