我有一个应用程序需要我为HEAD和GET动词定义一个动作。另一个应用程序(Mozilla Open Badges)使用两个HTTP请求调用我的应用程序。它首先使用HEAD来验证我的URL看起来是否返回正确的响应类型,然后对相同的URL使用GET来获取内容。以下方法有效:
GET /assertion controllers.Assertion.index
HEAD /assertion controllers.Assertion.index
......这是有效的,但是是严重干扰(不要重复自己)。
我更喜欢这样的东西:
(GET, HEAD) /assertion controllers.Assertion.index
...但不允许这样做。如果GET免费给你HEAD,我也会很高兴,但是我可能有理由阻止HEAD进行GET操作。
我认为冗余的Path-to-Action定义不是世界末日,但我希望尽可能保持代码清洁。
基于HEAD的W3C规范(http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html),我认为Play Framework 2的行为不正确,因为不允许对定义的路由进行HEAD调用对于GET:
9.4 HEAD
The HEAD method is identical to GET except that the server MUST NOT return a
message-body in the response. The metainformation contained in the HTTP headers in
response to a HEAD request SHOULD be identical to the information sent in response
to a GET request. This method can be used for obtaining metainformation about the
entity implied by the request without transferring the entity-body itself. This
method is often used for testing hypertext links for validity, accessibility, and
recent modification.
答案 0 :(得分:2)
在Play 2.0+中,无法使用通配符VERB(例如*
或ANY
或多值)(这可能是您的解决方案),因此在这种情况下' DRY违规'你使用的只是官方方式。
修改
实际上你可以尝试另一种方法:
routes
文件末尾放置' catch-all HEAD `rulez HEAD /path
指定路线 catch-all '将其发送到autoHead(path: String)
行动。GET
版本,然后只获取响应和返回标头。我将此方法的工作示例(仅限Java)添加到play-simple-rest示例应用程序。重定向的重要事项是:
public static Result autoHead(String originalPath) throws IllegalAccessException {
WS.WSRequestHolder forwardedRequest = WS.url("http://" + request().host() + request().path());
// this header will allow you to make additional choice i.e. avoid tracking the request or something else
// see condition in index() action
forwardedRequest.setHeader("X_FORWARD_FROM_HEAD", "true");
// Forward original headers
for (String header : request().headers().keySet()) {
forwardedRequest.setHeader(header, request().getHeader(header));
}
// Forward original queryString
for (String key : request().queryString().keySet()) {
for (String val : request().queryString().get(key)) {
forwardedRequest.setQueryParameter(key, val);
}
}
// Call the same path but with GET
WS.Response wsResponse = forwardedRequest.get().get();
// Set returned headers to the response
for (Field f : Http.HeaderNames.class.getFields()) {
String headerName = f.get(null).toString();
if (wsResponse.getHeader(headerName) != null) {
response().setHeader(headerName, wsResponse.getHeader(headerName));
}
}
return status(wsResponse.getStatus());
}
public static boolean forwardedFromHead() {
return (request().getHeader("X_FORWARD_FROM_HEAD") != null && "true".equals(request().getHeader("X_FORWARD_FROM_HEAD")));
}
HEAD / controllers.Application.autoHead(originalPath:String ?= "/")
HEAD /*originalPath controllers.Application.autoHead(originalPath:String)
P.S。如果你想在Scala中写一些类似的东西,那就太好了:)