Play framework2: удалить конечную косую черту из URL-адресов

252
19

В игровой среде 1 вы можете использовать в файле маршрутов что-то вроде этого (проверьте документацию на http://www.playframework.org/documentation/1.2.5/routes#syntax)


GET     /clients/?       Clients.index

чтобы маршрут соответствовал /api/clients, а также /api/clients/


Как я могу добиться того же в структуре воспроизведения 2?

спросил(а) 2021-01-19T17:31:25+03:00 9 месяцев назад
1
Решение
375

С точки зрения SEO одна и та же связь с trailing slash является другой, чем ссылка без нее. Настоятельно рекомендуется всегда использовать одну схему (прицепные или несвязанные ссылки).


Хотя существуют разные школы, которые лучше всего важнее, это сделать 301 переадресацию с "неправильного" URL на правильный. Вы можете достичь этого довольно легко в Play с помощью Динамическая часть, охватывающая несколько / '.


Лично я предпочитаю непривлекательную версию, возможно, потому, что ее реализация в Play - это просто запись нескольких простых строк. Добавьте к своим маршрутам файл этого правила где-то в начале (сохраняйте косую черту - это важно, поскольку он не рассматривается как следующий слэш в группе spanning) и позволяет легко сопоставлять обратный URL):


GET  /*path/  controllers.Application.untrail(path: String)

то вы можете просто сделать перенаправление в контроллере - с параметром, поэтому он будет без косой черты в конце:


Java

public static Result untrail(String path) {
return movedPermanently("/" + path);
}

Scala


def untrail(path: String) = Action { 
MovedPermanently("/" + path)
}

До сих пор все маршруты, заканчивающиеся на косую черту, будут перенаправлены на версию без следа. Легко:)


Конечно, настоятельно рекомендуется использовать обратный маршрутизатор для генерации правильного URL-адреса, чтобы минимизировать избыточные перенаправления. Кроме того, если вы где-то жестко кодируете URL (т.е. В каком-то JS или во внешнем приложении), лучше писать правильные, а вместо этого конвертировать их каждый раз. Если вы планируете публиковать публичный API, обратите внимание на документацию, какой шаблон предпочитает ваше приложение, поэтому разработчики будут предупреждены и (возможно) подготовят правильные вызовы.


Что еще - это наиболее важно для маршрутов GET, поскольку они подвержены манипуляциям со стороны клиента. При использовании POST, PUT, DELETE и других вам не нужно (точнее, вы не должны) заботиться о переадресации, так как они не могут быть изменены пользователем и таким образом вам нужно запомнить который вы выбираете. В случае неправильного вызова, т.е. для POST, просто верните ошибку 404 - поэтому разработчик приложения 3-й части будет обязан использовать правильные окончания.

ответил(а) 2021-01-19T17:31:25+03:00 9 месяцев назад
129

Мне удалось что-то придумать, это было не так просто, как я надеялся, но это не ракетостроение.


import play.api.mvc.RequestHeader

import play.api.Play.current

class NormalizedRequest(request: RequestHeader) extends RequestHeader {

val headers = request.headers
val queryString = request.queryString
val remoteAddress = request.remoteAddress
val method = request.method

val path = request.path.stripSuffix("/")
val uri = path + {
if(request.rawQueryString == "") ""
else "?" + request.rawQueryString
}
}

object NormalizedRequest {
def apply(request: RequestHeader) = new NormalizedRequest(request)
}

ans, то я использую его вот так в Global.scala


override def onRouteRequest(request: RequestHeader): Option[Handler] = {
super.onRouteRequest(NormalizedRequest(request))
}

ответил(а) 2021-01-19T17:31:25+03:00 9 месяцев назад
112

Обновлен пример by @opensas и @lloydmeta для игры 2.5


/**
* HttpRequestHandler that removes trailing slashes from requests.
*/
class TrailingSlashNormaliserHttpRequestHandler(router: Router, errorHandler: HttpErrorHandler, configuration: HttpConfiguration, filters: HttpFilters) extends HttpRequestHandler {

private val default = new DefaultHttpRequestHandler(router, errorHandler, configuration, filters)

override def handlerForRequest(request: RequestHeader): (RequestHeader, Handler) = {
default.handlerForRequest(removeTrailingSlash(request))
}

private def removeTrailingSlash(origReq: RequestHeader): RequestHeader = {
if (origReq.path.endsWith("/") && origReq.path != "/") {
val path = origReq.path.stripSuffix("/")
if (origReq.rawQueryString.isEmpty) {
origReq.copy(path = path, uri = path)
}else {
origReq.copy(path = path, uri = path + s"?${origReq.rawQueryString}")
}
} else {
origReq
}
}
}


см. https://www.playframework.com/documentation/2.5.x/ScalaHttpRequestHandlers для инструкций по использованию обработчика

ответил(а) 2021-01-19T17:31:25+03:00 9 месяцев назад
65

Это основано на ответе opensas, просто упрощенном, чтобы повторно использовать встроенный метод copy на Play copy, чтобы все вещи в оригинале RequestHeader сохраняются, например, идентификаторы, теги, версия, безопасность и т.д.


import play.api.GlobalSettings
import play.api.mvc.{Handler, RequestHeader}

trait TrailingSlashNormaliser extends GlobalSettings {

def removeTrailingSlash(origReq: RequestHeader): RequestHeader = {
if (origReq.path.endsWith("/")) {
val path = origReq.path.stripSuffix("/")
if (origReq.rawQueryString.isEmpty)
origReq.copy(path = path, uri = path)
else
origReq.copy(path = path, uri = path + s"?${origReq.rawQueryString}")
} else {
origReq
}
}

override def onRouteRequest(request: RequestHeader): Option[Handler] =
super.onRouteRequest(removeTrailingSlash(request))

}

/**
* Global object that removes trailing slashes from requests.
*/
object Global extends TrailingSlashNormaliser

ответил(а) 2021-01-19T17:31:25+03:00 9 месяцев назад
46

Добавьте запись дважды в файл маршрута. Один с косой чертой и один без.

ответил(а) 2021-01-19T17:31:25+03:00 9 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема