private Response cacheAwareResponse( Request request, String entity, EntityTag etag, Date lastModified, int maxAge ) { final Response.ResponseBuilder builderLastMod = request.evaluatePreconditions(lastModified); if (builderLastMod != null) { return builderLastMod.build(); } final Response.ResponseBuilder builderEtag = request.evaluatePreconditions(etag); if (builderEtag != null) { return builderEtag.build(); } final CacheControl cc = new CacheControl(); cc.setMaxAge(maxAge); return Response.ok(entity) .tag(etag) .lastModified(lastModified) .cacheControl(cc) .build(); }
@GET @Path("{derivate}{path: (/[^?#]*)?}") public Response show(@Context HttpServletRequest request, @Context Request jaxReq, @Context ServletContext context, @Context ServletConfig config) throws Exception { MCRContent content = getContent(request); String contentETag = content.getETag(); Response.ResponseBuilder responseBuilder = null; EntityTag eTag = contentETag == null ? null : new EntityTag(contentETag); if (eTag != null) { responseBuilder = jaxReq.evaluatePreconditions(eTag); } if (responseBuilder == null) { responseBuilder = Response.ok(content.asByteArray(), MediaType.valueOf(content.getMimeType())); } if (eTag != null) { responseBuilder.tag(eTag); } if (content.isUsingSession()) { CacheControl cc = new CacheControl(); cc.setPrivate(true); cc.setMaxAge(0); cc.setMustRevalidate(true); responseBuilder.cacheControl(cc); } return responseBuilder.build(); }
@GET public Response get(@HeaderParam(HttpHeaders.IF_NONE_MATCH) String ifNoneMatch, @HeaderParam(HttpHeaders.IF_MODIFIED_SINCE) Date ifModifiedSince) { // Check the ETags to see if the resource has changed... if (ifNoneMatch != null) { for (String eTag : ETAG_SPLITTER.split(ifNoneMatch)) { if ("*".equals(eTag) || ETAG.equals(EntityTag.valueOf(eTag))) { return NOT_MODIFIED; } } } // Check the last modification time if (ifModifiedSince != null && ifModifiedSince.after(LAST_MODIFIED)) { return NOT_MODIFIED; } return Response.ok().lastModified(LAST_MODIFIED).tag(ETAG).type(CONTENT_TYPE).entity(FAVICON).build(); }
@Override public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException { final EntityTag entityTag = getEntityTag(responseContext); final Date lastModified = getLastModified(responseContext); responseContext.getHeaders().putSingle(HttpHeaders.CACHE_CONTROL, cacheControl); writeHeader(responseContext, HttpHeaders.ETAG, entityTag); writeHeader(responseContext, HttpHeaders.LAST_MODIFIED, lastModified == null ? null : HttpUtils.getHttpDateFormat().format(lastModified)); final Response.ResponseBuilder builder = evaluatePreconditions(requestContext, entityTag, lastModified); if (builder != null) { responseContext.setStatusInfo(Response.Status.NO_CONTENT); responseContext.setEntity(null); } }
@Test public void testCustomerResource() throws Exception { WebTarget customerTarget = client.target("http://localhost:8080/services/customers/1"); Response response = customerTarget.request().get(); Assert.assertEquals(200, response.getStatus()); Customer cust = response.readEntity(Customer.class); EntityTag etag = response.getEntityTag(); response.close(); System.out.println("Doing a conditional GET with ETag: " + etag.toString()); response = customerTarget.request() .header("If-None-Match", etag).get(); Assert.assertEquals(304, response.getStatus()); response.close(); // Update and send a bad etag with conditional PUT cust.setCity("Bedford"); response = customerTarget.request() .header("If-Match", "JUNK") .put(Entity.xml(cust)); Assert.assertEquals(412, response.getStatus()); response.close(); }
@GET @Produces(MediaType.APPLICATION_JSON) public Response getJSON(@Context Request request) { EntityTag etag = new EntityTag(data().getVersioned().getUniqueId().toString()); ResponseBuilder builder = request.evaluatePreconditions(etag); if (builder != null) { return builder.build(); } RegionSearchRequest search = new RegionSearchRequest(); search.setPagingRequest(PagingRequest.ALL); // may need to add paging search.setChildrenOfId(data().getVersioned().getUniqueId()); RegionSearchResult children = data().getRegionMaster().search(search); data().setRegionChildren(children.getDocuments()); for (UniqueId parentId : data().getRegion().getRegion().getParentRegionIds()) { RegionDocument parent = data().getRegionMaster().get(parentId); data().getRegionParents().add(parent); } FlexiBean out = createRootData(); String json = getFreemarker().build(JSON_DIR + "region.ftl", out); return Response.ok(json).tag(etag).build(); }
@GET @Produces(MediaType.APPLICATION_JSON) public Response getJSON(@Context final Request request) { final EntityTag etag = new EntityTag(data().getConfig().getUniqueId().toString()); final ResponseBuilder builder = request.evaluatePreconditions(etag); if (builder != null) { return builder.build(); } final FlexiBean out = createRootData(); final ConfigDocument doc = data().getConfig(); final String jsonConfig = StringUtils.stripToNull(toJSON(doc.getConfig().getValue(), doc.getType())); if (jsonConfig != null) { out.put("configJSON", jsonConfig); } out.put(CONFIG_XML, StringEscapeUtils.escapeJava(createBeanXML(doc.getConfig().getValue()))); out.put("type", doc.getType().getSimpleName()); final String json = getFreemarker().build(JSON_DIR + "config.ftl", out); return Response.ok(json).tag(etag).build(); }
@GET @Produces(MediaType.APPLICATION_JSON) public Response getJSON(@Context Request request) { EntityTag etag = new EntityTag(data().getVersioned().getUniqueId().toString()); ResponseBuilder builder = request.evaluatePreconditions(etag); if (builder != null) { return builder.build(); } FlexiBean out = createRootData(); ConfigDocument doc = data().getVersioned(); String jsonConfig = toJSON(doc.getConfig().getValue()); if (jsonConfig != null) { out.put("configJSON", jsonConfig); } else { out.put(CONFIG_XML, StringEscapeUtils.escapeJavaScript(createBeanXML(doc.getConfig().getValue()))); } out.put("type", data().getTypeMap().inverse().get(doc.getType())); String json = getFreemarker().build(JSON_DIR + "config.ftl", out); return Response.ok(json).tag(etag).build(); }
@Test public void shouldGetStatusResponseEtag() { ZonedDateTime now = ZonedDateTime.now(); doReturn(Optional.of(Job.Builder.build(job -> { job.setId("123"); job.setStatus(JobStatus.EXECUTING); job.setStatusTimestamp(Date.from(now.toInstant())); }))).when(mockJobManager).getJob("123"); EntityTag entityTag = EntityTagGenerator.entityTagFromLong(now.toInstant().toEpochMilli()); doReturn(Response.notModified(entityTag)).when(mockRequest).evaluatePreconditions(any(EntityTag.class)); Response response = statusResource.getStatus("123"); assertThat(response.getStatus()).isEqualTo(304); assertThat(response.getEntity()).isNull(); assertThat(response.getEntityTag()).isEqualToComparingFieldByField(entityTag); }
@Test public void testPatchEtagUpdated() throws Exception { // Create object final FcrepoResponse createResp = create(); final EntityTag createdEtag = EntityTag.valueOf(createResp.getHeaderValue(ETAG)); final InputStream body = new ByteArrayInputStream(sparqlUpdate.getBytes()); // Update triples with sparql update final FcrepoResponse response = client.patch(url) .body(body) .ifMatch("\"" + createdEtag.getValue() + "\"") .perform(); final EntityTag updateEtag = EntityTag.valueOf(response.getHeaderValue(ETAG)); assertEquals(NO_CONTENT.getStatusCode(), response.getStatusCode()); assertNotEquals("Etag did not change after patch", createdEtag, updateEtag); }
@Override public Response put(Model model) { Model existing = getGraphStore().getModel(getURI().toString()); if (!existing.isEmpty()) // remove existing representation { EntityTag entityTag = new EntityTag(Long.toHexString(ModelUtils.hashModel(model))); ResponseBuilder rb = getRequest().evaluatePreconditions(entityTag); if (rb != null) { if (log.isDebugEnabled()) log.debug("PUT preconditions were not met for resource: {} with entity tag: {}", this, entityTag); return rb.build(); } } if (log.isDebugEnabled()) log.debug("PUT GRAPH {} to GraphStore {}", getURI(), getGraphStore()); getGraphStore().put(model, Boolean.FALSE, getURI()); if (existing.isEmpty()) return Response.created(getURI()).build(); else return Response.ok(model).build(); }
@javax.ws.rs.GET public Response method() { Response.ResponseBuilder responseBuilder = Response.ok(); responseBuilder.header("X-Test", "Hello"); responseBuilder.cacheControl(CacheControl.valueOf("")); responseBuilder.contentLocation(URI.create("")); responseBuilder.cookie(); responseBuilder.entity(12d); responseBuilder.expires(new Date()); responseBuilder.language(Locale.ENGLISH); responseBuilder.encoding("UTF-8"); responseBuilder.lastModified(new Date()); responseBuilder.link(URI.create(""), "rel"); responseBuilder.location(URI.create("")); responseBuilder.status(433); responseBuilder.tag(new EntityTag("")); responseBuilder.type(MediaType.APPLICATION_JSON_TYPE); responseBuilder.variants(new LinkedList<>()); return responseBuilder.build(); }
/** * if-none-matchヘッダで転送量削減 * * @throws Exception */ @Test public void testIfNoneMatch() throws Exception { //ハッシュファイルはGradleタスクで書き出すのでIDEでテスト実行 //するとハッシュファイルが出来なくてアレなのでassume使っとく URL resource = getClass().getResource("/static/hello.txt.md5"); Assume.assumeThat(resource, is(not(nullValue()))); Response response = target("static/hello.txt").request().get(); assertThat("Status code", response.getStatusInfo(), is(Status.OK)); EntityTag eTag = response.getEntityTag(); assertThat("ETag", eTag, is(not(nullValue()))); Response response2 = target("static/hello.txt").request() .header(HttpHeaders.IF_NONE_MATCH, eTag).get(); assertThat("Status code", response2.getStatusInfo(), is(Status.NOT_MODIFIED)); assertThat("Count", counter.getCount(), is(2)); }
/** Check if ETag is generated for a list of JSON */ @Test public void filterListEntityTest() throws Exception { final ContainerResponse response = resourceLauncher.service( HttpMethod.GET, SERVICE_PATH + "/list", BASE_URI, null, null, null); assertEquals(response.getStatus(), OK.getStatusCode()); // check entity Assert.assertEquals(response.getEntity(), Arrays.asList("a", "b", "c")); // Check etag List<Object> headerTags = response.getHttpHeaders().get("ETag"); Assert.assertNotNull(headerTags); Assert.assertEquals(headerTags.size(), 1); Assert.assertEquals(headerTags.get(0), new EntityTag("900150983cd24fb0d6963f7d28e17f72")); }
/** Check if ETag is added in response if we're also using a custom header */ @Test public void useExistingHeaders() throws Exception { final ContainerResponse response = resourceLauncher.service( HttpMethod.GET, SERVICE_PATH + "/modify", BASE_URI, null, null, null); assertEquals(response.getStatus(), OK.getStatusCode()); // check entity Assert.assertEquals(response.getEntity(), "helloContent"); // headers = 2 Assert.assertEquals(response.getHttpHeaders().keySet().size(), 3); // Check custom header List<Object> customTags = response.getHttpHeaders().get(HttpHeaders.CONTENT_DISPOSITION); Assert.assertNotNull(customTags); Assert.assertEquals(customTags.size(), 1); Assert.assertEquals(customTags.get(0), "attachment; filename=my.json"); // Check etag List<Object> headerTags = response.getHttpHeaders().get("ETag"); Assert.assertNotNull(headerTags); Assert.assertEquals(headerTags.get(0), new EntityTag("77e671575d94cfd400ed26c5ef08e0fd")); }
/** Check if ETag is generated for a simple entity of JSON */ @Test public void filterSingleEntityTest() throws Exception { final ContainerResponse response = resourceLauncher.service( HttpMethod.GET, SERVICE_PATH + "/single", BASE_URI, null, null, null); assertEquals(response.getStatus(), OK.getStatusCode()); // check entity Assert.assertEquals(response.getEntity(), "hello"); // Check etag List<Object> headerTags = response.getHttpHeaders().get("ETag"); Assert.assertNotNull(headerTags); Assert.assertEquals(headerTags.size(), 1); Assert.assertEquals(headerTags.get(0), new EntityTag("5d41402abc4b2a76b9719d911017c592")); }
/** Check if ETag sent with header is redirecting to NOT_MODIFIED */ @Test public void filterListEntityTestWithEtag() throws Exception { Map<String, List<String>> headers = new HashMap<>(); headers.put( "If-None-Match", Collections.singletonList(new EntityTag("900150983cd24fb0d6963f7d28e17f72").toString())); final ContainerResponse response = resourceLauncher.service( HttpMethod.GET, SERVICE_PATH + "/list", BASE_URI, headers, null, null); assertEquals(response.getStatus(), NOT_MODIFIED.getStatusCode()); // check null body Assert.assertNull(response.getEntity()); }
/** Check if ETag sent with header is redirecting to NOT_MODIFIED */ @Test public void filterSingleEntityTestWithEtag() throws Exception { Map<String, List<String>> headers = new HashMap<>(); headers.put( "If-None-Match", Collections.singletonList(new EntityTag("5d41402abc4b2a76b9719d911017c592").toString())); final ContainerResponse response = resourceLauncher.service( HttpMethod.GET, SERVICE_PATH + "/single", BASE_URI, headers, null, null); assertEquals(response.getStatus(), NOT_MODIFIED.getStatusCode()); // check null body Assert.assertNull(response.getEntity()); }
private static String etag2hash(String etag) { String hash; try { hash = EntityTag.valueOf(etag).getValue(); } catch (Exception e) { return null; } // Jetty insists on adding a -gzip suffix to ETags sometimes. If it's there, then strip it off. if (hash.endsWith("-gzip")) { hash = hash.substring(0, hash.length() - 5); } return hash; }
@GET @Path("{id}") @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) public Response getPugBy( @PathParam("id") String id, @Context Request request ) { Pug pug = PugsRepository.findById( id ); if ( pug == null ) { return Response.status( 404 ).build(); } //etag for this resource EntityTag etag = new EntityTag( Integer.toString( pug.hashCode() ) ); //evaluate cache Response.ResponseBuilder builder = request.evaluatePreconditions( etag ); // cached resource did change -> serve updated content if ( builder == null ) { builder = Response.ok( pug ); builder.tag( etag ); } return builder.build(); }
@PUT @Path("{id}") @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @Consumes(MediaType.APPLICATION_JSON) public Response createOrUpdatePug( @PathParam("id") String id, Pug pug, @Context Request request ) throws URISyntaxException { Pug actualPug = PugsRepository.findById( id ); Response.ResponseBuilder builder = null; if ( putIsAUpdate( actualPug ) ) { EntityTag etag = new EntityTag( Integer.toString( actualPug.hashCode() ) ); builder = request.evaluatePreconditions( etag ); // client is not up to date (send back 412) if ( builder != null ) { return builder.build(); } PugsRepository.update( pug ); } else { PugsRepository.create(id, pug ); } builder = Response.created( new URI( "/pugs/" + id ) ); return builder.build(); }
@Test public void conditionalPut() throws URISyntaxException { Pug originalPug = new Pug( 1, "Dorinha", 10, new URI( "http://api.puglovers.com/pugs/1" ), new URI( "http://api.puglovers.com/pics/1" ) ); Response responsePut = target.path( "pugs/1" ).request().put( Entity.json( originalPug ) ); assertEquals( 201, responsePut.getStatus() ); Response response200 = target.path( "pugs/1" ).request().accept( MediaType.APPLICATION_JSON ).get(); EntityTag originalTag = response200.getEntityTag(); assertEquals( 200, response200.getStatus() ); //another concurrent request with right tag Pug concurrentPug = new Pug( 1, "Slim Dorinha", 11, new URI( "http://api.puglovers.com/pugs/1" ), new URI( "http://api.puglovers.com/pic/1" ) ); Response responsePutSlim = target.path( "pugs/1" ).request().header( "If-Match", originalTag ).put( Entity.json( concurrentPug ) ); assertEquals( 201, responsePutSlim.getStatus() ); Response responseNewPug = target.path( "pugs/1" ).request().accept( MediaType.APPLICATION_JSON ).get(); EntityTag newTag = responseNewPug.getEntityTag(); assertEquals( 200, responseNewPug.getStatus() ); //update with the first version //Only perform the action if the client supplied entity matches the same entity on server originalPug.setPeso( 1 ); Response response412 = target.path( "pugs/1" ).request().header( "If-Match", originalTag ).put( Entity.json( originalPug ) ); assertEquals( 412, response412.getStatus() ); }
@Override public void filter(final ContainerRequestContext reqCtx, final ContainerResponseContext resCtx) throws IOException { if (resCtx.getEntityTag() == null) { AbstractAnnotatedBean annotated = null; if (resCtx.getEntity() instanceof AbstractAnnotatedBean) { annotated = (AbstractAnnotatedBean) resCtx.getEntity(); } else if (resCtx.getEntity() instanceof ProvisioningResult) { EntityTO entity = ((ProvisioningResult<?>) resCtx.getEntity()).getEntity(); if (entity instanceof AbstractAnnotatedBean) { annotated = (AbstractAnnotatedBean) entity; } } if (annotated != null) { String etagValue = annotated.getETagValue(); if (StringUtils.isNotBlank(etagValue)) { resCtx.getHeaders().add(HttpHeaders.ETAG, new EntityTag(etagValue).toString()); } } } }
@Override public void filter(final ContainerRequestContext reqCtx, final ContainerResponseContext resCtx) throws IOException { if (resCtx.getEntityTag() == null) { Date lastModified = null; if (resCtx.getEntity() instanceof SCIMUser) { lastModified = ((SCIMUser) resCtx.getEntity()).getMeta().getLastModified(); if (resCtx.getEntity() instanceof SCIMGroup) { lastModified = ((SCIMGroup) resCtx.getEntity()).getMeta().getLastModified(); } if (lastModified != null) { String etagValue = String.valueOf(lastModified.getTime()); if (StringUtils.isNotBlank(etagValue)) { resCtx.getHeaders().add(HttpHeaders.ETAG, new EntityTag(etagValue, true).toString()); } } } } }
/** * Validation of client cache. * * @return response with HTTP 304 if cache valid or null if cache not valid */ public Response validateClientCache() { // Get Request parameters from URI String resID = uriInfo.getPathSegments().get(1).getPath(); ResourceInfo resInfo = pandaSettings.getResourceMap().getMap().get(resID); String filePath = resInfo.getFilePath(); if (filePath != null) { File file = new File(filePath); if (file.exists()) { lastModified = new Date(file.lastModified()); eTag = new EntityTag(resID + "_" + lastModified.getTime(), false); ResponseBuilder builder = request.evaluatePreconditions(lastModified, eTag); // resource not modified if (builder != null) { return builder.cacheControl(pandaSettings.getCacheControl()) .lastModified(lastModified).tag(eTag).build(); } } else { throw new WebApplicationException(404); } } return null; }
/** * Add multiple values from list to cache. Values need to have SubURIs to * reconstruct entire URI! * * @param valList list of values * @param resourceType type of resource * @param resID unique ID of resource * @param eTag entity tag of resource for cache validation */ public void addResourceValues(ValueExchangeExt valList, DataResourceType resourceType, String resID, EntityTag eTag) { this.eTags.put(resID, eTag); valueCacheWriteLock.lock(); try { String baseURI = valList.getBaseURI(); for (Value v : valList.getValue()) { String subURI = v.getSubURI(); if (subURI == null) { throw new WebApplicationException(422); } else { addResourceValue(baseURI + v.getSubURI(), v.getValue(), v.getType(), resourceType); } } } finally { valueCacheWriteLock.unlock(); } }
@Test public void testFailedEvaluatePreconditions() throws Exception { injector.setOauthAuthenticationWithEducationRole(); mockApplicationEntity(); mockBulkExtractEntity(null); HttpRequestContext context = new HttpRequestContextAdapter() { @Override public ResponseBuilder evaluatePreconditions(Date lastModified, EntityTag eTag) { return Responses.preconditionFailed(); } }; Response res = bulkExtract.getEdOrgExtractResponse(context, null, null); assertEquals(412, res.getStatus()); }
@Test public void testCache() { when(mockRequest.evaluatePreconditions(eq(from(binaryTime)), any(EntityTag.class))) .thenReturn(status(PRECONDITION_FAILED)); when(mockResource.getBinary()).thenReturn(of(testBinary)); final File entity = new File(getClass().getResource("/simpleData.txt").getFile()); final PutHandler putHandler = new PutHandler(mockLdpRequest, entity, mockResourceService, mockIoService, mockBinaryService, null); assertThrows(WebApplicationException.class, () -> putHandler.setResource(mockResource)); }
@Test public void testGetLdprs() { when(mockHeaders.getAcceptableMediaTypes()).thenReturn(singletonList(TEXT_TURTLE_TYPE)); final GetHandler getHandler = new GetHandler(mockLdpRequest, mockResourceService, mockIoService, mockBinaryService, null); final Response res = getHandler.getRepresentation(mockResource).build(); assertEquals(OK, res.getStatusInfo()); assertTrue(res.getLinks().stream().anyMatch(hasType(LDP.Resource))); assertTrue(res.getLinks().stream().anyMatch(hasType(LDP.RDFSource))); assertFalse(res.getLinks().stream().anyMatch(hasType(LDP.Container))); assertNull(res.getHeaderString(ACCEPT_POST)); assertEquals(APPLICATION_SPARQL_UPDATE, res.getHeaderString(ACCEPT_PATCH)); assertNull(res.getHeaderString(PREFERENCE_APPLIED)); assertNull(res.getHeaderString(ACCEPT_RANGES)); assertTrue(TEXT_TURTLE_TYPE.isCompatible(res.getMediaType())); assertTrue(res.getMediaType().isCompatible(TEXT_TURTLE_TYPE)); assertEquals(from(time), res.getLastModified()); final String allow = res.getHeaderString(ALLOW); assertTrue(allow.contains(GET)); assertTrue(allow.contains(HEAD)); assertTrue(allow.contains(OPTIONS)); assertTrue(allow.contains(PUT)); assertTrue(allow.contains(DELETE)); assertTrue(allow.contains(PATCH)); assertFalse(allow.contains(POST)); final EntityTag etag = res.getEntityTag(); assertTrue(etag.isWeak()); assertEquals(md5Hex(time + baseUrl), etag.getValue()); final List<Object> varies = res.getHeaders().get(VARY); assertFalse(varies.contains(RANGE)); assertFalse(varies.contains(WANT_DIGEST)); assertTrue(varies.contains(ACCEPT_DATETIME)); assertTrue(varies.contains(PREFER)); }
@Test public void testCache() { when(mockRequest.evaluatePreconditions(eq(from(time)), any(EntityTag.class))) .thenReturn(notModified()); when(mockHeaders.getAcceptableMediaTypes()).thenReturn(singletonList(TEXT_TURTLE_TYPE)); final GetHandler getHandler = new GetHandler(mockLdpRequest, mockResourceService, mockIoService, mockBinaryService, baseUrl); assertThrows(WebApplicationException.class, () -> getHandler.getRepresentation(mockResource)); }
@Test public void testCacheLdpNr() { when(mockResource.getBinary()).thenReturn(of(testBinary)); when(mockResource.getInteractionModel()).thenReturn(LDP.NonRDFSource); when(mockRequest.evaluatePreconditions(eq(from(binaryTime)), any(EntityTag.class))) .thenReturn(notModified()); when(mockHeaders.getAcceptableMediaTypes()).thenReturn(singletonList(WILDCARD_TYPE)); final GetHandler getHandler = new GetHandler(mockLdpRequest, mockResourceService, mockIoService, mockBinaryService, baseUrl); assertThrows(WebApplicationException.class, () -> getHandler.getRepresentation(mockResource)); }
@Test public void testMinimalLdprs() { when(mockHeaders.getAcceptableMediaTypes()).thenReturn(singletonList(APPLICATION_LD_JSON_TYPE)); when(mockLdpRequest.getPrefer()).thenReturn(Prefer.valueOf("return=minimal")); final GetHandler getHandler = new GetHandler(mockLdpRequest, mockResourceService, mockIoService, mockBinaryService, baseUrl); final Response res = getHandler.getRepresentation(mockResource).build(); assertEquals(NO_CONTENT, res.getStatusInfo()); assertTrue(res.getLinks().stream().anyMatch(hasType(LDP.Resource))); assertTrue(res.getLinks().stream().anyMatch(hasType(LDP.RDFSource))); assertFalse(res.getLinks().stream().anyMatch(hasType(LDP.Container))); assertNull(res.getHeaderString(ACCEPT_POST)); assertEquals(APPLICATION_SPARQL_UPDATE, res.getHeaderString(ACCEPT_PATCH)); assertEquals("return=minimal", res.getHeaderString(PREFERENCE_APPLIED)); assertNull(res.getHeaderString(ACCEPT_RANGES)); assertTrue(APPLICATION_LD_JSON_TYPE.isCompatible(res.getMediaType())); assertTrue(res.getMediaType().isCompatible(APPLICATION_LD_JSON_TYPE)); assertEquals(from(time), res.getLastModified()); final String allow = res.getHeaderString(ALLOW); assertTrue(allow.contains(GET)); assertTrue(allow.contains(HEAD)); assertTrue(allow.contains(OPTIONS)); assertTrue(allow.contains(PUT)); assertTrue(allow.contains(DELETE)); assertTrue(allow.contains(PATCH)); assertFalse(allow.contains(POST)); final EntityTag etag = res.getEntityTag(); assertTrue(etag.isWeak()); assertEquals(md5Hex(time + baseUrl), etag.getValue()); final List<Object> varies = res.getHeaders().get(VARY); assertFalse(varies.contains(RANGE)); assertFalse(varies.contains(WANT_DIGEST)); assertTrue(varies.contains(ACCEPT_DATETIME)); assertTrue(varies.contains(PREFER)); }
@Test public void testConflict() { when(mockRequest.evaluatePreconditions(any(Date.class), any(EntityTag.class))) .thenReturn(status(CONFLICT)); when(mockLdpRequest.getPath()).thenReturn("resource"); final PatchHandler patchHandler = new PatchHandler(mockLdpRequest, insert, mockResourceService, mockIoService, null); assertThrows(WebApplicationException.class, () -> patchHandler.updateResource(mockResource)); }
@Test public void testCache() { when(mockRequest.evaluatePreconditions(eq(from(time)), any(EntityTag.class))) .thenReturn(status(PRECONDITION_FAILED)); final DeleteHandler handler = new DeleteHandler(mockLdpRequest, mockResourceService, baseUrl); assertThrows(WebApplicationException.class, () -> handler.deleteResource(mockResource)); }
private void prepareDiscoveryEntity() throws Exception { if (discoveryJson == null) { final String schemaUrl = UriBuilder.fromUri(baseURI) .path(".well-known/outland.yaml") .build() .toASCIIString(); Map<String, String> discovery = Maps.newHashMap(); discovery.put("schema_url", schemaUrl); discovery.put("schema_type", "swagger-2.0"); discoveryJson = gson.toJson(discovery); discoveryEtag = new EntityTag(generateEtag(discoveryJson)); } }
/** * Build a response given a concrete request. If the request contain an <code>if-modified-since</code> or * <code>if-none-match</code> header this will be checked against the entity given to the builder returning * a response with status not modified if appropriate. */ public Response build(Request req) { EntityTag eTag = new EntityTag(Integer.toString(entity.hashCode())); Date lastModified = entity instanceof AbstractAuditable ? ((AbstractAuditable) entity).getLastModifiedTime() : Date.from(Instant.now()); Response.ResponseBuilder notModifiedBuilder = req.evaluatePreconditions(lastModified, eTag); if (notModifiedBuilder != null) { return notModifiedBuilder.build(); } Map<String, String> parameters = new ConcurrentHashMap<>(); if (name != null) { parameters.put("concept", name); } if (version != null) { parameters.put("v", version); } MediaType type = getMediaType(parameters, supportsContentTypeParameter); Response.ResponseBuilder b = Response.ok(mapper.apply(entity)) .type(type) .tag(eTag) .lastModified(lastModified); if (maxAge != null) { CacheControl cc = new CacheControl(); cc.setMaxAge(maxAge); b.cacheControl(cc).expires(Date.from(Instant.now().plusSeconds(maxAge))); } return b.build(); }
@GET public Response get(@Context Request request) { ClimateDto currentClimate = stockholmClimateRepository.get(); EntityTag currentETag = eTagGenerator.eTagFor(currentClimate); Optional<Response> notModifiedResponse = evaluateETagPrecondition(request, currentETag); if (notModifiedResponse.isPresent()) return notModifiedResponse.get(); return Response.ok(currentClimate).tag(currentETag).build(); }
@PUT public Response put(@Context Request request, @NotNull ClimateDto climate) { synchronized (transactionLock) { ClimateDto currentClimate = stockholmClimateRepository.get(); EntityTag currentETag = eTagGenerator.eTagFor(currentClimate); Optional<Response> preconditionFailedResponse = evaluateETagPrecondition(request, currentETag); if (preconditionFailedResponse.isPresent()) return preconditionFailedResponse.get(); stockholmClimateRepository.save(climate); } EntityTag eTag = eTagGenerator.eTagFor(climate); return Response.noContent().tag(eTag).build(); }