Skip to content

Commit

Permalink
Merge pull request #273 from FgForrest/lab-update
Browse files Browse the repository at this point in the history
Lab update: cookie cache fix, namespaces by server name
  • Loading branch information
lukashornych authored Sep 30, 2023
2 parents 8bfe4ec + 8a9fc5b commit 4c02212
Show file tree
Hide file tree
Showing 16 changed files with 127 additions and 88 deletions.
1 change: 1 addition & 0 deletions docker/evita-configuration.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
server:
name: ${server.name:evita-db-prod}
coreThreadCount: ${server.coreThreadCount:4}
maxThreadCount: ${server.maxThreadCount:16}
threadPriority: ${server.threadPriority:5}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,17 @@

import io.evitadb.api.EvitaSessionContract;
import io.evitadb.api.requestResponse.data.EntityContract;
import io.evitadb.dataType.ClassifierType;
import io.evitadb.utils.ClassifierUtils;
import lombok.ToString;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

/**
* DTO contains base server wide settings for the evitaDB.
*
* @param name Name of the server. It's used for identification purposes only.
* @param coreThreadCount Defines count of threads that are spun up in {@link java.util.concurrent.ExecutorService} for handling
* input requests as well as maintenance tasks. The more catalog in Evita
* DB there is, the higher count of thread count might be required.
Expand All @@ -51,6 +55,7 @@
* @author Jan Novotný ([email protected]), FG Forrest a.s. (c) 2022
*/
public record ServerOptions(
@Nonnull String name,
int coreThreadCount,
int maxThreadCount,
int threadPriority,
Expand All @@ -61,6 +66,7 @@ public record ServerOptions(
boolean readOnly
) {

public static final String DEFAULT_SERVER_NAME = "evitaDB";
public static final int DEFAULT_CORE_THREAD_COUNT = Runtime.getRuntime().availableProcessors() * 10;
public static final int DEFAULT_MAX_THREAD_COUNT = Runtime.getRuntime().availableProcessors() * 20;
public static final int DEFAULT_THREAD_PRIORITY = 5;
Expand All @@ -69,6 +75,10 @@ public record ServerOptions(
public static final int DEFAULT_KILL_TIMED_OUT_SHORT_RUNNING_THREADS_EVERY_SECONDS = 30;
public static final int DEFAULT_CLOSE_SESSIONS_AFTER_SECONDS_OF_INACTIVITY = 60 * 20;

public ServerOptions {
ClassifierUtils.validateClassifierFormat(ClassifierType.SERVER_NAME, name);
}

/**
* Builder for the server options. Recommended to use to avoid binary compatibility problems in the future.
*/
Expand All @@ -85,6 +95,7 @@ public static ServerOptions.Builder builder(@Nonnull ServerOptions serverOptions

public ServerOptions() {
this(
DEFAULT_SERVER_NAME,
DEFAULT_CORE_THREAD_COUNT,
DEFAULT_MAX_THREAD_COUNT,
DEFAULT_THREAD_PRIORITY,
Expand All @@ -101,6 +112,7 @@ public ServerOptions() {
*/
@ToString
public static class Builder {
private String name = DEFAULT_SERVER_NAME;
private int coreThreadCount = DEFAULT_CORE_THREAD_COUNT;
private int maxThreadCount = DEFAULT_MAX_THREAD_COUNT;
private int threadPriority = DEFAULT_THREAD_PRIORITY;
Expand All @@ -124,6 +136,11 @@ public static class Builder {
this.readOnly = serverOptions.readOnly;
}

public ServerOptions.Builder name(@Nullable String name) {
this.name = name;
return this;
}

public ServerOptions.Builder coreThreadCount(int coreThreadCount) {
this.coreThreadCount = coreThreadCount;
return this;
Expand Down Expand Up @@ -166,6 +183,7 @@ public ServerOptions.Builder readOnly(boolean readOnly) {

public ServerOptions build() {
return new ServerOptions(
name,
coreThreadCount,
maxThreadCount,
threadPriority,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
@RequiredArgsConstructor
public enum ClassifierType {

SERVER_NAME("Server name"),
CATALOG("Catalog"),
ENTITY("Entity"),
ATTRIBUTE("Attribute"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ public class ClassifierUtils {
* Keywords must be written in camel case, validating method will check all cases.
*/
private static final Map<ClassifierType, Set<String>> RESERVED_KEYWORDS = Map.of(
ClassifierType.SERVER_NAME,
Set.of(),
ClassifierType.CATALOG,
Set.of(
"system" // would collide with special system API endpoints for managing evitaDB
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ private void registerLabGui() {
new CorsFilter(
new LabExceptionHandler(
objectMapper,
GuiHandler.create(labConfig, apiOptions, objectMapper)
GuiHandler.create(labConfig, evita.getConfiguration().server(), apiOptions, objectMapper)
),
labConfig.getAllowedOrigins()
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
package io.evitadb.externalApi.lab.gui.resolver;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.evitadb.api.configuration.ServerOptions;
import io.evitadb.externalApi.configuration.ApiOptions;
import io.evitadb.externalApi.exception.ExternalApiInternalError;
import io.evitadb.externalApi.graphql.GraphQLProvider;
Expand All @@ -45,8 +46,9 @@

import javax.annotation.Nonnull;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Base64.Encoder;
import java.util.List;
import java.util.Optional;
import java.util.regex.Pattern;
Expand All @@ -58,43 +60,57 @@
*/
public class GuiHandler extends ResourceHandler {

private static final String EVITALAB_SERVER_NAME_COOKIE = "evitalab_servername";
private static final String EVITALAB_READONLY_COOKIE = "evitalab_readonly";
private static final String EVITALAB_PRECONFIGURED_CONNECTIONS_COOKIE = "evitalab_pconnections";

private static final Pattern ASSETS_PATTERN = Pattern.compile("/assets/[a-zA-Z0-9\\-]+\\.[a-z0-9]+");
public static final Encoder BASE_64_ENCODER = Base64.getEncoder();

@Nonnull private final LabConfig labConfig;
@Nonnull private final ServerOptions serverOptions;
@Nonnull private final ApiOptions apiOptions;
@Nonnull private final ObjectMapper objectMapper;

private GuiHandler(@Nonnull ResourceSupplier resourceSupplier,
@Nonnull LabConfig labConfig,
@Nonnull ServerOptions serverOptions,
@Nonnull ApiOptions apiOptions,
@Nonnull ObjectMapper objectMapper) {
super(resourceSupplier);
this.labConfig = labConfig;
this.serverOptions = serverOptions;
this.apiOptions = apiOptions;
this.objectMapper = objectMapper;
}

@Nonnull
public static GuiHandler create(@Nonnull LabConfig labConfig,
@Nonnull ServerOptions serverOptions,
@Nonnull ApiOptions apiOptions,
@Nonnull ObjectMapper objectMapper) {
try (final ResourceManager rm = new ClassPathResourceManager(GuiHandler.class.getClassLoader(), "META-INF/lab/gui/dist")) {
return new GuiHandler(new GuiResourceSupplier(rm), labConfig, apiOptions, objectMapper);
return new GuiHandler(new GuiResourceSupplier(rm), labConfig, serverOptions, apiOptions, objectMapper);
} catch (IOException e) {
throw new ExternalApiInternalError("Failed to load GUI resources.", e);
}
}

@Override
public void handleRequest(HttpServerExchange exchange) throws Exception {
passServerName(exchange);
passReadOnlyFlag(exchange);
passPreconfiguredEvitaDBConnections(exchange);
super.handleRequest(exchange);
}

private void passServerName(@Nonnull HttpServerExchange exchange) {
exchange.getResponseHeaders().add(
Headers.SET_COOKIE,
createCookie(EVITALAB_SERVER_NAME_COOKIE, serverOptions.name())
);
}

/**
* Sends a {@link #EVITALAB_READONLY_COOKIE} cookie to the evitaLab with {@link GuiConfig#isReadOnly()} flag.
* If true, the evitaLab GUI will be in read-only mode.
Expand Down Expand Up @@ -133,7 +149,7 @@ private List<EvitaDBConnection> resolvePreconfiguredEvitaDBConnections() {
final GraphQLConfig graphQLConfig = apiOptions.getEndpointConfiguration(GraphQLProvider.CODE);
final EvitaDBConnection selfConnection = new EvitaDBConnection(
null,
"evitaDB",
serverOptions.name(),
labConfig.getBaseUrls()[0] + LabManager.LAB_API_URL_PREFIX,
Optional.ofNullable(restConfig).map(it -> it.getBaseUrls()[0]).orElse(null),
Optional.ofNullable(graphQLConfig).map(it -> it.getBaseUrls()[0]).orElse(null)
Expand All @@ -143,7 +159,7 @@ private List<EvitaDBConnection> resolvePreconfiguredEvitaDBConnections() {

@Nonnull
private String createCookie(@Nonnull String name, @Nonnull String value) {
return name + "=" + URLEncoder.encode(value, StandardCharsets.UTF_8) + "; SameSite=Strict";
return name + "=" + BASE_64_ENCODER.encodeToString(value.getBytes(StandardCharsets.UTF_8)) + ";SameSite=Strict";
}

@RequiredArgsConstructor
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Large diffs are not rendered by default.

This file was deleted.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 4c02212

Please sign in to comment.