Skip to content

Commit

Permalink
Merge branch '8.0.x'
Browse files Browse the repository at this point in the history
* 8.0.x:
  🔧 Add configuration for xPoweredBy and dateHeader interceptors
  ♻️ Refactor x-powereb-by handler as an interceptor
  ⚡ Disable undertow option to add Date response header and replace it with DateHeaderInjector
  ⚡ Virtual working threads always use heap buffers because they are faster for their operations
  🔧 Rename configuration option buffer-pooling to buffers-pooling
  🔧 Set default value of direct-buffers configuration option to true
  🔧 Fix threads options in standalone default configuration
  ♻️ Remove unused LOGGER in AuthCookieSetter
  🔧 Cookie Authentication is disabled by default
  ✨ Cookie Authentication now support both JWT and RGT cookies
  📝 Update javadoc of RegisterPlugin
  ✨ jwtAuthenticationMechanism configuration now allow both rolesClaim and fixedRoles (will be merged)
  ✨ Setps Undertow to use custom ThreadAwareByteBufferPool that delegates to specific implementations based on the thread type to optimize performance given the unique characteristics of virtual threads
  ✨ Lazy-load request content
  ✨ Allow to configure the number of carrier threads for virtual threads
  🐛 Use UTF_8 in ChannelReader.receiveFullString()
  🐛 Use UTF_8 in ChannelReader.receiveFullString()
  ♻️ ChannelReader uses exchange.getRequestReceiver()
  • Loading branch information
