Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ plugins {
}

group = 'com.flexcodelabs'
version = '0.0.42'
version = '0.0.43'
description = 'Flextuma App'

java {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,9 @@ public ResponseEntity<Object> handleAccessDenied(AccessDeniedException ex) {
public ResponseEntity<Object> handleNotFound(HttpServletRequest request) {
String requestUri = request.getRequestURI();
String method = request.getMethod();
if ("GET".equals(method) && !requestUri.startsWith("/api/")) {
String accept = request.getHeader("Accept");
boolean acceptsHtml = accept != null && accept.contains(MediaType.TEXT_HTML_VALUE);
if ("GET".equals(method) && acceptsHtml && !requestUri.startsWith("/api/")) {
try {
Path filePath = Paths.get(frontendDirectory, "index.html");
Resource resource = new FileSystemResource(filePath.toString());
Expand Down Expand Up @@ -360,4 +362,4 @@ private HttpStatus getResponseStatus(String message, HttpStatus defaultStatus) {
return HttpStatus.NOT_FOUND;
return defaultStatus;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,27 @@ public ResponseEntity<Resource> serveCatchAll(HttpServletRequest request) {
return serveStatic(path);
}

if (path.startsWith(".well-known/")) {
if (path.startsWith(".well-known/") && acceptsHtml(request)) {
return serveStatic(indexFile);
}

return serveStatic(indexFile);
// Only browser document navigations should receive the SPA shell. Requests
// from vulnerability scanners (for example /wp-login.php) normally accept
// any content type and must remain a 404 instead of appearing to be routes.
return acceptsHtml(request) ? serveStatic(indexFile) : ResponseEntity.notFound().build();
}

private boolean acceptsHtml(HttpServletRequest request) {
String accept = request.getHeader("Accept");
return accept != null && accept.contains(MediaType.TEXT_HTML_VALUE);
}

private ResponseEntity<Resource> serveStatic(String path) {
try {
Path filePath = Paths.get(frontendDirectory, path);
Resource resource = new FileSystemResource(filePath.toString());

if (resource.exists() || resource.isReadable()) {
if (resource.exists() && resource.isReadable()) {
String contentType = getContentType(path);

return ResponseEntity.ok()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.springframework.http.MediaType;

import java.nio.file.Files;
import java.nio.file.Path;

Expand Down Expand Up @@ -33,24 +35,23 @@ void setUp() throws Exception {
}

@Test
void serveCatchAll_shouldReturnIndexForNonApiRoutes() throws Exception {
mockMvc.perform(get("/dashboard/overview"))
void serveCatchAll_shouldReturnIndexForBrowserNavigation() throws Exception {
mockMvc.perform(get("/dashboard/overview").header("Accept", MediaType.TEXT_HTML_VALUE))
.andExpect(status().isOk())
.andExpect(content().string("<html><body>app</body></html>"));
}

@Test
void serveCatchAll_shouldReturnIndexForLoginRoute() throws Exception {
mockMvc.perform(get("/login"))
mockMvc.perform(get("/login").header("Accept", MediaType.TEXT_HTML_VALUE))
.andExpect(status().isOk())
.andExpect(content().string("<html><body>app</body></html>"));
}

@Test
void serveCatchAll_shouldReturnIndexForDottedNonApiRoutes() throws Exception {
mockMvc.perform(get("/foo.bar"))
.andExpect(status().isOk())
.andExpect(content().string("<html><body>app</body></html>"));
void serveCatchAll_shouldReturnNotFoundForNonBrowserRequests() throws Exception {
mockMvc.perform(get("/wp-login.php").header("Accept", "*/*"))
.andExpect(status().isNotFound());
}

@Test
Expand Down