diff --git a/src/main/java/org/springframework/hateoas/ResourceSupport.java b/src/main/java/org/springframework/hateoas/ResourceSupport.java
index c2cb23ff..cfb5cca4 100755
--- a/src/main/java/org/springframework/hateoas/ResourceSupport.java
+++ b/src/main/java/org/springframework/hateoas/ResourceSupport.java
@@ -98,6 +98,13 @@ public class ResourceSupport implements Identifiable {
return Collections.unmodifiableList(links);
}
+ /**
+ * Removes all {@link Link}s added to the resource so far.
+ */
+ public void removeLinks() {
+ this.links.clear();
+ }
+
/**
* Returns the link with the given rel.
*
diff --git a/src/main/java/org/springframework/hateoas/mvc/HeaderLinksResponseEntity.java b/src/main/java/org/springframework/hateoas/mvc/HeaderLinksResponseEntity.java
new file mode 100644
index 00000000..a9450744
--- /dev/null
+++ b/src/main/java/org/springframework/hateoas/mvc/HeaderLinksResponseEntity.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2013 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.hateoas.mvc;
+
+import java.util.List;
+
+import org.springframework.hateoas.Link;
+import org.springframework.hateoas.Links;
+import org.springframework.hateoas.ResourceProcessor;
+import org.springframework.hateoas.ResourceSupport;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.util.Assert;
+
+/**
+ * Special {@link ResponseEntity} that exposes {@link Link} instances in the contained {@link ResourceSupport} as link
+ * headers instead of in the body. Note, that this class is not intended to be used directly from user code but by
+ * support code that will transparently invoke the header exposure. If you use this class from a controller directly,
+ * the {@link Link}s will not be present in the {@link ResourceSupport} instance anymore when {@link ResourceProcessor}s
+ * kick in.
+ *
+ * @author Oliver Gierke
+ */
+public class HeaderLinksResponseEntity extends ResponseEntity {
+
+ /**
+ * Creates a new {@link HeaderLinksResponseEntity} from the given {@link ResponseEntity}.
+ *
+ * @param entity must not be {@literal null}.
+ */
+ private HeaderLinksResponseEntity(ResponseEntity entity) {
+
+ super(entity.getBody(), getHeadersWithLinks(entity), entity.getStatusCode());
+ entity.getBody().removeLinks();
+ }
+
+ /**
+ * Creates a new {@link HeaderLinksResponseEntity} from the given {@link HttpEntity} by defaulting the status code to
+ * {@link HttpStatus#OK}.
+ *
+ * @param entity must not be {@literal null}.
+ */
+ private HeaderLinksResponseEntity(HttpEntity entity) {
+ this(new ResponseEntity(entity.getBody(), entity.getHeaders(), HttpStatus.OK));
+ }
+
+ /**
+ * Wraps the given {@link HttpEntity} into a {@link HeaderLinksResponseEntity}. Will default the status code to
+ * {@link HttpStatus#OK} if the given value is not a {@link ResponseEntity}.
+ *
+ * @param entity must not be {@literal null}.
+ * @return
+ */
+ public static HeaderLinksResponseEntity wrap(HttpEntity entity) {
+
+ Assert.notNull(entity, "Given HttpEntity must not be null!");
+
+ if (entity instanceof ResponseEntity) {
+ return new HeaderLinksResponseEntity((ResponseEntity) entity);
+ } else {
+ return new HeaderLinksResponseEntity(entity);
+ }
+ }
+
+ /**
+ * Returns the {@link Link}s contained in the {@link ResourceSupport} of the given {@link ResponseEntity} as
+ * {@link HttpHeaders}.
+ *
+ * @param entity must not be {@literal null}.
+ * @return
+ */
+ private static HttpHeaders getHeadersWithLinks(ResponseEntity entity) {
+
+ List links = entity.getBody().getLinks();
+
+ HttpHeaders httpHeaders = new HttpHeaders();
+ httpHeaders.putAll(entity.getHeaders());
+ httpHeaders.add("Link", new Links(links).toString());
+
+ return httpHeaders;
+ }
+}
diff --git a/src/test/java/org/springframework/hateoas/mvc/HeaderLinksResponseEntityUnitTests.java b/src/test/java/org/springframework/hateoas/mvc/HeaderLinksResponseEntityUnitTests.java
new file mode 100644
index 00000000..43b2fea6
--- /dev/null
+++ b/src/test/java/org/springframework/hateoas/mvc/HeaderLinksResponseEntityUnitTests.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2013 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.hateoas.mvc;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+import java.util.List;
+
+import org.hamcrest.Matchers;
+import org.junit.Test;
+import org.springframework.hateoas.Link;
+import org.springframework.hateoas.Resource;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+/**
+ * Unit tests for {@link HeaderLinksResponseEntity}.
+ *
+ * @author Oliver Gierke
+ */
+public class HeaderLinksResponseEntityUnitTests {
+
+ static final Object CONTENT = new Object();
+ static final Link LINK = new Link("href", "rel");
+
+ Resource