Play framework2: удалить конечную косую черту из URL-адресов
В игровой среде 1 вы можете использовать в файле маршрутов что-то вроде этого (проверьте документацию на http://www.playframework.org/documentation/1.2.5/routes#syntax)
GET /clients/? Clients.index
чтобы маршрут соответствовал /api/clients, а также /api/clients/
Как я могу добиться того же в структуре воспроизведения 2?
Ответы
Ответ 1
С точки зрения 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-й части будет обязан использовать правильные окончания.
Ответ 2
Мне удалось что-то придумать, это было не так просто, как я надеялся, но это не ракетостроение.
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))
}
Ответ 3
Обновлен пример 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 для инструкций по использованию обработчика
Ответ 4
Это основано на ответе 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
Ответ 5
Добавьте запись дважды в файл маршрута. Один с косой чертой и один без.