diff --git a/src/main/java/org/olat/restapi/security/RestApiLoginFilter.java b/src/main/java/org/olat/restapi/security/RestApiLoginFilter.java
index f87ecc274f19cf54798008d2444a0a7d9c4333ed..7fb7ca5668cdcecbdd1aec407ef94aba138de8c1 100644
--- a/src/main/java/org/olat/restapi/security/RestApiLoginFilter.java
+++ b/src/main/java/org/olat/restapi/security/RestApiLoginFilter.java
@@ -20,6 +20,8 @@
 package org.olat.restapi.security;
 
 import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.StringTokenizer;
@@ -103,7 +105,7 @@ public class RestApiLoginFilter implements Filter {
 				HttpServletRequest httpRequest = (HttpServletRequest)request;
 				HttpServletResponse httpResponse = (HttpServletResponse)response;
 
-				String requestURI = httpRequest.getRequestURI();
+				String requestURI = getRequestURI(httpRequest);
 				RestModule restModule = (RestModule)CoreSpringFactory.getBean("restModule");
 				if(restModule == null || !restModule.isEnabled() && !isRequestURIAlwaysEnabled(requestURI)) {
 					httpResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
@@ -294,11 +296,11 @@ public class RestApiLoginFilter implements Filter {
 			followToken(token, request, response, chain);
 			return;
 		}
-		//fxdiff FXOLAT-113: business path in DMZ
+		
 		UserRequest ureq = null;
 		try{
 			//upon creation URL is checked for
-			String requestURI = request.getRequestURI();
+			String requestURI = getRequestURI(request);
 			ureq = new UserRequestImpl(requestURI, request, response);
 		} catch(NumberFormatException nfe) {
 			response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
@@ -337,7 +339,7 @@ public class RestApiLoginFilter implements Filter {
 		UserRequest ureq = null;
 		try{
 			//upon creation URL is checked for
-			String requestURI = request.getRequestURI();
+			String requestURI = getRequestURI(request);
 			ureq = new UserRequestImpl(requestURI, request, response);
 			ureq.getUserSession().putEntryInNonClearedStore(SYSTEM_MARKER, Boolean.TRUE);
 		} catch(NumberFormatException nfe) {
@@ -356,7 +358,7 @@ public class RestApiLoginFilter implements Filter {
 			UserRequest ureq = null;
 			try{
 				//upon creation URL is checked for
-				String requestURI = request.getRequestURI();
+				String requestURI = getRequestURI(request);
 				ureq = new UserRequestImpl(requestURI, request, response);
 			} catch(Exception e) {
 				response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
@@ -386,7 +388,7 @@ public class RestApiLoginFilter implements Filter {
 			UserRequest ureq = null;
 			try{
 				//upon creation URL is checked for
-				String requestURI = request.getRequestURI();
+				String requestURI = getRequestURI(request);
 				ureq = new UserRequestImpl(requestURI, request, response);
 			} catch(NumberFormatException nfe) {
 				response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
@@ -411,6 +413,18 @@ public class RestApiLoginFilter implements Filter {
 		}
 		return WebappHelper.getServletContextPath() != null;
 	}
+	
+	private String getRequestURI(HttpServletRequest request) {
+		String requestURI = request.getRequestURI();
+		if(StringHelper.containsNonWhitespace(requestURI)) {
+			try {
+				requestURI = URLDecoder.decode(requestURI, "UTF-8");
+			} catch (UnsupportedEncodingException e) {
+				log.error("", e);
+			}
+		}
+		return requestURI;
+	}
 
 	private String getLoginUrl() {
 		if(LOGIN_URL == null && isWebappHelperInitiated()) {
diff --git a/src/test/java/org/olat/restapi/CoursesFoldersTest.java b/src/test/java/org/olat/restapi/CoursesFoldersTest.java
index 53b06f5ad4279eab5ad3adb73a0431a6648a37f1..7c902fa86b21b87d488b090102c08b611b601bb3 100644
--- a/src/test/java/org/olat/restapi/CoursesFoldersTest.java
+++ b/src/test/java/org/olat/restapi/CoursesFoldersTest.java
@@ -70,10 +70,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 
 public class CoursesFoldersTest extends OlatJerseyTestCase {
 
-	private static ICourse course1;
-	private static CourseNode bcNode;
-	private static Identity admin, user;
-
 	private RestConnection conn;
 	
 	@Autowired
@@ -84,23 +80,6 @@ public class CoursesFoldersTest extends OlatJerseyTestCase {
 	@Before
 	public void setUp() throws Exception {
 		conn = new RestConnection();
-		
-		admin = securityManager.findIdentityByName("administrator");
-		user = JunitTestHelper.createAndPersistIdentityAsUser("rest-cf-one");
-		RepositoryEntry courseEntry = JunitTestHelper.deployBasicCourse(admin);
-		course1 = CourseFactory.loadCourse(courseEntry);
-		dbInstance.intermediateCommit();
-		
-		//create a folder
-		CourseNodeConfiguration newNodeConfig = CourseNodeFactory.getInstance().getCourseNodeConfiguration("bc");
-		bcNode = newNodeConfig.getInstance();
-		bcNode.setShortTitle("Folder");
-		bcNode.setLearningObjectives("Folder objectives");
-		bcNode.setNoAccessExplanation("You don't have access");
-		course1.getEditorTreeModel().addCourseNode(bcNode, course1.getRunStructure().getRootNode());
-
-		CourseFactory.publishCourse(course1, RepositoryEntryStatusEnum.published, true, false, admin, Locale.ENGLISH);
-		
 		dbInstance.intermediateCommit();
 	}
 	
@@ -118,10 +97,10 @@ public class CoursesFoldersTest extends OlatJerseyTestCase {
 	
 	@Test
 	public void testGetFolderInfo() throws IOException, URISyntaxException {
-		boolean loggedIN = conn.login("administrator", "openolat");
-		assertTrue(loggedIN);
-
-		URI uri = UriBuilder.fromUri(getNodeURI()).build();
+		assertTrue(conn.login("administrator", "openolat"));
+		
+		CourseWithBC courseWithBc = deployCourse();
+		URI uri = UriBuilder.fromUri(getNodeURI(courseWithBc)).build();
 		HttpGet get = conn.createGet(uri, MediaType.APPLICATION_JSON, true);
 		HttpResponse response = conn.execute(get);
 		assertEquals(200, response.getStatusLine().getStatusCode());
@@ -136,10 +115,11 @@ public class CoursesFoldersTest extends OlatJerseyTestCase {
 	 */
 	@Test
 	public void testGetFolderInfoByUser() throws IOException, URISyntaxException {
-		boolean loggedIN = conn.login(user.getName(), "A6B7C8");
-		assertTrue(loggedIN);
-
-		URI uri = UriBuilder.fromUri(getNodeURI()).build();
+		Identity user = JunitTestHelper.createAndPersistIdentityAsRndUser("rest-user-bc");
+		assertTrue(conn.login(user.getName(), "A6B7C8"));
+		
+		CourseWithBC courseWithBc = deployCourse();
+		URI uri = UriBuilder.fromUri(getNodeURI(courseWithBc)).build();
 		HttpGet get = conn.createGet(uri, MediaType.APPLICATION_JSON, true);
 		HttpResponse response = conn.execute(get);
 		assertEquals(200, response.getStatusLine().getStatusCode());
@@ -149,10 +129,10 @@ public class CoursesFoldersTest extends OlatJerseyTestCase {
 	
 	@Test
 	public void testGetFoldersInfo() throws IOException, URISyntaxException {
-		boolean loggedIN = conn.login("administrator", "openolat");
-		assertTrue(loggedIN);
+		assertTrue(conn.login("administrator", "openolat"));
+		CourseWithBC courseWithBc = deployCourse();
 
-		URI uri = UriBuilder.fromUri(getNodesURI()).build();
+		URI uri = UriBuilder.fromUri(getNodesURI(courseWithBc)).build();
 		HttpGet get = conn.createGet(uri, MediaType.APPLICATION_JSON, true);
 		HttpResponse response = conn.execute(get);
 		assertEquals(200, response.getStatusLine().getStatusCode());
@@ -166,8 +146,9 @@ public class CoursesFoldersTest extends OlatJerseyTestCase {
 	@Test
 	public void testUploadFile() throws IOException, URISyntaxException {
 		assertTrue(conn.login("administrator", "openolat"));
+		CourseWithBC courseWithBc = deployCourse();
 		
-		URI uri = UriBuilder.fromUri(getNodeURI()).path("files").build();
+		URI uri = UriBuilder.fromUri(getNodeURI(courseWithBc)).path("files").build();
 		
 		//create single page
 		URL fileUrl = CoursesFoldersTest.class.getResource("singlepage.html");
@@ -179,21 +160,46 @@ public class CoursesFoldersTest extends OlatJerseyTestCase {
 		HttpResponse response = conn.execute(method);
 		assertEquals(200, response.getStatusLine().getStatusCode());
 
-		VFSContainer folder = BCCourseNode.getNodeFolderContainer((BCCourseNode)bcNode, course1.getCourseEnvironment());
+		VFSContainer folder = BCCourseNode.getNodeFolderContainer((BCCourseNode)courseWithBc.bcNode, courseWithBc.course.getCourseEnvironment());
 		VFSItem item = folder.resolve(file.getName());
 		assertNotNull(item);
 	}
 	
+	@Test
+	public void testUploadFile_withSpecialCharacter() throws IOException, URISyntaxException {
+		assertTrue(conn.login("administrator", "openolat"));
+		CourseWithBC courseWithBc = deployCourse();
+		
+		URI uri = UriBuilder.fromUri(getNodeURI(courseWithBc)).path("files").build();
+		
+		//create single page
+		URL fileUrl = CoursesFoldersTest.class.getResource("singlepage.html");
+		assertNotNull(fileUrl);
+		File file = new File(fileUrl.toURI());
+		String filename = "SingleP\u00E4ge.html";
+		
+		HttpPut method = conn.createPut(uri, MediaType.APPLICATION_JSON, true);
+		conn.addMultipart(method, filename, file);
+		HttpResponse response = conn.execute(method);
+		assertEquals(200, response.getStatusLine().getStatusCode());
+
+		VFSContainer folder = BCCourseNode.getNodeFolderContainer((BCCourseNode)courseWithBc.bcNode, courseWithBc.course.getCourseEnvironment());
+		VFSItem item = folder.resolve(filename);
+		assertNotNull(item);
+		assertEquals(filename, item.getName());
+	}
+	
 	@Test
 	public void testCreateFolder() throws IOException, URISyntaxException {
 		assertTrue(conn.login("administrator", "openolat"));
+		CourseWithBC courseWithBc = deployCourse();
 		
-		URI uri = UriBuilder.fromUri(getNodeURI()).path("files").path("RootFolder").build();
+		URI uri = UriBuilder.fromUri(getNodeURI(courseWithBc)).path("files").path("RootFolder").build();
 		HttpPut method = conn.createPut(uri, MediaType.APPLICATION_JSON, true);
 		HttpResponse response = conn.execute(method);
 		assertEquals(200, response.getStatusLine().getStatusCode());
 		
-		VFSContainer folder = BCCourseNode.getNodeFolderContainer((BCCourseNode)bcNode, course1.getCourseEnvironment());
+		VFSContainer folder = BCCourseNode.getNodeFolderContainer((BCCourseNode)courseWithBc.bcNode, courseWithBc.course.getCourseEnvironment());
 		VFSItem item = folder.resolve("RootFolder");
 		assertNotNull(item);
 		assertTrue(item instanceof VFSContainer);
@@ -202,13 +208,14 @@ public class CoursesFoldersTest extends OlatJerseyTestCase {
 	@Test
 	public void testCreateFolders() throws IOException, URISyntaxException {
 		assertTrue(conn.login("administrator", "openolat"));
+		CourseWithBC courseWithBc = deployCourse();
 		
-		URI uri = UriBuilder.fromUri(getNodeURI()).path("files").path("NewFolder1").path("NewFolder2").build();
+		URI uri = UriBuilder.fromUri(getNodeURI(courseWithBc)).path("files").path("NewFolder1").path("NewFolder2").build();
 		HttpPut method = conn.createPut(uri, MediaType.APPLICATION_JSON, true);
 		HttpResponse response = conn.execute(method);
 		assertEquals(200, response.getStatusLine().getStatusCode());
 		
-		VFSContainer folder = BCCourseNode.getNodeFolderContainer((BCCourseNode)bcNode, course1.getCourseEnvironment());
+		VFSContainer folder = BCCourseNode.getNodeFolderContainer((BCCourseNode)courseWithBc.bcNode, courseWithBc.course.getCourseEnvironment());
 		VFSItem item = folder.resolve("NewFolder1");
 		assertNotNull(item);
 		assertTrue(item instanceof VFSContainer);
@@ -222,8 +229,8 @@ public class CoursesFoldersTest extends OlatJerseyTestCase {
 	@Test
 	public void testCreateFolders_tooMany() throws IOException, URISyntaxException {
 		assertTrue(conn.login("administrator", "openolat"));
-		
-		URI uri = UriBuilder.fromUri(getNodeURI()).path("files").path("RootFolder")
+		CourseWithBC courseWithBc = deployCourse();
+		URI uri = UriBuilder.fromUri(getNodeURI(courseWithBc)).path("files").path("RootFolder")
 				.path("Folder").path("Folder").path("Folder").path("Folder").path("Folder")
 				.path("Folder").path("Folder").path("Folder").path("Folder").path("Folder")
 				.path("Folder").path("Folder").path("Folder").path("Folder").path("Folder")
@@ -233,10 +240,30 @@ public class CoursesFoldersTest extends OlatJerseyTestCase {
 		assertEquals(406, response.getStatusLine().getStatusCode());
 	}
 	
+	@Test
+	public void testCreateFolders_withSpecialCharacters() throws IOException, URISyntaxException {
+		assertTrue(conn.login("administrator", "openolat"));
+		
+		CourseWithBC courseWithBc = deployCourse();
+		
+		URI uri = UriBuilder.fromUri(getNodeURI(courseWithBc)).path("files").path("RootFolder")
+				.path("F\u00FClder").build();
+		HttpPut method = conn.createPut(uri, MediaType.APPLICATION_JSON, true);
+		HttpResponse response = conn.execute(method);
+		assertEquals(200, response.getStatusLine().getStatusCode());
+		
+		VFSContainer folder = BCCourseNode.getNodeFolderContainer((BCCourseNode)courseWithBc.bcNode, courseWithBc.course.getCourseEnvironment());
+		VFSItem item = folder.resolve("RootFolder/F\u00FClder");
+		assertNotNull(item);
+		assertTrue(item instanceof VFSContainer);
+	}
+	
 	@Test
 	public void deleteFolder() throws IOException, URISyntaxException {
+		CourseWithBC courseWithBc = deployCourse();
+		
 		//add some folders
-		VFSContainer folder = BCCourseNode.getNodeFolderContainer((BCCourseNode)bcNode, course1.getCourseEnvironment());
+		VFSContainer folder = BCCourseNode.getNodeFolderContainer((BCCourseNode)courseWithBc.bcNode, courseWithBc.course.getCourseEnvironment());
 		VFSItem item = folder.resolve("FolderToDelete");
 		if(item == null) {
 			folder.createChildContainer("FolderToDelete");
@@ -244,7 +271,7 @@ public class CoursesFoldersTest extends OlatJerseyTestCase {
 		
 		assertTrue(conn.login("administrator", "openolat"));
 		
-		URI uri = UriBuilder.fromUri(getNodeURI()).path("files").path("FolderToDelete").build();
+		URI uri = UriBuilder.fromUri(getNodeURI(courseWithBc)).path("files").path("FolderToDelete").build();
 		HttpDelete method = conn.createDelete(uri, MediaType.APPLICATION_JSON);
 		HttpResponse response = conn.execute(method);
 		assertEquals(200, response.getStatusLine().getStatusCode());
@@ -253,13 +280,42 @@ public class CoursesFoldersTest extends OlatJerseyTestCase {
 		assertNull(deletedItem);
 	}
 	
-	private URI getNodeURI() {
-		return UriBuilder.fromUri(getContextURI()).path("repo").path("courses").path(course1.getResourceableId().toString())
-			.path("elements").path("folder").path(bcNode.getIdent()).build();
+	private URI getNodeURI(CourseWithBC courseWithBc) {
+		return UriBuilder.fromUri(getContextURI()).path("repo").path("courses").path(courseWithBc.course.getResourceableId().toString())
+			.path("elements").path("folder").path(courseWithBc.bcNode.getIdent()).build();
 	}
 	
-	private URI getNodesURI() {
-		return UriBuilder.fromUri(getContextURI()).path("repo").path("courses").path(course1.getResourceableId().toString())
+	private URI getNodesURI(CourseWithBC courseWithBc) {
+		return UriBuilder.fromUri(getContextURI()).path("repo").path("courses").path(courseWithBc.course.getResourceableId().toString())
 			.path("elements").path("folder").build();
 	}
+	
+	private CourseWithBC deployCourse() {
+		Identity admin = securityManager.findIdentityByName("administrator");
+		RepositoryEntry courseEntry = JunitTestHelper.deployBasicCourse(admin);
+		ICourse course = CourseFactory.loadCourse(courseEntry);
+		dbInstance.intermediateCommit();
+		
+		//create a folder
+		CourseNodeConfiguration newNodeConfig = CourseNodeFactory.getInstance().getCourseNodeConfiguration("bc");
+		CourseNode bcNode = newNodeConfig.getInstance();
+		bcNode.setShortTitle("Folder");
+		bcNode.setLearningObjectives("Folder objectives");
+		bcNode.setNoAccessExplanation("You don't have access");
+		course.getEditorTreeModel().addCourseNode(bcNode, course.getRunStructure().getRootNode());
+
+		CourseFactory.publishCourse(course, RepositoryEntryStatusEnum.published, true, false, admin, Locale.ENGLISH);
+		return new CourseWithBC(course, bcNode);
+	}
+	
+	private static class CourseWithBC {
+		private final ICourse course;
+		private final CourseNode bcNode;
+		
+		public CourseWithBC(ICourse course, CourseNode bcNode) {
+			this.course = course;
+			this.bcNode = bcNode;
+		}
+		
+	}
 }
diff --git a/src/test/java/org/olat/restapi/RestConnection.java b/src/test/java/org/olat/restapi/RestConnection.java
index 64d9aff2488c9c9a22d4a5bf912251cc38ab96a1..2388de9dee3fd603612da192075dad299915e12a 100644
--- a/src/test/java/org/olat/restapi/RestConnection.java
+++ b/src/test/java/org/olat/restapi/RestConnection.java
@@ -27,6 +27,7 @@ import java.io.UnsupportedEncodingException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -221,8 +222,8 @@ public class RestConnection {
 	
 	/**
 	 * Add an object (application/json)
-	 * @param put
-	 * @param obj
+	 * @param put The request
+	 * @param obj The object which will be serialized as json in UTF-8
 	 * @throws UnsupportedEncodingException
 	 */
 	public void addJsonEntity(HttpEntityEnclosingRequestBase put, Object obj)
@@ -234,12 +235,18 @@ public class RestConnection {
 		put.setEntity(myEntity);
 	}
 	
+	/**
+	 * @param post The request
+	 * @param filename The filename (will encoded as UTF-8)
+	 * @param file The file (application/octet-stream)
+	 * @throws UnsupportedEncodingException
+	 */
 	public void addMultipart(HttpEntityEnclosingRequestBase post, String filename, File file)
 	throws UnsupportedEncodingException {
 		
 		HttpEntity entity = MultipartEntityBuilder.create()
 				.setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
-				.addTextBody("filename", filename)
+				.addTextBody("filename", filename, ContentType.create("text/plain", StandardCharsets.UTF_8))
 				.addBinaryBody("file", file, ContentType.APPLICATION_OCTET_STREAM, filename).build();
 		post.setEntity(entity);
 	}