private static HttpResponse handleNotFound(ServiceRequestContext ctx, RoutingContext routingCtx) {
        // Handle 404 Not Found.
        final String oldPath = routingCtx.path();
        if (oldPath.charAt(oldPath.length() - 1) == '/') {
            // No need to send a redirect response because the request path already ends with '/'.
            return newFallbackResponse(ctx, HttpStatus.NOT_FOUND);
        }

        // Handle the case where '/path' (or '/path?query') doesn't exist
        // but '/path/' (or '/path/?query') exists.
        if (!ctx.config().virtualHost().findServiceConfig(routingCtx.withPath(oldPath + '/')).isPresent()) {
            // No need to send a redirect response because '/path/' (or '/path/?query') does not exist.
            return newFallbackResponse(ctx, HttpStatus.NOT_FOUND);
        }

        // Use relative path to handle the case where the server is behind a reverse proxy.
        // The reverse proxy might rewrite the path, so we should use the relative path.
        // For example, if the proxy rewrite the path /proxy/path -> /path, then we should send the location
        // with path/ so that the client can send the request to /proxy/path/ again.
        final int index = oldPath.lastIndexOf('/');
        assert index >= 0;
        String location = oldPath.substring(index + 1) + '/';
        if (routingCtx.query() != null) {
            location += '?' + routingCtx.query();
        }

        return HttpResponse.of(ResponseHeaders.builder(HttpStatus.TEMPORARY_REDIRECT)
                                              .add(HttpHeaderNames.LOCATION, location)
                                              .build());
    }
Handles the {@link HttpRequest}s that are not matched by any user-specified {@link Route}s.
core/src/main/java/com/linecorp/armeria/server/FallbackService.java