DATAREST-835 - Search resources returning a single resource now get and consider ETag and Last-Modified headers.

We now interpret If-None-Match and If-Modified-Since headers on requests to resources backed by query methods returning a single instance only. This allows clients to optimize GET requests to those resources to save bandwidth.
This commit is contained in:
Oliver Gierke
2016-06-10 23:22:07 +02:00
parent 42378ab34d
commit aa7eec4683
11 changed files with 361 additions and 72 deletions

View File

@@ -42,12 +42,12 @@ import org.springframework.data.rest.webmvc.support.DefaultedPageable;
import org.springframework.data.rest.webmvc.support.ETag;
import org.springframework.hateoas.Resource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.HttpRequestMethodNotSupportedException;
/**
@@ -273,7 +273,7 @@ public class RepositoryEntityControllerIntegrationTests extends AbstractControll
Mockito.when(assembler.toFullResource(Mockito.any(Object.class))).thenReturn(resource);
ResponseEntity<Resource<?>> entity = controller.getItemResource(getResourceInformation(Address.class), address.id,
assembler, new LinkedMultiValueMap<String, String>());
assembler, new HttpHeaders());
assertThat(entity.getHeaders().getETag(), is(notNullValue()));
}

View File

@@ -39,6 +39,7 @@ import org.springframework.hateoas.PagedResources;
import org.springframework.hateoas.ResourceSupport;
import org.springframework.hateoas.Resources;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.ContextConfiguration;
@@ -100,8 +101,8 @@ public class RepositorySearchControllerIntegrationTests extends AbstractControll
MultiValueMap<String, Object> parameters = new LinkedMultiValueMap<String, Object>(1);
parameters.add("firstname", "John");
ResponseEntity<Object> response = controller.executeSearch(resourceInformation, parameters, "firstname", PAGEABLE,
null, assembler);
ResponseEntity<?> response = controller.executeSearch(resourceInformation, parameters, "firstname", PAGEABLE, null,
assembler, new HttpHeaders());
ResourceTester tester = ResourceTester.of(response.getBody());
PagedResources<Object> pagedResources = tester.assertIsPage();
@@ -190,8 +191,8 @@ public class RepositorySearchControllerIntegrationTests extends AbstractControll
RootResourceInformation resourceInformation = getResourceInformation(Book.class);
ResponseEntity<Object> result = controller.executeSearch(resourceInformation, parameters, "findByAuthorsContains",
PAGEABLE, null, assembler);
ResponseEntity<?> result = controller.executeSearch(resourceInformation, parameters, "findByAuthorsContains",
PAGEABLE, null, assembler, new HttpHeaders());
assertThat(result.getBody(), is(instanceOf(Resources.class)));
}

View File

@@ -21,6 +21,7 @@ import java.util.Map;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.annotation.Version;
import org.springframework.data.mongodb.core.mapping.Document;
import com.fasterxml.jackson.annotation.JsonIgnore;
@@ -36,6 +37,7 @@ public class Profile {
private Long person;
private @JsonProperty(required = true) String type;
private @LastModifiedDate Date lastModifiedDate;
private @Version Long version;
private @JsonProperty("renamed") String aliased;
private Map<String, String> metadata = new HashMap<String, String>();

View File

@@ -343,4 +343,34 @@ public class MongoWebTests extends CommonWebTests {
mvc.perform(get(href)).andExpect(status().isOk());
}
/**
* @see DATAREST-835
*/
@Test
public void exposesETagHeaderForSearchResourceYieldingItemResource() throws Exception {
Link link = client.discoverUnique("profiles", "search", "findById");
Profile profile = repository.findAll().iterator().next();
mvc.perform(get(link.expand(profile.getId()).getHref()))//
.andExpect(header().string("ETag", is("\"0\"")))//
.andExpect(header().string("Last-Modified", is(notNullValue())));
}
/**
* @see DATAREST-835
*/
@Test
public void doesNotAddETagHeaderForCollectionQueryResource() throws Exception {
Link link = client.discoverUnique("profiles", "search", "findByType");
Profile profile = repository.findAll().iterator().next();
mvc.perform(get(link.expand(profile.getType()).getHref()))//
.andExpect(header().string("ETag", is(nullValue())))//
.andExpect(header().string("Last-Modified", is(nullValue())));
}
}