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

io.gatling.http.engine.response.FollowUpProcessor.scala Maven / Gradle / Ivy

There is a newer version: 3.13.1
Show newest version
/*
 * Copyright 2011-2023 GatlingCorp (https://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.engine.response

import java.nio.charset.Charset

import scala.jdk.CollectionConverters._

import io.gatling.core.session.Session
import io.gatling.http.auth.DigestAuthSupport
import io.gatling.http.client.{ Request, RequestBuilder }
import io.gatling.http.client.realm.DigestRealm
import io.gatling.http.client.uri.Uri
import io.gatling.http.cookie.CookieSupport
import io.gatling.http.protocol.HttpProtocol

import io.netty.handler.codec.http.{ HttpHeaderNames, HttpResponseStatus }
import io.netty.handler.codec.http.HttpMethod._
import io.netty.handler.codec.http.HttpResponseStatus._

object FollowUpProcessor {
  def redirectRequest(
      requestName: String,
      originalRequest: Request,
      session: Session,
      responseStatus: HttpResponseStatus,
      httpProtocol: HttpProtocol,
      redirectUri: Uri,
      defaultCharset: Charset,
      redirectCount: Int
  ): Request = {
    val originalMethod = originalRequest.getMethod

    val switchToGet =
      originalMethod != GET && originalMethod != HEAD && originalMethod != OPTIONS && (responseStatus == HttpResponseStatus.MOVED_PERMANENTLY || responseStatus == SEE_OTHER || (responseStatus == FOUND && !httpProtocol.responsePart.strict302Handling))
    val keepBody =
      responseStatus == TEMPORARY_REDIRECT || responseStatus == PERMANENT_REDIRECT || (responseStatus == FOUND && httpProtocol.responsePart.strict302Handling)

    val newHeaders = originalRequest.getHeaders
      .remove(HttpHeaderNames.HOST)
      .remove(HttpHeaderNames.CONTENT_LENGTH)
      .remove(HttpHeaderNames.COOKIE)
      .remove(HttpHeaderNames.ORIGIN)

    if (originalRequest.getRealm != null) {
      // remove Authorization header if there's a realm as it will be recomputed
      newHeaders.remove(HttpHeaderNames.AUTHORIZATION)
    }

    if (!keepBody) {
      newHeaders.remove(HttpHeaderNames.CONTENT_TYPE)
    }

    val requestBuilder =
      new RequestBuilder(
        httpProtocol.responsePart.redirectNamingStrategy(redirectUri, requestName, redirectCount),
        if (switchToGet) GET else originalMethod,
        redirectUri,
        originalRequest.getNameResolver
      )
        .setHeaders(newHeaders)
        .setHttp2Enabled(originalRequest.isHttp2Enabled)
        .setLocalIpV4Address(originalRequest.getLocalIpV4Address)
        .setLocalIpV6Address(originalRequest.getLocalIpV6Address)
        .setRealm(originalRequest.getRealm)
        .setRequestTimeout(originalRequest.getRequestTimeout)
        .setDefaultCharset(defaultCharset)

    if (originalRequest.getUri.isSameBase(redirectUri)) {
      // we can only assume the virtual host is still valid if the baseUrl is the same
      requestBuilder.setVirtualHost(originalRequest.getVirtualHost)
    }

    if (!httpProtocol.proxyPart.proxyExceptions.contains(redirectUri.getHost)) {
      val originalRequestProxy = if (originalRequest.getUri.getHost == redirectUri.getHost) Option(originalRequest.getProxyServer) else None
      val protocolProxy = httpProtocol.proxyPart.proxy
      originalRequestProxy.orElse(protocolProxy).foreach(requestBuilder.setProxyServer)
    }

    if (keepBody) {
      Option(originalRequest.getBody).foreach(body => requestBuilder.setBodyBuilder(body.newBuilder))
    }

    val cookies = CookieSupport.getStoredCookies(session, redirectUri)
    if (cookies.nonEmpty) {
      requestBuilder.setCookies(cookies.asJava)
    }

    requestBuilder.build
  }

  def digestChallengeRequest(
      requestName: String,
      originalRequest: Request,
      session: Session,
      digestRealm: DigestRealm,
      defaultCharset: Charset
  ): Request = {
    val newHeaders = originalRequest.getHeaders
      .remove(HttpHeaderNames.HOST)
      .remove(HttpHeaderNames.CONTENT_LENGTH)
      .remove(HttpHeaderNames.COOKIE)
      .remove(HttpHeaderNames.ORIGIN)
      // remove Authorization header if there's a realm as it will be recomputed
      .remove(HttpHeaderNames.AUTHORIZATION)

    val requestBuilder =
      new RequestBuilder(
        requestName,
        originalRequest.getMethod,
        originalRequest.getUri,
        originalRequest.getNameResolver
      )
        .setHeaders(newHeaders)
        .setHttp2Enabled(originalRequest.isHttp2Enabled)
        .setLocalIpV4Address(originalRequest.getLocalIpV4Address)
        .setLocalIpV6Address(originalRequest.getLocalIpV6Address)
        .setRealm(originalRequest.getRealm)
        .setRequestTimeout(originalRequest.getRequestTimeout)
        .setDefaultCharset(defaultCharset)
        .setVirtualHost(originalRequest.getVirtualHost)
        .setRealm(DigestAuthSupport.realmWithAuthorizationGen(session, digestRealm))

    Option(originalRequest.getBody).foreach(body => requestBuilder.setBodyBuilder(body.newBuilder))

    val cookies = CookieSupport.getStoredCookies(session, originalRequest.getUri)
    if (cookies.nonEmpty) {
      requestBuilder.setCookies(cookies.asJava)
    }

    requestBuilder.build
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy