All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.restheart.exchange.Request Maven / Gradle / Ivy
Go to download
RESTHeart Commons - Common classes for core components and plugins.
/*-
* ========================LICENSE_START=================================
* restheart-commons
* %%
* Copyright (C) 2019 - 2024 SoftInstigate
* %%
* 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.
* =========================LICENSE_END==================================
*/
package org.restheart.exchange;
import io.undertow.security.idm.Account;
import io.undertow.server.HttpServerExchange;
import io.undertow.server.handlers.Cookie;
import io.undertow.util.AttachmentKey;
import io.undertow.util.HeaderMap;
import io.undertow.util.Headers;
import io.undertow.util.HttpString;
import io.undertow.util.Methods;
import io.undertow.util.PathTemplate;
import io.undertow.util.PathTemplateMatcher;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.restheart.exchange.ExchangeKeys.METHOD;
/**
*
* The root class for implementing a Request providing the implementation for
* common methods
*
* @author Andrea Di Cesare {@literal }
* @param generic type
*/
public abstract class Request extends Exchange {
// other constants
public static final String SLASH = "/";
public static final String PATCH = "PATCH";
public static final String UNDERSCORE = "_";
public static final AttachmentKey PIPELINE_INFO_KEY = AttachmentKey.create(PipelineInfo.class);
private static final AttachmentKey START_TIME_KEY = AttachmentKey.create(Long.class);
private static final AttachmentKey>> XFORWARDED_HEADERS = AttachmentKey.create(Map.class);
private static final AttachmentKey BLOCK_AUTH_FOR_TOO_MANY_REQUESTS = AttachmentKey.create(Boolean.class);
protected Request(HttpServerExchange exchange) {
super(exchange);
}
@SuppressWarnings("rawtypes")
public static Request of(HttpServerExchange exchange) {
var pi = pipelineInfo(exchange);
if (pi.getType() == PipelineInfo.PIPELINE_TYPE.SERVICE) {
return ServiceRequest.of(exchange);
} else {
return ByteArrayProxyRequest.of(exchange);
}
}
public static String getContentType(HttpServerExchange exchange) {
return exchange.getRequestHeaders().getFirst(Headers.CONTENT_TYPE);
}
/**
*
* @return the request path
*/
public String getPath() {
return wrapped.getRequestPath();
}
/**
*
* @return the request URL
*/
public String getURL() {
return wrapped.getRequestURL();
}
/**
*
* @return the query string
*/
public String getQueryString() {
return wrapped.getQueryString();
}
/**
*
* @return the request method
*/
public METHOD getMethod() {
return selectMethod(getWrappedExchange().getRequestMethod());
}
/**
*
* @return a content lenght
*/
public long getRequestContentLength() {
return wrapped.getRequestContentLength();
}
/**
*
* @return a mutable map of query parameters
*/
public Map> getQueryParameters() {
return wrapped.getQueryParameters();
}
/**
* @param name the name of the query parameter
* @param defaultValue the default value of the query parameter to be used if request does not specifies it
* @return the value of the query parameter or defaultValue if not present
* @deprecated use {@link org.restheart.exchange.Request#getQueryParameterOrDefault} instead
* This method contains a typo in the name and will be removed in a future release
*/
@Deprecated
public String getQueryParameterOfDefault(String name, String defaultValue) {
return wrapped.getQueryParameters().containsKey(name)
? wrapped.getQueryParameters().get(name).getFirst()
: defaultValue;
}
/**
* @param name the name of the query parameter
* @param defaultValue the default value to return if the query parameter is not present
* @return the value of the query parameter or defaultValue if not present
*/
public String getQueryParameterOrDefault(String name, String defaultValue) {
return wrapped.getQueryParameters().containsKey(name)
? wrapped.getQueryParameters().get(name).getFirst()
: defaultValue;
}
/**
*
* @return the request headers
*/
public HeaderMap getHeaders() {
return wrapped.getRequestHeaders();
}
/**
* note: an header can have multiple values. This only returns the first one.
* use getHeaders() to get all the header's values
*
* @param name the name of the header to return
* @return the first value of the header
*/
public String getHeader(String name) {
return getHeaders().getFirst(HttpString.tryFromString(name));
}
/**
* note: an header can have multiple values. This sets the given value clearing
* existing ones. use getHeaders().add(value) to add the value without clearing.
*
* @param name the name of the header to return
* @param value
*/
public void setHeader(HttpString name, String value) {
if (getHeaders().get(name) == null) {
getHeaders().put(name, value);
} else {
getHeaders().get(name).clear();
getHeaders().get(name).add(value);
}
}
/**
* note: an header can have multiple values. This sets the given value clearing
* existing ones. use getHeaders().add(value) to add the value without clearing.
*
* @param name the name of the header to return
* @param value
*/
public void setHeader(String name, String value) {
if (getHeaders().get(name) == null) {
getHeaders().put(HttpString.tryFromString(name), value);
} else {
getHeaders().get(HttpString.tryFromString(name)).clear();
getHeaders().get(HttpString.tryFromString(name)).add(value);
}
}
/**
* @param name the name of the cookie to return
* @return a the cookie
*/
public Cookie getCookie(String name) {
return wrapped.getRequestCookie(name);
}
/**
* get path parameters using a template
*
* {@literal pathTemplate=/foo/{id} and URI=/foo/bar => returns a map with id=bar }
*
* @param pathTemplate the path template
* @return the path parameters
*/
public Map getPathParams(String pathTemplate) {
var ptm = new PathTemplateMatcher();
try {
ptm.add(PathTemplate.create(pathTemplate), "");
} catch (Throwable t) {
throw new IllegalArgumentException("wrong path template", t);
}
var match = ptm.match(getPath());
return match != null ? ptm.match(getPath()).getParameters() : new HashMap<>();
}
/**
* get a path parameter using a path template
*
* eg {@literal pathTemplate=/foo/{id}, paramName=id and URI=/foo/bar => returns bar }
*
* @param pathTemplate the path template
* @param paramName name of parameter
* @return the path parameter
*/
public String getPathParam(String pathTemplate, String paramName) {
var params = getPathParams(pathTemplate);
return params != null ? params.get(paramName) : null;
}
/**
* @return the request ContentType
*/
@Override
public String getContentType() {
return getContentType(getWrappedExchange());
}
/**
* @param responseContentType the responseContentType to set
*/
public void setContentType(String responseContentType) {
getHeaders().put(Headers.CONTENT_TYPE, responseContentType);
}
/**
* sets Content-Type=application/json
*/
public void setContentTypeAsJson() {
setContentType("application/json");
}
protected void setContentLength(int length) {
getHeaders().put(Headers.CONTENT_LENGTH, length);
}
/**
* @return the requestStartTime
*/
public Long getStartTime() {
return getWrappedExchange().getAttachment(START_TIME_KEY);
}
/**
* @param requestStartTime the requestStartTime to set
*/
public void setStartTime(Long requestStartTime) {
getWrappedExchange().putAttachment(START_TIME_KEY, requestStartTime);
}
/**
* @return the authenticatedAccount
*/
public Account getAuthenticatedAccount() {
return getWrappedExchange().getSecurityContext() != null
? getWrappedExchange().getSecurityContext().getAuthenticatedAccount()
: null;
}
/**
* @return true if account is authenticated
*/
@Override
public boolean isAuthenticated() {
return getAuthenticatedAccount() != null;
}
/**
* Add the header X-Forwarded-[key] to the proxied request; use it to pass to
* the backend information otherwise lost proxying the request.
*
* @param key
* @param value
*/
public void addXForwardedHeader(String key, String value) {
if (wrapped.getAttachment(XFORWARDED_HEADERS) == null) {
wrapped.putAttachment(XFORWARDED_HEADERS, new LinkedHashMap<>());
}
var values = wrapped.getAttachment(XFORWARDED_HEADERS).get(key);
if (values == null) {
values = new ArrayList<>();
wrapped.getAttachment(XFORWARDED_HEADERS).put(key, values);
}
values.add(value);
}
public Map> getXForwardedHeaders() {
return getWrappedExchange().getAttachment(XFORWARDED_HEADERS);
}
/**
*
* @param exchange
* @return the PipelineInfo that allows to know which pipeline (service, proxy
* or static resource) is handling the exchange
*/
public static PipelineInfo pipelineInfo(HttpServerExchange exchange) {
return exchange.getAttachment(PIPELINE_INFO_KEY);
}
/**
* @param exchange the exchange to bind the pipelineInfo to
* @param pipelineInfo the pipelineInfo to set
*/
public static void setPipelineInfo(HttpServerExchange exchange, PipelineInfo pipelineInfo) {
exchange.putAttachment(PIPELINE_INFO_KEY, pipelineInfo);
}
/**
*
* @return the PipelineInfo that allows to know which pipeline (service, proxy
* or static resource) is handling the exchange
*/
public PipelineInfo getPipelineInfo() {
return getWrappedExchange().getAttachment(PIPELINE_INFO_KEY);
}
/**
*
* @param exchange
* @return the PipelineInfo that allows to know which pipeline (service, proxy
* or static resource) is handling the exchange
*/
public static PipelineInfo getPipelineInfo(HttpServerExchange exchange) {
return exchange.getAttachment(PIPELINE_INFO_KEY);
}
/**
* @param pipelineInfo the pipelineInfo to set
*/
public void setPipelineInfo(PipelineInfo pipelineInfo) {
getWrappedExchange().putAttachment(PIPELINE_INFO_KEY, pipelineInfo);
}
/**
* helper method to check request method
*
* @return true if method is METHOD.DELETE
*/
public boolean isDelete() {
return getMethod() == METHOD.DELETE;
}
/**
* helper method to check request method
*
* @return true if method is METHOD.GET
*/
public boolean isGet() {
return getMethod() == METHOD.GET;
}
/**
* helper method to check request method
*
* @return true if method is METHOD.OPTIONS
*/
public boolean isOptions() {
return getMethod() == METHOD.OPTIONS;
}
/**
* helper method to check request method
*
* @return true if method is METHOD.PATCH
*/
public boolean isPatch() {
return getMethod() == METHOD.PATCH;
}
/**
* helper method to check request method
*
* @return true if method is METHOD.POST
*/
public boolean isPost() {
return getMethod() == METHOD.POST;
}
/**
* helper method to check request method
*
* @return true if method is METHOD.PUT
*/
public boolean isPut() {
return getMethod() == METHOD.PUT;
}
private static METHOD selectMethod(HttpString _method) {
if (Methods.GET.equals(_method)) {
return METHOD.GET;
} else if (Methods.POST.equals(_method)) {
return METHOD.POST;
} else if (Methods.PUT.equals(_method)) {
return METHOD.PUT;
} else if (Methods.DELETE.equals(_method)) {
return METHOD.DELETE;
} else if (PATCH.equals(_method.toString())) {
return METHOD.PATCH;
} else if (Methods.OPTIONS.equals(_method)) {
return METHOD.OPTIONS;
} else {
return METHOD.OTHER;
}
}
/**
* If called BEFORE authentication, the request will be aborted
* with a 429 Too Many Requests response.
*/
public void blockForTooManyRequests() {
getWrappedExchange().putAttachment(BLOCK_AUTH_FOR_TOO_MANY_REQUESTS, true);
}
/**
* @return true if the request is blocked for too many requests
*/
public boolean isBlockForTooManyRequests() {
var block = getWrappedExchange().getAttachment(BLOCK_AUTH_FOR_TOO_MANY_REQUESTS);
return block == null ? false : block;
}
}