DATAREST-292, DATAREST-296 - RepositoryLinkBuilder now honors absolute base URIs.

In case a base URI is an absolute one, we now rely on only the base URI as foundation for all links created. Relative base URIs are considered are considered an amendment to the current server base up until the servlet mapping. The latter allows to create a dedicated URI namespace for Spring Data REST exposed resources.
This commit is contained in:
Oliver Gierke
2014-04-29 09:54:17 +02:00
parent 45ef259826
commit b69b715a66
2 changed files with 111 additions and 2 deletions

View File

@@ -20,30 +20,69 @@ import java.net.URI;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.rest.core.mapping.ResourceMetadata;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.LinkBuilder;
import org.springframework.hateoas.core.LinkBuilderSupport;
import org.springframework.util.Assert;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import org.springframework.web.util.UriComponentsBuilder;
/**
* {@link LinkBuilder} to be able to create links pointing to repositories.
*
* @author Oliver Gierke
*/
public class RepositoryLinkBuilder extends LinkBuilderSupport<RepositoryLinkBuilder> {
private final ResourceMetadata metadata;
/**
* Creates a new {@link RepositoryLinkBuilder} with the given {@link ResourceMetadata} and base {@link URI}.
*
* @param metadata must not be {@literal null}.
* @param baseUri
*/
public RepositoryLinkBuilder(ResourceMetadata metadata, URI baseUri) {
this(metadata, prepareBuilder(baseUri, metadata));
}
/**
* Creates a new {@link RepositoryLinkBuilder} with the given {@link ResourceMetadata} and
* {@link UriComponentsBuilder}.
*
* @param metadata must not be {@literal null}.
* @param builder must not be {@literal null}.
*/
private RepositoryLinkBuilder(ResourceMetadata metadata, UriComponentsBuilder builder) {
super(builder);
Assert.notNull(metadata, "ResourceMetadata must not be null!");
this.metadata = metadata;
}
/**
* Prepares the {@link UriComponentsBuilder} pointing to the root repository path. If the given URI is an absolute one
* (starting with {@code http://}) we'll use it as is and fallback to lookup the root URI of the current request's
* servlet mapping appending the base URI.
*
* @param baseUri must not be {@literal null}.
* @param metadata must not be {@literal null}.
* @return
*/
private static UriComponentsBuilder prepareBuilder(URI baseUri, ResourceMetadata metadata) {
ServletUriComponentsBuilder builder = ServletUriComponentsBuilder.fromCurrentServletMapping();
return builder.path(baseUri.toString()).path(metadata.getPath().toString());
Assert.notNull(baseUri, "Base URI must not be null!");
Assert.notNull(metadata, "ResourceMetadata must not be null!");
UriComponentsBuilder builder = baseUri.isAbsolute() ? UriComponentsBuilder.fromUri(baseUri)
: ServletUriComponentsBuilder.fromCurrentServletMapping().path(baseUri.toString());
return builder.path(metadata.getPath().toString());
}
/*
* (non-Javadoc)
* @see org.springframework.hateoas.core.LinkBuilderSupport#slash(java.lang.Object)
*/
@Override
public RepositoryLinkBuilder slash(Object object) {

View File

@@ -0,0 +1,70 @@
/*
* Copyright 2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.rest.webmvc.support;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import java.net.URI;
import org.junit.Test;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.rest.core.mapping.MappingResourceMetadata;
import org.springframework.data.rest.core.mapping.ResourceMetadata;
import org.springframework.data.rest.webmvc.WebTestUtils;
import org.springframework.data.rest.webmvc.mongodb.Profile;
import org.springframework.hateoas.Link;
/**
* Unit tests for {@link RepositoryLinkBuilder}.
*
* @author Oliver Gierke
*/
public class RepositoryLinkBuildUnitTests {
MongoMappingContext context = new MongoMappingContext();
/**
* @see DATAREST-292
*/
@Test
public void usesCurrentRequestsUriBaseForRelativeBaseUri() {
WebTestUtils.initWebTest();
assertRootUriFor("api", "http://localhost/api/profile");
}
/**
* @see DATAREST-292, DATAREST-296
*/
@Test
public void usesBaseUriOnlyIfItIsAbsolute() {
assertRootUriFor("http://foobar/api", "http://foobar/api/profile");
}
private void assertRootUriFor(String baseUri, String expectedUri) {
MongoPersistentEntity<?> entity = context.getPersistentEntity(Profile.class);
ResourceMetadata metadata = new MappingResourceMetadata(entity);
RepositoryLinkBuilder builder = new RepositoryLinkBuilder(metadata, URI.create(baseUri));
Link link = builder.withSelfRel();
assertThat(link.getHref(), is(expectedUri));
}
}