CENSORED_LOWERCASE_PARAMETER_NAMES =
+ ImmutableSet.of("password", "passphrase", "secret", "secretKey");
/*
- * Contains the file extension used by HTML
+ * Caches the GMT TimeZone (lookup is synchronized)
*/
- private static final String FILETYPE_HTML = ".html";
+ private static final TimeZone TIME_ZONE_GMT = TimeZone.getTimeZone("GMT");
/*
* Contains the content type used for html
@@ -339,10 +343,8 @@ private void updateStatistics(HttpResponseStatus status) {
if (WebServer.serverErrors.incrementAndGet() < 0) {
WebServer.serverErrors.set(0);
}
- } else if (status.code() >= 400) {
- if (WebServer.clientErrors.incrementAndGet() < 0) {
- WebServer.clientErrors.set(0);
- }
+ } else if (status.code() >= 400 && WebServer.clientErrors.incrementAndGet() < 0) {
+ WebServer.clientErrors.set(0);
}
}
@@ -473,12 +475,21 @@ private void updateResponseTimeMetrics(CallContext callContext) {
wc.getRequestedURL(),
wc.getParameterNames()
.stream()
- .map(param -> param + ": " + Strings.limit(wc.get(param).asString(), 50))
+ .map(param -> param + ": " + censor(param))
.collect(Collectors.joining("\n")),
callContext);
}
}
+ @Nonnull
+ private String censor(@Nonnull String parameterName) {
+ if (CENSORED_LOWERCASE_PARAMETER_NAMES.contains(parameterName.toLowerCase())) {
+ return "(censored)";
+ } else {
+ return Strings.limit(wc.get(parameterName).asString(), 50);
+ }
+ }
+
private void handleKeepalive(boolean keepalive, ChannelFuture future) {
if (!keepalive) {
if (WebServer.LOG.isFINE()) {
@@ -520,14 +531,12 @@ private void completeAndClose(ChannelFuture future) {
*/
public boolean handleIfModifiedSince(long lastModifiedInMillis) {
long ifModifiedSinceDateSeconds = wc.getDateHeader(HttpHeaderNames.IF_MODIFIED_SINCE) / 1000;
- if (ifModifiedSinceDateSeconds > 0 && lastModifiedInMillis > 0) {
- if (ifModifiedSinceDateSeconds >= lastModifiedInMillis / 1000) {
- setDateAndCacheHeaders(lastModifiedInMillis,
- cacheSeconds == null ? HTTP_CACHE : cacheSeconds,
- isPrivate);
- status(HttpResponseStatus.NOT_MODIFIED);
- return true;
- }
+ if (ifModifiedSinceDateSeconds > 0
+ && lastModifiedInMillis > 0
+ && ifModifiedSinceDateSeconds >= lastModifiedInMillis / 1000) {
+ setDateAndCacheHeaders(lastModifiedInMillis, cacheSeconds == null ? HTTP_CACHE : cacheSeconds, isPrivate);
+ status(HttpResponseStatus.NOT_MODIFIED);
+ return true;
}
return false;
@@ -1172,15 +1181,6 @@ public void template(HttpResponseStatus status, Template template, Object... par
}
}
- private void setupContentType(Template template) {
- String fileName = template.getEffectiveFileName();
- if (fileName.endsWith(FILETYPE_HTML)) {
- setHeader(HttpHeaderNames.CONTENT_TYPE, CONTENT_TYPE_HTML);
- } else {
- setContentTypeHeader(fileName);
- }
- }
-
private void handleTemplateError(String name, Exception e) {
throw Exceptions.handle()
.to(Tagliatelle.LOG)
diff --git a/src/main/java/sirius/web/http/SmartHttpContentCompressor.java b/src/main/java/sirius/web/http/SmartHttpContentCompressor.java
index f2416e7de..f830951e0 100644
--- a/src/main/java/sirius/web/http/SmartHttpContentCompressor.java
+++ b/src/main/java/sirius/web/http/SmartHttpContentCompressor.java
@@ -35,10 +35,11 @@ class SmartHttpContentCompressor extends HttpContentCompressor {
@Override
protected Result beginEncode(HttpResponse res, String acceptEncoding) throws Exception {
- if (!(res instanceof FullHttpResponse)) {
- if (!res.headers().contains(HttpHeaderNames.TRANSFER_ENCODING, HttpHeaderValues.CHUNKED, true)) {
- return null;
- }
+ if (!(res instanceof FullHttpResponse) && !res.headers()
+ .contains(HttpHeaderNames.TRANSFER_ENCODING,
+ HttpHeaderValues.CHUNKED,
+ true)) {
+ return null;
}
// If the content type is not compressable (jpg, png ...), we skip compression
diff --git a/src/main/java/sirius/web/http/WebContext.java b/src/main/java/sirius/web/http/WebContext.java
index 778d33f30..3000b074f 100644
--- a/src/main/java/sirius/web/http/WebContext.java
+++ b/src/main/java/sirius/web/http/WebContext.java
@@ -15,7 +15,7 @@
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.hash.Hashing;
-import com.google.common.io.Files;
+import com.google.common.io.ByteStreams;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufInputStream;
import io.netty.channel.ChannelHandlerContext;
@@ -37,6 +37,7 @@
import sirius.kernel.async.CallContext;
import sirius.kernel.async.SubContext;
import sirius.kernel.commons.Callback;
+import sirius.kernel.commons.Files;
import sirius.kernel.commons.Strings;
import sirius.kernel.commons.Tuple;
import sirius.kernel.commons.Value;
@@ -1691,11 +1692,13 @@ public File getContentAsCopy() throws IOException {
}
File result = File.createTempFile("http", "");
- if (!content.isInMemory()) {
- Files.copy(content.getFile(), result);
- } else {
- try (FileOutputStream outputStream = new FileOutputStream(result)) {
+ try (FileOutputStream outputStream = new FileOutputStream(result)) {
+ if (content.isInMemory()) {
outputStream.write(content.get());
+ } else {
+ try (FileInputStream inputStream = new FileInputStream(content.getFile())) {
+ ByteStreams.copy(inputStream, outputStream);
+ }
}
}
@@ -1773,15 +1776,15 @@ public JSONObject getJSONContent() {
.withSystemErrorMessage("Expected a valid JSON map as body of this request.")
.handle();
}
- if (!content.isInMemory()) {
- if (content.getFile().length() > maxStructuredInputSize && maxStructuredInputSize > 0) {
- throw Exceptions.handle()
- .to(WebServer.LOG)
- .withSystemErrorMessage(
- "Request body is too large to parse as JSON. The limit is %d bytes",
- maxStructuredInputSize)
- .handle();
- }
+ if (!content.isInMemory()
+ && content.getFile().length() > maxStructuredInputSize
+ && maxStructuredInputSize > 0) {
+ throw Exceptions.handle()
+ .to(WebServer.LOG)
+ .withSystemErrorMessage(
+ "Request body is too large to parse as JSON. The limit is %d bytes",
+ maxStructuredInputSize)
+ .handle();
}
return JSON.parseObject(content.getString(getRequestEncoding()));
} catch (HandledException e) {
@@ -1947,24 +1950,12 @@ private void cleanupFiles() {
}
for (File file : filesToCleanup) {
- saveDeleteFile(file);
+ Files.delete(file);
}
filesToCleanup = null;
}
- private void saveDeleteFile(File file) {
- try {
- if (file != null && file.exists()) {
- if (!file.delete()) {
- WebServer.LOG.WARN("Cannot delete temporary file: %s", file.getAbsolutePath());
- }
- }
- } catch (Exception e) {
- Exceptions.handle(WebServer.LOG, e);
- }
- }
-
/**
* Returns a token which can be added to dynamic asset-URLS (/asset/dynamic/TOKEN/...).
*
@@ -2006,7 +1997,7 @@ public String toString() {
if (request == null) {
return result;
}
-
+
return result + request.toString();
}
diff --git a/src/main/java/sirius/web/http/WebServerHandler.java b/src/main/java/sirius/web/http/WebServerHandler.java
index 04efa2ed2..5f809517b 100644
--- a/src/main/java/sirius/web/http/WebServerHandler.java
+++ b/src/main/java/sirius/web/http/WebServerHandler.java
@@ -231,10 +231,9 @@ public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exc
* @return true if keepalive is still supported, false otherwise.
*/
public boolean shouldKeepAlive() {
- if (!WebServer.getProxyIPs().isEmpty()) {
- if (WebServer.getProxyIPs().accepts(((InetSocketAddress) this.remoteAddress).getAddress())) {
- return true;
- }
+ if (!WebServer.getProxyIPs().isEmpty() && WebServer.getProxyIPs()
+ .accepts(((InetSocketAddress) this.remoteAddress).getAddress())) {
+ return true;
}
return numKeepAlive-- > 0;
@@ -300,10 +299,8 @@ private void channelReadHttpContent(Object msg) throws IOException {
return;
}
boolean last = msg instanceof LastHttpContent;
- if (!last) {
- if (WebServer.chunks.incrementAndGet() < 0) {
- WebServer.chunks.set(0);
- }
+ if (!last && WebServer.chunks.incrementAndGet() < 0) {
+ WebServer.chunks.set(0);
}
if (currentContext.contentHandler != null) {
CallContext.setCurrent(currentCall);
@@ -561,13 +558,12 @@ private void processContent(HttpContent chunk) {
File file = currentContext.content.getFile();
checkUploadFileLimits(file);
}
- } else if (!(chunk instanceof LastHttpContent)) {
- if (!HttpMethod.POST.equals(currentRequest.method())
- && !HttpMethod.PUT.equals(currentRequest.method())) {
- currentContext.respondWith()
- .error(HttpResponseStatus.BAD_REQUEST, "Only POST or PUT may sent chunked data");
- currentRequest = null;
- }
+ } else if (!(chunk instanceof LastHttpContent)
+ && !HttpMethod.POST.equals(currentRequest.method())
+ && !HttpMethod.PUT.equals(currentRequest.method())) {
+ currentContext.respondWith()
+ .error(HttpResponseStatus.BAD_REQUEST, "Only POST or PUT may sent chunked data");
+ currentRequest = null;
}
} catch (Exception ex) {
currentContext.respondWith()
@@ -629,12 +625,6 @@ private boolean preDispatch() {
return getPipeline().preDispatch(currentContext);
}
- private void logPredispatched(String msg) {
- if (WebServer.LOG.isFINE()) {
- WebServer.LOG.FINE(msg);
- }
- }
-
/*
* Dispatches the completely read request.
*/
diff --git a/src/main/java/sirius/web/resources/LocalPathResolver.java b/src/main/java/sirius/web/resources/LocalPathResolver.java
index 12bc98cce..9cbec6785 100644
--- a/src/main/java/sirius/web/resources/LocalPathResolver.java
+++ b/src/main/java/sirius/web/resources/LocalPathResolver.java
@@ -86,10 +86,8 @@ private boolean isReady() {
baseDirFound = false;
} else {
getBaseDir();
- if (!baseDir.exists()) {
- if (!DEFAULT_BASE_DIR.equals(localResourcePath)) {
- Resources.LOG.WARN(CHECK_MSG, localResourcePath, baseDir.getAbsolutePath());
- }
+ if (!baseDir.exists() && !DEFAULT_BASE_DIR.equals(localResourcePath)) {
+ Resources.LOG.WARN(CHECK_MSG, localResourcePath, baseDir.getAbsolutePath());
}
baseDirFound = baseDir.exists();
}
diff --git a/src/main/java/sirius/web/security/Permissions.java b/src/main/java/sirius/web/security/Permissions.java
index 5458b6e99..87d86bd10 100644
--- a/src/main/java/sirius/web/security/Permissions.java
+++ b/src/main/java/sirius/web/security/Permissions.java
@@ -12,7 +12,6 @@
import sirius.kernel.Sirius;
import sirius.kernel.commons.Explain;
import sirius.kernel.commons.Strings;
-import sirius.kernel.di.std.ConfigValue;
import sirius.kernel.health.Log;
import sirius.kernel.nls.NLS;
import sirius.kernel.settings.Extension;
diff --git a/src/main/java/sirius/web/security/ScopeInfo.java b/src/main/java/sirius/web/security/ScopeInfo.java
index e35355505..bd2f586d1 100644
--- a/src/main/java/sirius/web/security/ScopeInfo.java
+++ b/src/main/java/sirius/web/security/ScopeInfo.java
@@ -179,7 +179,6 @@ public boolean is(@Nonnull Class> type) {
return super.is(type);
}
- @SuppressWarnings("unchecked")
@Override
public Optional tryAs(@Nonnull Class adapterType) {
Transformable userObject = getScopeObject(Transformable.class);
@@ -420,9 +419,9 @@ private static void collectDefaultConfigFiles(Map configFiles, V
public UserSettings getSettings() {
if (settings == null) {
if (configSupplier != null) {
- settings = new UserSettings(configSupplier.apply(this).withFallback(getScopeDefaultConfig()));
+ settings = new UserSettings(configSupplier.apply(this).withFallback(getScopeDefaultConfig()), false);
} else {
- settings = new UserSettings(getScopeDefaultConfig());
+ settings = new UserSettings(getScopeDefaultConfig(), false);
}
}
diff --git a/src/main/java/sirius/web/security/UserSettings.java b/src/main/java/sirius/web/security/UserSettings.java
index b80354af6..6ad68bdad 100644
--- a/src/main/java/sirius/web/security/UserSettings.java
+++ b/src/main/java/sirius/web/security/UserSettings.java
@@ -21,9 +21,11 @@ public class UserSettings extends ExtendedSettings {
* Creates a new wrapper for the given config.
*
* @param config the config to wrap
+ * @param strict determines if the config is strict. A strict config will log an error if an unkown path is
+ * requested
*/
- public UserSettings(Config config) {
- super(config);
+ public UserSettings(Config config, boolean strict) {
+ super(config, strict);
}
/**
diff --git a/src/main/java/sirius/web/services/ServiceDispatcher.java b/src/main/java/sirius/web/services/ServiceDispatcher.java
index 2b52d6b35..1d8e818b8 100644
--- a/src/main/java/sirius/web/services/ServiceDispatcher.java
+++ b/src/main/java/sirius/web/services/ServiceDispatcher.java
@@ -102,14 +102,13 @@ private Tuple parsePath(WebContext ctx, String u
private void invokeService(WebContext ctx, ServiceCall call, StructuredService serv) {
TaskContext.get().setSystem(SYSTEM_SERVICE).setSubSystem(serv.getClass().getSimpleName());
- // Check firewall
- if (firewall != null && !serv.getClass().isAnnotationPresent(Unlimited.class)) {
- if (firewall.handleRateLimiting(ctx,
- Optional.ofNullable(serv.getClass().getAnnotation(Limited.class))
- .map(Limited::value)
- .orElse(Limited.HTTP))) {
- return;
- }
+ if (firewall != null
+ && !serv.getClass().isAnnotationPresent(Unlimited.class)
+ && firewall.handleRateLimiting(ctx,
+ Optional.ofNullable(serv.getClass().getAnnotation(Limited.class))
+ .map(Limited::value)
+ .orElse(Limited.HTTP))) {
+ return;
}
// ... and check permissions