ujibang committed May 10, 2024
2 parents dac94a1 + 10d5b8c commit ff90f08
Show file tree
Hide file tree
Showing 72 changed files with 902 additions and 849 deletions.
14 changes: 11 additions & 3 deletions commons/src/main/java/org/restheart/configuration/CoreModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ public record CoreModule(String name,
boolean pluginsScanningVerbose,
String baseUrl,
int ioThreads,
int workersSchedulerParallelism,
int workersSchedulerMaxPoolSize,
boolean buffersPooling,
int bufferSize,
boolean directBuffers,
boolean forceGzipEncoding,
Expand All @@ -44,22 +47,27 @@ public record CoreModule(String name,
public static final String PLUGINS_SCANNING_VERBOSE_KEY = "plugins-scanning-verbose";
public static final String BASE_URL_KEY = "base-url";
public static final String IO_THREADS_KEY = "io-threads";
public static final String WORKERS_SCHEDULER_PARALLELISM_KEY ="workers-scheduler-parallelism";
public static final String WORKERS_SCHEDULER_MAX_POOL_SIZE_KEY = "workers-scheduler-max-pool-size";
public static final String BUFFERS_POOLING_KEY = "buffers-pooling";
public static final String BUFFER_SIZE_KEY = "buffer-size";
public static final String DIRECT_BUFFERS_KEY = "direct-buffers";
public static final String FORCE_GZIP_ENCODING_KEY = "force-gzip-encoding";
public static final String ALLOW_UNESCAPED_CHARS_IN_ULR_KEY = "allow-unescaped-characters-in-url";

private static final CoreModule DEFAULT_CORE_MODULE = new CoreModule("default", "plugins", new ArrayList<>(), false, null, 0, 16364, true, false, true);
private static final CoreModule DEFAULT_CORE_MODULE = new CoreModule("default", "plugins", new ArrayList<>(), false, null, 0, 0, 256, true, 16364, true, false, true);

public CoreModule(Map<String, Object> conf, boolean silent) {
this(
getOrDefault(conf, INSTANCE_NAME_KEY, DEFAULT_CORE_MODULE.name(), silent),
this(getOrDefault(conf, INSTANCE_NAME_KEY, DEFAULT_CORE_MODULE.name(), silent),
getOrDefault(conf, PLUGINS_DIRECTORY_PATH_KEY, DEFAULT_CORE_MODULE.pluginsDirectory(), silent),
// following is optional, so get it always in silent mode
getOrDefault(conf, PLUGINS_PACKAGES_KEY, DEFAULT_CORE_MODULE.pluginsPackages(), true),
getOrDefault(conf, PLUGINS_SCANNING_VERBOSE_KEY, false, true),
getOrDefault(conf, BASE_URL_KEY, DEFAULT_CORE_MODULE.baseUrl(), true),
getOrDefault(conf, IO_THREADS_KEY, DEFAULT_CORE_MODULE.ioThreads(), silent),
getOrDefault(conf, WORKERS_SCHEDULER_PARALLELISM_KEY, DEFAULT_CORE_MODULE.workersSchedulerParallelism(), silent),
getOrDefault(conf, WORKERS_SCHEDULER_MAX_POOL_SIZE_KEY, DEFAULT_CORE_MODULE.workersSchedulerMaxPoolSize(), silent),
getOrDefault(conf, BUFFERS_POOLING_KEY, DEFAULT_CORE_MODULE.buffersPooling(), silent),
getOrDefault(conf, BUFFER_SIZE_KEY, DEFAULT_CORE_MODULE.bufferSize(), silent),
getOrDefault(conf, DIRECT_BUFFERS_KEY, DEFAULT_CORE_MODULE.directBuffers(), silent),
// following is optional, so get it always in silent mode
Expand Down
8 changes: 6 additions & 2 deletions commons/src/main/java/org/restheart/configuration/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,6 @@ private static String __valueFromEnv(final String confParameter, final String ke
UNDERTOW_OPTIONS.add(UndertowOptions.ALLOW_EQUALS_IN_COOKIE_VALUE);
UNDERTOW_OPTIONS.add(UndertowOptions.ALLOW_UNKNOWN_PROTOCOLS);
UNDERTOW_OPTIONS.add(UndertowOptions.ALLOW_UNESCAPED_CHARACTERS_IN_URL);
UNDERTOW_OPTIONS.add(UndertowOptions.ALWAYS_SET_DATE);
UNDERTOW_OPTIONS.add(UndertowOptions.ALWAYS_SET_KEEP_ALIVE);
UNDERTOW_OPTIONS.add(UndertowOptions.BUFFER_PIPELINED_DATA);
UNDERTOW_OPTIONS.add(UndertowOptions.DECODE_URL);
Expand Down Expand Up @@ -464,11 +463,16 @@ public static void setConnectionOptions(Builder builder, Configuration configura
}
}
});

// In Undertow, the `Date` header is added via {@code ThreadLocal<SimpleDateFormat>}.
// * However, this approach is not optimal for virtual threads
// we disable it and add the header with DateHeaderInjector
builder.setServerOption(UndertowOptions.ALWAYS_SET_DATE, false);
}

// matches ; in a way that we can ignore matches that are inside quotes
// inspired by https://stackoverflow.com/a/23667311/4481670
private static Pattern SPLIT_REGEX = Pattern.compile(
private static final Pattern SPLIT_REGEX = Pattern.compile(
"\\\\\"|\"(?:\\\\\"|[^\"])*\"" +
"|\\\\'|'(?:\\\\'|[^'])*'" +
"|(;)");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,14 @@
import org.bson.json.JsonParseException;
import org.bson.types.ObjectId;
import org.restheart.utils.BsonUtils;
import static org.restheart.utils.BsonUtils.document;
import org.restheart.utils.ChannelReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.undertow.server.HttpServerExchange;
import io.undertow.util.HeaderValues;
import io.undertow.util.Headers;
import static org.restheart.utils.BsonUtils.document;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;

/**
* ServiceRequest implementation backed by BsonValue and initialized from csv
Expand All @@ -61,17 +62,7 @@ protected BsonFromCsvRequest(HttpServerExchange exchange) {
public static BsonFromCsvRequest init(HttpServerExchange exchange) {
var ret = new BsonFromCsvRequest(exchange);

if (checkContentType(exchange)) {
try {
ret.injectContent(exchange);
} catch (IOException ex) {
LOGGER.warn("error parsing CSV", ex);
ret.setInError(true);
} catch (Throwable ieo) {
LOGGER.warn("error initializing request", ieo);
ret.setInError(true);
}
} else {
if (!checkContentType(exchange)) {
LOGGER.warn("error initializing request, " + "Contenty-Type is not {}", CVS_CONTENT_TYPE);
ret.setInError(true);
}
Expand All @@ -83,11 +74,12 @@ public static BsonFromCsvRequest of(HttpServerExchange exchange) {
return of(exchange, BsonFromCsvRequest.class);
}

public void injectContent(HttpServerExchange exchange) throws IOException {
final var params = new CsvRequestParams(exchange);
final var csv = ChannelReader.readString(exchange);
@Override
public BsonArray parseContent() throws IOException, BadRequestException {
final var params = new CsvRequestParams(wrapped);
final var csv = ChannelReader.readString(wrapped);

setContent(parseCsv(params, csv));
return parseCsv(params, csv);
}

private static boolean checkContentType(HttpServerExchange exchange) {
Expand Down Expand Up @@ -183,8 +175,8 @@ private static class CsvRequestParams {
Deque<String> _sep = exchange.getQueryParameters().get(SEPARATOR_QPARAM_NAME);
Deque<String> _id = exchange.getQueryParameters().get(ID_IDX_QPARAM_NAME);

sep = _sep != null ? _sep.size() > 0 ? _sep.getFirst() : "" : ",";
String _idIdx = _id != null ? _id.size() > 0 ? _id.getFirst() : "-1" : "-1";
sep = _sep != null ? !_sep.isEmpty() ? _sep.getFirst() : "" : ",";
String _idIdx = _id != null ? !_id.isEmpty() ? _id.getFirst() : "-1" : "-1";

try {
idIdx = Integer.parseInt(_idIdx);
Expand Down
26 changes: 13 additions & 13 deletions commons/src/main/java/org/restheart/exchange/BsonRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,14 @@
*/
package org.restheart.exchange;

import io.undertow.server.HttpServerExchange;
import java.io.IOException;

import org.bson.BsonValue;
import org.restheart.utils.ChannelReader;
import org.bson.json.JsonParseException;
import org.restheart.utils.BsonUtils;
import org.restheart.utils.ChannelReader;

import io.undertow.server.HttpServerExchange;

/**
* ServiceRequest implementation backed by BsonValue
Expand All @@ -36,22 +39,19 @@ protected BsonRequest(HttpServerExchange exchange) {
}

public static BsonRequest init(HttpServerExchange exchange) {
var ret = new BsonRequest(exchange);

try {
ret.injectContent();
} catch (Throwable ieo) {
ret.setInError(true);
}

return ret;
return new BsonRequest(exchange);
}

public static BsonRequest of(HttpServerExchange exchange) {
return of(exchange, BsonRequest.class);
}

public void injectContent() throws IOException {
setContent(BsonUtils.parse(ChannelReader.readString(wrapped)));
@Override
public BsonValue parseContent() throws IOException, BadRequestException {
try {
return BsonUtils.parse(ChannelReader.readString(wrapped));
} catch(JsonParseException jpe) {
throw new BadRequestException(jpe.getMessage(), jpe);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@
*/
package org.restheart.exchange;

import io.undertow.connector.PooledByteBuffer;
import java.io.IOException;

import io.undertow.connector.PooledByteBuffer;

/**
*
* A buffered exchage stores content in a PooledByteBuffer
Expand All @@ -36,15 +37,15 @@ public interface BufferedExchange<T> {
* reads data from the buffer converting it to T
*
* @return
* @throws IOException
* @throws java.io.IOException
*/
public abstract T readContent() throws IOException;

/**
* writes data the buffer from T
*
* @param content
* @throws IOException
* @throws java.io.IOException
*/
public abstract void writeContent(T content) throws IOException;

Expand Down
20 changes: 7 additions & 13 deletions commons/src/main/java/org/restheart/exchange/ByteArrayRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@
*/
package org.restheart.exchange;

import io.undertow.server.HttpServerExchange;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

import org.restheart.utils.ChannelReader;

import io.undertow.server.HttpServerExchange;

/**
*
* @author Andrea Di Cesare {@literal <[email protected]>}
Expand All @@ -35,26 +36,19 @@ protected ByteArrayRequest(HttpServerExchange exchange) {
}

public static ByteArrayRequest init(HttpServerExchange exchange) {
var ret = new ByteArrayRequest(exchange);

try {
ret.injectContent();
} catch (IOException ieo) {
ret.setInError(true);
}

return ret;
return new ByteArrayRequest(exchange);
}

public static ByteArrayRequest of(HttpServerExchange exchange) {
return of(exchange, ByteArrayRequest.class);
}

public void injectContent() throws IOException {
@Override
public byte[] parseContent() throws IOException, BadRequestException {
if (wrapped.getRequestContentLength() > 0) {
setContent(ChannelReader.readBytes(wrapped));
return ChannelReader.readBytes(wrapped);
} else {
setContent(null);
return new byte[0];
}
}

Expand Down
Loading

0 comments on commit ff90f08

Please sign in to comment.