您的位置:首页 > 编程语言 > Java开发

Spring rest对etag支持

2013-06-02 16:15 357 查看
原文地址:http://www.javaarch.net/jiagoushi/698.htm

Spring rest对etag支持

etag(entity tag)是http响应头中用来判断对应响应结果是否修改。可以使用hash算法来计算etag的值。

比如:第一次访问

curl -H "Accept: application/json" -i http://localhost:8080/rest-sec/api/resources/1 
响应为:

HTTP/1.1 200 OK
ETag: "f88dd058fe004909615a64f01be66a7"
Content-Type: application/json;charset=UTF-8
Content-Length: 52

那么下次客户端访问的时候If-None-Match或者If-Match头来让服务端判断是否修改

curl -H "Accept: application/json" -H 'If-None-Match: "f88dd058fe004909615a64f01be66a7"'
-i http://localhost:8080/rest-sec/api/resources/1 
如果没有修改,则服务端会返回

HTTP/1.1 304 Not Modified
ETag: "f88dd058fe004909615a64f01be66a7"

我们重新修改请求参数:

curl --user admin@fake.com:adminpass -H "Content-Type: application/json" -i
-X PUT --data '{ "id":1, "name":"newRoleName2", "description":"theNewDescription" }' http://localhost:8080/rest-sec/api/resources/1 
响应为:

HTTP/1.1 200 OK
ETag: "d41d8cd98f00b204e9800998ecf8427e"
Content-Length: 0

如果我们再访问

curl -H "Accept: application/json" -H 'If-None-Match: "f88dd058fe004909615a64f01be66a7"' -i http://localhost:8080/rest-sec/api/resources/1 
则返回:

HTTP/1.1 200 OK
ETag: "03cb37ca667706c68c0aad4cb04c3a211"
Content-Type: application/json;charset=UTF-8
Content-Length: 56

spring对etag的支持,在web.xml中加上这个filter

<filter>
<filter-name>etagFilter</filter-name>
<filter-class>org.springframework.web.filter.ShallowEtagHeaderFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>etagFilter</filter-name>
<url-pattern>/api/*</url-pattern>
</filter-mapping>

测试etags

第一次判断etag不为空

@Test
public void givenResourceExists_whenRetrievingResource_thenEtagIsAlsoReturned() {
// Given
Resource existingResource = getApi().create(new Resource());
String uriOfResource = baseUri + "/" + existingResource.getId();

// When
Response findOneResponse = RestAssured.given().
header("Accept", "application/json").get(uriOfResource);

// Then
assertNotNull(findOneResponse.getHeader(HttpHeaders.ETAG));
}

第二次,我们从上一次取出etag之后把etag发送给服务端验证

@Test
public void givenResourceWasRetrieved_whenRetrievingAgainWithEtag_thenNotModifiedReturned() {
// Given
T existingResource = getApi().create(createNewEntity());
String uriOfResource = baseUri + "/" + existingResource.getId();
Response findOneResponse = RestAssured.given().
header("Accept", "application/json").get(uriOfResource);
String etagValue = findOneResponse.getHeader(HttpHeaders.ETAG);

// When
Response secondFindOneResponse= RestAssured.given().
header("Accept", "application/json").headers("If-None-Match", etagValue)
.get(uriOfResource);

// Then
assertTrue(secondFindOneResponse.getStatusCode() == 304);
}

测试服务端响应结果变化了,则

@Test
public void givenResourceWasRetrieved_whenRetrievingAgainWithEtag_thenNotModifiedReturned() {
// Given
T existingResource = getApi().create(createNewEntity());
String uriOfResource = baseUri + "/" + existingResource.getId();
Response findOneResponse = RestAssured.given().
header("Accept", "application/json").get(uriOfResource);
String etagValue = findOneResponse.getHeader(HttpHeaders.ETAG);

existingResource.setName(randomAlphabetic(6))
getApi().update(existingResource.setName(randomString));

// When
Response secondFindOneResponse= RestAssured.given().
header("Accept", "application/json").headers("If-None-Match", etagValue)
.get(uriOfResource);

// Then
assertTrue(secondFindOneResponse.getStatusCode() == 200);
}

如果请求带上不正确的etag值并且加上if-match判断,则会返回412Precondition Failed

@Test
public void givenResourceExists_whenRetrievedWithIfMatchIncorrectEtag_then412IsReceived() {
// Given
T existingResource = getApi().create(createNewEntity());

// When
String uriOfResource = baseUri + "/" + existingResource.getId();
Response findOneResponse = RestAssured.given().header("Accept", "application/json").
headers("If-Match", randomAlphabetic(8)).get(uriOfResource);

// Then
assertTrue(findOneResponse.getStatusCode() == 412);
}

github示例地址:https://github.com/eugenp/REST
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: