![JAR search and dependency download from the Maven repository](/logo.png)
com.xceptance.xlt.nocoding.command.action.request.Request Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xlt-nocoding Show documentation
Show all versions of xlt-nocoding Show documentation
A library based on XLT to run Web test cases that are written in either YAML or CSV format.
The newest version!
/*
* Copyright (c) 2013-2023 Xceptance Software Technologies GmbH
*
* 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 com.xceptance.xlt.nocoding.command.action.request;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.htmlunit.FailingHttpStatusCodeException;
import org.htmlunit.HttpMethod;
import org.htmlunit.WebRequest;
import org.htmlunit.WebResponse;
import org.htmlunit.util.NameValuePair;
import org.htmlunit.util.UrlUtils;
import org.openqa.selenium.InvalidArgumentException;
import com.xceptance.xlt.engine.XltWebClient;
import com.xceptance.xlt.nocoding.command.action.AbstractActionSubItem;
import com.xceptance.xlt.nocoding.util.Constants;
import com.xceptance.xlt.nocoding.util.RecentKeyTreeMap;
import com.xceptance.xlt.nocoding.util.context.Context;
import com.xceptance.xlt.nocoding.util.resolver.VariableResolver;
import com.xceptance.xlt.nocoding.util.storage.DataStorage;
/**
* Describes a HTTP Request, that gets transformed to a {@link WebRequest} and then sent via the {@link XltWebClient}.
*
* @author ckeiner
*/
public class Request extends AbstractActionSubItem
{
/**
* The URL as String
*/
private String url;
/**
* The HttpMethod for the WebRequest. Defaults to "GET"
*/
private String httpMethod;
/**
* Sets the WebRequest as Xhr request. Defaults to "false"
*/
private String xhr;
/**
* Defines if the parameters are encoded. Defaults to "false"
*/
private String encodeParameters;
/**
* The list of the parameters
*/
private List parameters;
/**
* The list of cookies
*/
private Map cookies;
/**
* A map that defines the headers
*/
private Map headers;
/**
* The body of the {@link WebRequest}
*/
private String body;
/**
* Defines if the body is encoded. Defaults to "false"
*/
private String encodeBody;
/**
* Creates an instance of {@link Request}, that sets {@link #url} to null.
*/
public Request()
{
this(null);
}
/**
* Creates an instance of {@link Request}, that sets {@link #url}.
*
* @param url
* The URL as {@link String}.
*/
public Request(final String url)
{
this.url = url;
parameters = new ArrayList<>();
cookies = new LinkedHashMap<>();
headers = new RecentKeyTreeMap();
}
public String getUrl()
{
return url;
}
public void setUrl(final String url)
{
this.url = url;
}
public String getHttpMethod()
{
return httpMethod;
}
public void setHttpMethod(final String httpMethod)
{
this.httpMethod = httpMethod;
}
public String getXhr()
{
return xhr;
}
public void setXhr(final String xhr)
{
this.xhr = xhr;
}
public String getEncodeParameters()
{
return encodeParameters;
}
public void setEncodeParameters(final String encodeParameters)
{
this.encodeParameters = encodeParameters;
}
public List getParameters()
{
return parameters;
}
public void setParameters(final List parameters)
{
this.parameters = parameters;
}
public Map getCookies()
{
return cookies;
}
public void setCookies(final Map cookies)
{
this.cookies = cookies;
}
public Map getHeaders()
{
return headers;
}
/**
* Create a {@link RecentKeyTreeMap} out of the specified map, so headers are always treated case insensitive.
*
* @param headers
* The map with the headers
*/
public void setHeaders(final Map headers)
{
if (headers != null && !headers.isEmpty())
{
this.headers = new RecentKeyTreeMap();
this.headers.putAll(headers);
}
}
public String getBody()
{
return body;
}
public void setBody(final String body)
{
this.body = body;
}
public String getEncodeBody()
{
return encodeBody;
}
public void setEncodeBody(final String encodeBody)
{
this.encodeBody = encodeBody;
}
/**
* Fills in the default values for all unspecified attributes.
* Note, that default headers and cookies are already set at the WebClient..
*
* @param context
* The {@link Context} with the {@link DataStorage}
*/
public void fillDefaultData(final Context> context)
{
// Set default URL if it isn't specified
if (getUrl() == null || getUrl().isEmpty())
{
setUrl(context.getDefaultItems().get(Constants.URL));
}
// Set default HttpMethod if it isn't specified
if (getHttpMethod() == null)
{
setHttpMethod(context.getDefaultItems().get(Constants.METHOD));
}
// Set default Xhr if it isn't specified
if (getXhr() == null)
{
setXhr(context.getDefaultItems().get(Constants.XHR));
}
// Set default encodeParameters if it isn't specified
if (getEncodeParameters() == null)
{
setEncodeParameters(context.getDefaultItems().get(Constants.ENCODEPARAMETERS));
}
/*
* Set default parameters
*/
if (context.getDefaultParameters() != null && !context.getDefaultParameters().getItems().isEmpty())
{
// Get default parameters
final List defaultParameters = context.getDefaultParameters().getItems();
// Overwrite the default values with the current ones or add the current ones
if (getParameters() != null)
{
for (final NameValuePair defaultParameter : defaultParameters)
{
if (!getParameters().contains(defaultParameter))
{
getParameters().add(defaultParameter);
}
}
}
}
// Set default body if it isn't specified
if (getBody() == null)
{
setBody(context.getDefaultItems().get(Constants.BODY));
}
// Set default encodeBody if it isn't specified
if (getEncodeBody() == null)
{
setEncodeBody(context.getDefaultItems().get(Constants.ENCODEBODY));
}
}
/**
* Tries to resolve all variables of non-null attributes
*
* @param context
* The {@link Context} with the {@link VariableResolver}
* @throws InvalidArgumentException
*/
void resolveValues(final Context> context) throws InvalidArgumentException
{
String resolvedValue;
// Resolve Url
resolvedValue = context.resolveString(getUrl());
setUrl(resolvedValue);
// Resolve Httpmethod
resolvedValue = context.resolveString(getHttpMethod());
setHttpMethod(resolvedValue);
// Resolve Xhr if it isn't null
if (getXhr() != null)
{
resolvedValue = context.resolveString(getXhr());
setXhr(resolvedValue);
}
// Resolve encodeParameters if it isn't null
if (getEncodeParameters() != null)
{
resolvedValue = context.resolveString(getEncodeParameters());
setEncodeParameters(resolvedValue);
}
// Resolve each parameter in parameters if is neither null nor empty
if (getParameters() != null && !getParameters().isEmpty())
{
final List resolvedParameters = new ArrayList<>();
String resolvedParameterName, resolvedParameterValue;
// Iterate over the list
for (final NameValuePair parameter : parameters)
{
// Resolve the name of the parameter
resolvedParameterName = context.resolveString(parameter.getName());
// Resolve the value of the parameter
resolvedParameterValue = context.resolveString(parameter.getValue());
// Add the resolved name and resolved value to the new parameter list
resolvedParameters.add(new NameValuePair(resolvedParameterName, resolvedParameterValue));
}
// Reassign the parameter list to the resolved parameter list
setParameters(resolvedParameters);
}
// Resolve each header in headers if is neither null nor empty
if (getHeaders() != null && !getHeaders().isEmpty())
{
// Create a new map
final Map resolvedHeaders = new HashMap<>();
// And insert the resolved key and value of the old map into the new one
getHeaders().forEach((final String key, final String value) -> {
resolvedHeaders.put(context.resolveString(key), context.resolveString(value));
});
// Reassign the header to its resolved values
setHeaders(resolvedHeaders);
}
// Resolve each cookie in cookies if is neither null nor empty
if (getCookies() != null && !getCookies().isEmpty())
{
// Create a new map
final Map resolvedCookies = new HashMap<>();
// And insert the resolved key and value of the old map into the new one
getCookies().forEach((final String key, final String value) -> {
resolvedCookies.put(context.resolveString(key), context.resolveString(value));
});
// Reassign the cookies to its resolved values
setCookies(resolvedCookies);
}
// Resolve encodeBody if it isn't null
if (getEncodeBody() != null)
{
resolvedValue = context.resolveString(getEncodeBody());
setEncodeBody(resolvedValue);
}
// Resolve Body if it isn't null
if (getBody() != null)
{
resolvedValue = context.resolveString(getBody());
setBody(resolvedValue);
}
}
/**
* Builds the {@link WebRequest} with the given {@link Context} and sends the WebRequest
. Finally, it
* stores the corresponding {@link WebResponse} with {@link Context#setWebResponse(WebResponse)}.
*
* @param context
* The {@link Context} with the {@link DataStorage}, {@link VariableResolver} and {@link XltWebClient}
* @throws IOException
* if building of sending the WebRequest
fails
* @throws FailingHttpStatusCodeException
*/
@Override
public void execute(final Context> context) throws FailingHttpStatusCodeException, IOException
{
// Fill in the default data if the attribute is not specified
fillDefaultData(context);
// Then resolve all variables
resolveValues(context);
// Throw an error if the url is null or empty
if (url == null || url.isEmpty())
{
throw new InvalidArgumentException("Url is empty. Please set a default url or specify a url.");
}
// Build the WebRequest
final WebRequest webRequest = buildWebRequest(context);
// Check that the webRequest isn't null
if (webRequest != null)
{
// Load the webResponse
context.loadWebResponse(webRequest);
}
}
/**
* Sets the cookies at the web client
*
* @param context
* The current {@link Context}
* @throws MalformedURLException
* If {@link #url} of this request cannot be transformed to a URL
*/
private void setCookiesAtWebClient(final Context> context) throws MalformedURLException
{
if (getCookies() != null && !getCookies().isEmpty())
{
final URL url = new URL(getUrl());
cookies.forEach((key, value) -> {
context.getWebClient().addCookie(key + "=" + value, url, this);
});
}
}
/**
* Builds the {@link WebRequest} that is specified by this object
*
* @param context
* The current {@link Context}
* @return The WebRequest
that is specified by this object
* @throws MalformedURLException
* @throws UnsupportedEncodingException
*/
WebRequest buildWebRequest(final Context> context) throws MalformedURLException, UnsupportedEncodingException
{
// Create a URL object
final URL url = new URL(this.url);
// Create a WebRequest
final WebRequest webRequest = new WebRequest(url, HttpMethod.valueOf(getHttpMethod()));
// Set headers if they aren't null or empty
if (getHeaders() != null || !getHeaders().isEmpty())
{
final RecentKeyTreeMap headerExchange = new RecentKeyTreeMap();
headerExchange.putAll(webRequest.getAdditionalHeaders());
headerExchange.putAll(headers);
webRequest.setAdditionalHeaders(headerExchange);
}
// Set Xhr if it is specified and can be converted to a boolean
if (getXhr() != null && Boolean.valueOf(getXhr()))
{
webRequest.setXHR();
// Set XHR headers
webRequest.getAdditionalHeaders().put("X-Requested-With", "XMLHttpRequest");
// If there was a previous WebResponse, set the Url als Referer
if (context.getWebResponse() != null)
{
// Get the url of the old webResponse
webRequest.getAdditionalHeaders().put("Referer", context.getWebResponse().getWebRequest().getUrl().toString());
}
}
// Set parameters if they aren't null or empty
if (getParameters() != null && !getParameters().isEmpty())
{
// Decode parameters if they are specified and set to "true"
if (getEncodeParameters() != null && !Boolean.valueOf(getEncodeParameters()))
{
decodeParameters();
}
handleParameters(webRequest, parameters);
}
// Set Body if specified and no parameters are set
if (getBody() != null && !getBody().isEmpty() && (getParameters() == null || getParameters().isEmpty()))
{
// Decode Body if they are specified and set to "true"
if (getEncodeBody() != null && !Boolean.valueOf(getEncodeBody()))
{
decodeBody();
}
webRequest.setRequestBody(body);
}
// Sets the cookies at the web client
setCookiesAtWebClient(context);
// Return the webRequest
return webRequest;
}
/**
* Decodes the body.
*
* @throws UnsupportedEncodingException
*/
private void decodeBody() throws UnsupportedEncodingException
{
setBody(URLDecoder.decode(getBody(), "UTF-8"));
}
/**
* Decodes each parameter in {@link #parameters}.
*
* @throws UnsupportedEncodingException
*/
private void decodeParameters() throws UnsupportedEncodingException
{
final List decodedParameters = new ArrayList<>();
for (final NameValuePair parameter : getParameters())
{
final String decodedName = parameter.getName() != null ? URLDecoder.decode(parameter.getName(), "UTF-8") : null;
final String decodedValue = parameter.getValue() != null ? URLDecoder.decode(parameter.getValue(), "UTF-8") : null;
final NameValuePair decodedParameter = new NameValuePair(decodedName, decodedValue);
decodedParameters.add(decodedParameter);
}
setParameters(decodedParameters);
}
/**
* Provides the url and method used
*/
public String toSimpleDebugString()
{
final String output = "Request-URL: " + url + " with Method." + httpMethod;
return output;
}
private void handleParameters(final WebRequest webRequest, final List parameters) throws MalformedURLException
{
final HttpMethod method = webRequest.getHttpMethod();
if (parameters != null && !parameters.isEmpty())
{
// POST as well as PUT and PATCH
if (method.equals(HttpMethod.POST) || method.equals(HttpMethod.PUT) || method.equals(HttpMethod.PATCH))
{
webRequest.setRequestParameters(parameters);
}
else
{
final URL url = buildNewUrl(webRequest.getUrl(), parameters);
webRequest.setUrl(url);
}
}
}
private static URL buildNewUrl(final URL url, final List parameters) throws MalformedURLException
{
URL newUrl = url;
if (parameters != null && !parameters.isEmpty())
{
final String query = url.getQuery();
String parameterToQuery = "";
// Add query and "&" to the url
if (query != null)
{
parameterToQuery += query + "&";
}
for (final NameValuePair parameter : parameters)
{
parameterToQuery += parameter.getName() + "=" + parameter.getValue() + "&";
}
parameterToQuery = parameterToQuery.substring(0, parameterToQuery.lastIndexOf("&"));
newUrl = UrlUtils.getUrlWithNewQuery(url, parameterToQuery);
}
return newUrl;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy