Подтвердить что ты не робот

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

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

GET     /clients/?       Clients.index

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

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

4b9b3361

Ответ 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

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