2012-11-02 53 views

回答

69

從SEO的角度來看,與trailing slash相同的鏈接是其他鏈接沒有它。強烈建議始終使用一種模式(有尾或無尾的鏈接)。

雖然有不同的學校哪一個更好,最重要的是做一個301錯誤的URL重定向到正確的。使用'Dynamic part spanning several /'即可輕鬆實現。

就我個人而言,我更喜歡無拖尾的版本,也許是因爲在Play中實現它就像寫幾條簡單的線條一樣。添加到您的路徑文件該規則,在開始的地方(保持斜槓 - 這是重要的,因爲它不被視爲跨越組中下一個斜槓,並允許符合落後的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 - 以最小化冗餘重定向。另外,如果你在某處(例如在某些JS或外部應用程序中)對URL進行了硬編碼,最好是編寫正確的URL,而不是每次轉換它們。如果您打算髮布一些公共API在文檔中做筆記,您的應用程序更喜歡哪種模式,所以開發人員將被警告並(可能)準備正確的調用。

更重要的是,它對於GET路線最爲重要,因爲它們受到客戶端的操縱。在使用POSTPUT,DELETE和其他你不需要(或者說,你不應該)關心重定向的時候,因爲它們不能被用戶改變,因此你需要記住你選擇的方式。在錯誤的情況下,即。對於POST,只是返回一個404錯誤 - 所以第三方應用程序的開發人員將有義務使用正確的結尾。

+0

非常好的答案,我會試試看... – opensas

+1

謝謝。而在斯卡拉,這看起來像:def untrail(path:String)= Action {MovedPermanently(「/%s」.format(path))} –

+0

@ChristopherMartin,thanx,我將你的示例複製到答案 – biesior

0

在您的路線文件中添加條目兩次。一個與斜線和一個沒有。

+0

嗯,是的,這是我迄今發現的解決方法,我只是試圖保持我的路線乾淨 – opensas

+0

加倍是一件壞事 – mmmbell

+0

@ygra爲什麼感謝,這是建設性的。 –

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

ANS我Global.scala

使用它像這樣
override def onRouteRequest(request: RequestHeader): Option[Handler] = { 
    super.onRouteRequest(NormalizedRequest(request)) 
} 
+2

全球攔截在實踐中的例子很少和很遠,+1對於真實世界的情況 – virtualeyes

1

這是基於opensas's answer,只是簡化了一下重用播放的內置copy方法上RequestHeader,使所有在原RequestHeader的東西都保持一樣的ID,標籤,版本,安全等

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 
+1

if(origReq.path.endsWith(「/」)&& origReq.path!=「/」){ – radekg

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關於如何應用處理器的指令