Исправить относительные пути в HTML, обслуживаемые сервлетом Java (для HTML5 pushstate) - PullRequest
0 голосов
/ 27 ноября 2018

Я пытаюсь изменить сервер Jetty с сервлетом (RootResource.java), который каким-то образом волшебным образом подхватывает и использует:

@Singleton
@Path("/")
public class RootResource {
    @Context
    private ServletContext servletContext;

    @GET
    @Path("react-client/{path: .*\\..+$}")
    public Response serveReactClientContent(@Context HttpServletRequest httpServletRequest) {
        // This doesn't work, a resolved relative resource is not relative
        // to the /react-client base. See description of problem.
        final String pathToResource = httpServletRequest.getRequestURI();
        return serveStaticContent(pathToResource);
    }

    @GET
    @Path("react-client/{path: .*$}")
    public Response serveReactClientIndexPage(@Context HttpServletRequest httpServletRequest) {
        return serveStaticContent("/react-client/index.html");
    }

    private Response serveStaticContent(String pathToResource) {
        final String type = this.servletContext.getMimeType(pathToResource);
        final Response.ResponseBuilder response = Response.ok(servletContext.getResourceAsStream(pathToResource)).type(type);
        return response.build();
    }
}

Идея состоит в том, чтобы перевести GET-запрос на react-client/some/pathи верните содержимое react-client/index.html.По сути, заставить Jetty вести себя как сервер веб-приложений, использующий маршрутизацию на стороне клиента.

Проблема, с которой я сталкиваюсь, заключается в том, что относительные пути в index.html работают, только если путь имеет глубину на один уровень например react-client/products.

<script src="./webapp.js"></script>

В этом случае файл javascript выше в index.html найден, потому что webapp.js - это файл, который существует в react-client/webapp.js.

Как толькокогда я пытаюсь найти более глубокую ссылку, например react-client/products/97357361, которая не работает, когда сервлет пытается найти webapp.js в react-client/products/webapp.js, который не существует.

Как я могу сделать так, чтобы он всегда запрашивал ресурс, как будто он из/react-client?Спасибо

Ответы [ 2 ]

0 голосов
/ 07 декабря 2018

Поскольку ваш index.html может получить доступ по нескольким URL-адресам, таким как

  • / реагировать-клиент / продукты
  • / реагировать-клиент / продукты / 97357361
  • / реагировать-клиент / некоторые
  • / реагировать-клиент / некоторые / путь

Возможно, было бы целесообразно добавить тег <base> в заголовок вашей HTML-страницы.

<head>
    ...
    <base href="https://www.yourwebsite.com/react-content/" />
    <script src="./script.js"></script>
    ...
</head>

Это скажет браузеру разрешить любой относительный путь, найденный на странице, относительно https://www.yourwebsite.com/react-content/

Так, согласно приведенному выше примеру, <script src="./script.js"></script> будет запрошеносервер как "https://www.yourwebsite.com/react-content/script.js" независимо от текущего URL-адреса, используемого для доступа к этой странице.

Затем вы можете отменить эти настройки на Jetty и сохранить его простым.

0 голосов
/ 03 декабря 2018

Я пробовал много вещей, таких как фильтры и обработчики перезаписи , но ни разу Jetty никогда не обеспечивала исходный неразрешенный относительный импорт (например, ./webapp), поэтому у меня никогда не было возможности переписать относительные ресурсы.

В конце концов, я должен был просто обнаружить их с помощью взлома, зная, что почти все они были запрошены из подкаталога /static/ (мне пришлось добавить жестко закодированное исключение для favicon.ico и manifest.json.

@GET
@Path("react-client/{path: .*\\..+$}")
public Response serveReactClientContent(@Context HttpServletRequest httpServletRequest) {
    final String pathToResource = httpServletRequest.getRequestURI();

    Pattern p = Pattern.compile("/react-client/(.+?(?=static/|favicon.ico))", Pattern.CASE_INSENSITIVE);
    Matcher m = p.matcher(pathToResource);
    String resolveResourcePath = m.replaceAll("/react-client/");
    return serveStaticContent(resolveResourcePath);
}

Не доволен, но работает.

...