diff --git a/CHANGELOG.md b/CHANGELOG.md
index 04f6d43ad5e61befeae5c1441eec7f61126bde94..a4d71f73495699c50b38ba204b3a8275e57a9546 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
   `GRPC_RESPONSE_LOG_FORMAT` which control the format and information included
   in the log message of any response of the respective API. See
   `conf/core/server.conf` for more information.
+* REST API: Permanent redirect from "FileSystem" to "FileSystem/".
 
 ### Changed ###
 
@@ -22,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ### Fixed ###
 
+* Wrong url returned by FileSystem resource behind proxy.
 * `NullPointerException` in GRPC API converters when executing SELECT query on
   NULL values.
 
diff --git a/src/main/java/org/caosdb/server/CaosDBServer.java b/src/main/java/org/caosdb/server/CaosDBServer.java
index deca9aaec1a3b02f76b42e2d962374e55d609efc..2a115c5cfa06ed0e3db85847c27fb4c8424eadaf 100644
--- a/src/main/java/org/caosdb/server/CaosDBServer.java
+++ b/src/main/java/org/caosdb/server/CaosDBServer.java
@@ -108,6 +108,7 @@ import org.restlet.data.Reference;
 import org.restlet.data.ServerInfo;
 import org.restlet.data.Status;
 import org.restlet.engine.Engine;
+import org.restlet.routing.Redirector;
 import org.restlet.routing.Route;
 import org.restlet.routing.Router;
 import org.restlet.routing.Template;
@@ -708,6 +709,9 @@ public class CaosDBServer extends Application {
     protectedRouter.attach("/EntityPermissions/", EntityPermissionsResource.class);
     protectedRouter.attach("/EntityPermissions/{specifier}", EntityPermissionsResource.class);
     protectedRouter.attach("/Owner/{specifier}", EntityOwnerResource.class);
+    protectedRouter.attach(
+        "/FileSystem",
+        new Redirector(getContext(), "/FileSystem/", Redirector.MODE_CLIENT_PERMANENT));
     protectedRouter.attach("/FileSystem/", FileSystemResource.class);
     // FileSystem etc. needs to accept parameters which contain slashes and would otherwise be
     // split at the first separator
diff --git a/src/main/java/org/caosdb/server/resource/FileSystemResource.java b/src/main/java/org/caosdb/server/resource/FileSystemResource.java
index 1e601cb2116c92ae3aa31aaca4be01b429f9e826..9c0d615833148f706b190d7dfbc1aafdca61a75f 100644
--- a/src/main/java/org/caosdb/server/resource/FileSystemResource.java
+++ b/src/main/java/org/caosdb/server/resource/FileSystemResource.java
@@ -86,14 +86,16 @@ public class FileSystemResource extends AbstractCaosDBServerResource {
     }
 
     if (file.isDirectory()) {
-      String referenceString = getReference().toString();
-      if (!referenceString.endsWith("/")) {
-        referenceString = referenceString + "/";
-      }
+      String path = (specifier.endsWith("/") ? specifier : specifier + "/");
+      String url =
+          getUtils().getServerRootURI()
+              + "/FileSystem"
+              + (path.startsWith("/") ? path : ("/" + path));
+
       final Element folder = new Element("dir");
-      folder.setAttribute("path", (specifier.endsWith("/") ? specifier : specifier + "/"));
+      folder.setAttribute("path", path);
       folder.setAttribute("name", file.getName());
-      folder.setAttribute("url", referenceString);
+      folder.setAttribute("url", url);
 
       final boolean thumbnailsExist =
           new File(file.getAbsolutePath() + File.separator + ".thumbnails").exists();
@@ -110,7 +112,7 @@ public class FileSystemResource extends AbstractCaosDBServerResource {
         }
 
         if (thumbnailsExist) {
-          final Attribute thumbnailAttribute = getThumbnailAttribute(file, child, referenceString);
+          final Attribute thumbnailAttribute = getThumbnailAttribute(file, child, url);
           if (thumbnailAttribute != null) {
             celem.setAttribute(thumbnailAttribute);
           }
diff --git a/src/main/java/org/caosdb/server/utils/WebinterfaceUtils.java b/src/main/java/org/caosdb/server/utils/WebinterfaceUtils.java
index 375d6b5e7bbced84cec5bdcdee26a9e436f0215a..6c583fccce77471ae4a4272f35d94ec2c886afd3 100644
--- a/src/main/java/org/caosdb/server/utils/WebinterfaceUtils.java
+++ b/src/main/java/org/caosdb/server/utils/WebinterfaceUtils.java
@@ -61,6 +61,23 @@ public class WebinterfaceUtils {
   private long buildNumberDate;
   private static final Map<String, WebinterfaceUtils> instances = new HashMap<>();
 
+  public static String getForwardedProto(Request request) {
+    String scheme = null;
+    String forwarded = request.getHeaders().getFirstValue("Forwarded", true);
+    if (forwarded != null) {
+      for (String directive : forwarded.split(";")) {
+        String[] s = directive.split("=", 2);
+        if (s.length == 2 && "proto".equalsIgnoreCase(s[0])) {
+          scheme = s[1];
+        }
+      }
+    }
+    if (scheme == null) {
+      scheme = request.getHeaders().getFirstValue("X-Forwarded-Proto", true);
+    }
+    return scheme;
+  }
+
   /**
    * Retrieve an instance of {@link WebinterfaceUtils} for the request. The instance can be shared
    * with other callers.
@@ -70,7 +87,7 @@ public class WebinterfaceUtils {
    */
   public static WebinterfaceUtils getInstance(Request request) {
     String hostStr = request.getHostRef().getHostIdentifier();
-    String scheme = request.getHeaders().getFirstValue("X-Forwarded-Proto", true);
+    String scheme = getForwardedProto(request);
     if (scheme != null) {
       hostStr = hostStr.replaceFirst("^" + request.getHostRef().getScheme(), scheme);
     }