com.intuit.karate.http.Request Maven / Gradle / Ivy
The newest version!
/*
* The MIT License
*
* Copyright 2022 Karate Labs Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.intuit.karate.http;
import com.intuit.karate.FileUtils;
import com.intuit.karate.JsonUtils;
import com.intuit.karate.StringUtils;
import com.intuit.karate.graal.JsArray;
import com.intuit.karate.graal.JsValue;
import com.intuit.karate.graal.Methods;
import com.linecorp.armeria.common.RequestContext;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.http.DefaultFullHttpRequest;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.QueryStringDecoder;
import io.netty.handler.codec.http.cookie.ClientCookieDecoder;
import io.netty.handler.codec.http.cookie.Cookie;
import io.netty.handler.codec.http.multipart.Attribute;
import io.netty.handler.codec.http.multipart.FileUpload;
import io.netty.handler.codec.http.multipart.HttpPostMultipartRequestDecoder;
import io.netty.handler.codec.http.multipart.HttpPostStandardRequestDecoder;
import io.netty.handler.codec.http.multipart.InterfaceHttpData;
import io.netty.handler.codec.http.multipart.InterfaceHttpPostRequestDecoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import static java.util.stream.Collectors.toList;
import org.graalvm.polyglot.Value;
import org.graalvm.polyglot.proxy.ProxyObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author pthomas3
*/
public class Request implements ProxyObject {
private static final Logger logger = LoggerFactory.getLogger(Request.class);
private static final String PATH = "path";
private static final String METHOD = "method";
private static final String PARAM = "param";
private static final String PARAM_INT = "paramInt";
private static final String PARAM_BOOL = "paramBool";
private static final String PARAM_JSON = "paramJson";
private static final String PARAM_EXISTS = "paramExists";
private static final String PARAMS = "params";
private static final String HEADER = "header";
private static final String HEADERS = "headers";
private static final String HEADER_VALUES = "headerValues";
private static final String PATH_PARAM = "pathParam";
private static final String PATH_PARAMS = "pathParams";
private static final String PATH_MATCHES = "pathMatches";
private static final String PATH_PATTERN = "pathPattern";
private static final String BODY = "body";
private static final String BODY_STRING = "bodyString";
private static final String BODY_BYTES = "bodyBytes";
private static final String MULTI_PART = "multiPart";
private static final String MULTI_PARTS = "multiParts";
private static final String GET = "get";
private static final String POST = "post";
private static final String PUT = "put";
private static final String DELETE = "delete";
private static final String PATCH = "patch";
private static final String HEAD = "head";
private static final String CONNECT = "connect";
private static final String OPTIONS = "options";
private static final String TRACE = "trace";
private static final String URL_BASE = "urlBase";
private static final String URL = "url";
private static final String PATH_RAW = "pathRaw";
private static final String START_TIME = "startTime";
private static final String END_TIME = "endTime";
private static final String[] KEYS = new String[]{
PATH, METHOD, PARAM, PARAM_INT, PARAM_BOOL, PARAM_JSON, PARAM_EXISTS, PARAMS,
HEADER, HEADERS, HEADER_VALUES, PATH_PARAM, PATH_PARAMS, PATH_MATCHES, PATH_PATTERN,
BODY, BODY_STRING, BODY_BYTES, MULTI_PART, MULTI_PARTS,
GET, POST, PUT, DELETE, PATCH, HEAD, CONNECT, OPTIONS, TRACE, URL_BASE, URL, PATH_RAW, START_TIME, END_TIME
};
private static final Set KEY_SET = new HashSet<>(Arrays.asList(KEYS));
private static final JsArray KEY_ARRAY = new JsArray(KEYS);
private long startTime = System.currentTimeMillis();
private long endTime;
private String urlAndPath;
private String urlBase;
private String pathOriginal;
private String path;
private String method;
private Map> params;
private Map> headers;
private byte[] body;
private Map>> multiParts;
private ResourceType resourceType;
private String resourcePath;
private Map pathParams = Collections.emptyMap();
private String pathPattern;
private RequestContext requestContext;
public RequestContext getRequestContext() {
return requestContext;
}
public void setRequestContext(RequestContext requestContext) {
this.requestContext = requestContext;
}
public boolean isAjax() {
return getHeader(HttpConstants.HDR_HX_REQUEST) != null;
}
public boolean isMultiPart() {
return multiParts != null;
}
public Map>> getMultiParts() {
return multiParts;
}
public List getHeaderValues(String name) {
return StringUtils.getIgnoreKeyCase(headers, name); // TODO optimize
}
public String getHeader(String name) {
List list = getHeaderValues(name);
if (list == null || list.isEmpty()) {
return null;
} else {
return list.get(0);
}
}
public String getContentType() {
return getHeader(HttpConstants.HDR_CONTENT_TYPE);
}
public List getCookies() {
List cookieValues = getHeaderValues(HttpConstants.HDR_COOKIE);
if (cookieValues == null) {
return Collections.emptyList();
}
return cookieValues.stream().map(ClientCookieDecoder.STRICT::decode).collect(toList());
}
public int getParamInt(String name) {
String value = getParam(name);
try {
return value == null ? -1 : Integer.valueOf(value);
} catch (Exception e) {
return -1;
}
}
public boolean getParamBool(String name) {
String value = getParam(name);
try {
return value == null ? false : Boolean.valueOf(value);
} catch (Exception e) {
return false;
}
}
public String getParam(String name) {
List values = getParamValues(name);
if (values == null || values.isEmpty()) {
return null;
}
return values.get(0);
}
public Object getParam(String name, Object value) {
String temp = getParam(name);
return StringUtils.isBlank(temp) ? value : temp;
}
private final Methods.FunVar PARAM_FUNCTION = args -> {
if (args.length == 0 || args[0] == null) {
return null;
}
String name = args[0].toString();
if (args.length > 1) {
return getParam(name, args[1]);
} else {
return getParam(name);
}
};
public List getParamValues(String name) {
if (params == null) {
return null;
}
return params.get(name);
}
public boolean getParamExists(String name) {
if (params == null) {
return false;
}
return params.containsKey(name);
}
public String getPath() {
return path;
}
public String getPathRaw() {
if (urlBase != null && urlAndPath != null) {
if (urlAndPath.charAt(0) == '/') {
return urlAndPath;
} else {
return urlAndPath.substring(urlBase.length());
}
} else {
return path;
}
}
public void setUrl(String url) {
urlAndPath = url;
StringUtils.Pair pair = HttpUtils.parseUriIntoUrlBaseAndPath(url);
urlBase = pair.left;
QueryStringDecoder qsd = new QueryStringDecoder(pair.right);
setPath(qsd.path());
setParams(qsd.parameters());
}
public void setStartTime(long startTime) {
this.startTime = startTime;
}
public long getStartTime() {
return startTime;
}
public void setEndTime(long endTime) {
this.endTime = endTime;
}
public long getEndTime() {
return endTime;
}
public String getUrlAndPath() {
return urlAndPath != null ? urlAndPath : (urlBase != null ? urlBase : "") + path;
}
public String getUrlBase() {
return urlBase;
}
public void setUrlBase(String urlBase) {
this.urlBase = urlBase;
}
public void setPath(String path) {
if (path == null || path.isEmpty()) {
path = "/";
}
if (path.charAt(0) != '/') { // mocks and synthetic situations
path = "/" + path;
}
this.path = path;
if (pathOriginal == null) {
pathOriginal = path;
}
}
public String getPathOriginal() {
return pathOriginal;
}
public void setResourceType(ResourceType resourceType) {
this.resourceType = resourceType;
}
public String getResourcePath() {
return resourcePath;
}
public void setResourcePath(String resourcePath) {
this.resourcePath = resourcePath;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public Map> getParams() {
return params == null ? Collections.emptyMap() : params;
}
public void setParams(Map> params) {
this.params = params;
}
public boolean pathMatches(String pattern) {
Map temp = HttpUtils.parseUriPattern(pattern, path);
if (temp == null) {
return false;
}
pathParams = temp;
pathPattern = pattern;
return true;
}
public void setParamCommaDelimited(String name, String value) {
if (value == null) {
return;
}
setParam(name, StringUtils.split(value, ',', false));
}
public void setParam(String name, Object value) {
if (params == null) {
params = new HashMap();
}
if (value == null) {
params.put(name, null);
} else if (value instanceof List) {
List list = (List) value;
List values = new ArrayList(list.size());
for (Object o : list) {
values.add(o == null ? null : o.toString());
}
params.put(name, values);
} else {
params.put(name, Collections.singletonList(value.toString()));
}
}
public Object getPathParam() {
if (pathParams.isEmpty()) {
return null;
}
return pathParams.values().iterator().next();
}
public Map getPathParams() {
return pathParams;
}
public void setPathParams(Map pathParams) {
this.pathParams = pathParams;
}
public Map> getHeaders() {
return headers == null ? Collections.emptyMap() : headers;
}
public void setHeaders(Map> headers) {
this.headers = headers;
}
public void setCookiesRaw(List values) {
if (values == null) {
return;
}
if (headers == null) {
headers = new HashMap();
}
headers.put(HttpConstants.HDR_COOKIE, values);
}
public void setHeaderCommaDelimited(String name, String value) {
if (value == null) {
return;
}
if (headers == null) {
headers = new HashMap();
}
headers.put(name, StringUtils.split(value, ',', false));
}
public byte[] getBody() {
return body;
}
public void setBody(byte[] body) {
this.body = body;
}
public String getBodyAsString() {
return body == null ? null : FileUtils.toString(body);
}
public Object getBodyConverted() {
ResourceType rt = getResourceType(); // derive if needed
if (rt != null && rt.isBinary()) {
return body;
}
return JsonUtils.fromBytes(body, false, rt);
}
public boolean isHttpGetForStaticResource() {
if (!"GET".equals(method)) {
return false;
}
ResourceType rt = getResourceType();
return rt != null && !rt.isUrlEncodedOrMultipart();
}
public ResourceType getResourceType() {
if (resourceType == null) {
String contentType = getContentType();
if (contentType != null) {
resourceType = ResourceType.fromContentType(contentType);
}
}
return resourceType;
}
public Object getParamJson(String name) {
String value = getParam(name);
if (StringUtils.isBlank(value)) {
return null;
}
try {
return JsValue.fromJava(JsonUtils.fromJson(value));
} catch (Exception e) {
return null;
}
}
public Map getMultiPart(String name) {
if (multiParts == null) {
return null;
}
List