play framework 2:从url中删除尾部斜杠

时间:2012-11-02 03:57:19

标签: routes playframework-2.0 config

在Play框架1中,您可以在routes文件中使用类似的内容(查看http://www.playframework.org/documentation/1.2.5/routes#syntax处的文档)

GET     /clients/?       Clients.index

这样路由将匹配/ api / clients以及/ api / clients /

如何在Play框架2中实现相同的目标?

6 个答案:

答案 0 :(得分:70)

从SEO的角度来看,与trailing slash相同的链接是没有它的链接。强烈建议始终使用一个模式(牵引或非牵引链接)。

虽然有不同的学校哪一个更好,但最重要的是将301从“错误”的URL重定向到正确的。使用“Dynamic part spanning several /”可以轻松实现游戏。

我个人更喜欢非拖尾版本,也许是因为在Play中实现它就像写几条简单的线条一样。添加到您的路线文件这个规则,在开头的某个地方(保留斜线 - 这很重要,因为它不被视为生成组中的下一个斜杠,并且允许轻松匹配牵引的URL):

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

然后你可以在控制器中进行重定向 - 到param,所以最后没有斜线:

Java

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

Scala

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

到目前为止,所有以斜杠结尾的路线都将重定向到非追踪版本。容易:)

当然,强烈建议使用反向路由器生成正确的URL - 以最小化冗余重定向。此外,如果您在某处(即在某些JS或外部应用程序中)对URL进行硬编码,那么最好还是编写正确的URL,而不是每次都进行转换。如果您计划发布一些公共API在文档中做一个注释,您的应用程序更喜欢哪种模式,那么开发人员将收到警告,并且(可能)将准备正确的调用。

更重要的是 - 它对于GET路线最为重要,因为它们是客户端的操纵对象。在使用POSTPUTDELETE和其他人时,您不需要(或者更确切地说,您不应该)关注重定向,因为用户无法更改重定向那样你需要记住你选择哪种方式。如果是错误的电话,即。对于POST,只返回404错误 - 因此第3部分应用程序的开发人员将有义务使用正确的结尾。

答案 1 :(得分:7)

我已经设法提出了一些东西,它并不像我希望的那么简单,但它也不是火箭科学

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)
}

然后我在Global.scala

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

答案 2 :(得分:5)

更新了@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

答案 3 :(得分:1)

这是基于opensas's answer,只是简化了一点,以便在copy上重复播放Play的内置RequestHeader方法,以便原始{{1}中的所有内容保存,如id,标签,版本,安全等。

RequestHeader

答案 4 :(得分:1)

此处针对 Play 2.8 的其他答案的更新:

play.http.requestHandler = your.package.here.TrailingSlashHandler

然后只需将其放入您的 conf 中即可注册:{{1}}

答案 5 :(得分:0)

在路径文件中添加两次条目。一个有斜线,一个没有。