Skip to content

Commit c4805ae

Browse files
committed
#886 - Polishing.
Moved section on forward header handling to the link building section of the documentation describing server side components. Switched to sentence-per-line style for the newly introduced content. Pruned a couple of details about which headers are forwarded as what exactly is supported is likely to change with the components in Spring Framework. A bit of rewording to avoid the impression that Spring HATEOAS itself is providing support for the header forwarding. Re-ordered the server side support section before the media type one. Some polishing on the inline code examples (syntax highlighting etc.) Original pull request: #887.
1 parent 2957c91 commit c4805ae

File tree

3 files changed

+95
-116
lines changed

3 files changed

+95
-116
lines changed

src/main/asciidoc/configuration.adoc

Lines changed: 0 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
[[configuration]]
22
= Configuration
3-
:code-dir: ../../../src/docs/java/org/springframework/hateoas
4-
:resource-dir: ../../../src/docs/resources/org/springframework/hateoas
53

64
This section describes how to configure Spring HATEOAS.
75

@@ -15,110 +13,3 @@ To let the `RepresentationModel` subtypes be rendered according to the specifica
1513
* By default, it enables `@EnableEntityLinks` (see <<fundamentals.obtaining-links.entity-links>>) and automatically picks up `EntityLinks` implementations and bundles them into a `DelegatingEntityLinks` instance that you can autowire.
1614
* It automatically picks up all `RelProvider` implementations in the `ApplicationContext` and bundles them into a `DelegatingRelProvider` that you can autowire. It registers providers to consider `@Relation` on domain types as well as Spring MVC controllers. If the https://github.com/atteo/evo-inflector[EVO inflector] is on the classpath, collection `rel` values are derived by using the pluralizing algorithm implemented in the library (see <<spis.rel-provider>>).
1715

18-
[[configuration.forwarded-headers]]
19-
== Forwarded header handling
20-
21-
Spring HATEOAS supports various https://tools.ietf.org/html/rfc7239[RFC-7239 forwarding headers]. They are most commonly used when your application is behind a proxy, behind
22-
a load balancer, or in the cloud. The node that actually receives the web request is part of the infrastructure, and _forwards_ the request
23-
to your application.
24-
25-
Your application may be running on `localhost:8080`, but to the outside world, you're expected to be at `reallycoolsite.com` (and on
26-
web's standart port 80). By having the proxy include extra headers (which many already do), Spring HATEOAS can transform its generated
27-
links property.
28-
29-
IMPORTANT: Anything that can change the root URI based on external inputs must be properly guarded. That's why, by default, forwarded
30-
header handling is *disabled*. You MUST enable it to be operational. If you are deploying to the cloud or into a configuration where you
31-
control the proxies and load balancers, then you'll certainly want to use this feature.
32-
33-
To enable forwarded header handling in a Spring MVC application running inside Spring Boot, you only need add this to your configuration:
34-
35-
.Registering a `ForwardedHeaderFilter`
36-
====
37-
[source, java, tabsize=2, indent=0]
38-
----
39-
include::{code-dir}/ForwardedEnabledConfig.java[tags=code-1]
40-
----
41-
This will create a servlet filter that processes all the `X-Forwarded-*` headers. And it will register it properly with the servlet handlers.
42-
====
43-
44-
For a Spring WebFlux application, the reactive counterpart is `ForwardedHeaderTransformer`:
45-
46-
.Registering a `ForwardedHeaderTransformer`
47-
====
48-
[source, java, tabsize=2, indent=0]
49-
----
50-
include::{code-dir}/ForwardedEnabledConfig.java[tags=code-2]
51-
----
52-
This will create a function that transforms reactive web requests, processing `X-Forwarded-*` headers. And it will register it properly
53-
with WebFlux.
54-
====
55-
56-
Once enabled, you'll be able to use:
57-
58-
[cols='1,2', options="header"]
59-
|===
60-
| Header
61-
| Description
62-
63-
| https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Forwarded[Forwarded]
64-
| Single header that let's you apply several forwarding attributes.
65-
66-
| https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Host[X-Forwarded-Host]
67-
| Originating hostname (NOTE: Does NOT include the port).
68-
69-
| X-Forwarded-Port
70-
| Originating port number
71-
72-
| https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto[X-Forwarded-Proto]
73-
| Originating protocol (e.g. `http` or `https`).
74-
75-
| X-Forwarded-Prefix
76-
| Originating prefix that was stripped off.
77-
78-
| X-Forwarded-Ssl
79-
| Originating SSL status (e.g. `on`).
80-
|===
81-
82-
NOTE: `X-Forwarded-*` headers aren't governed by a spec, but are instead _de facto_ standards. `Forwarded` is governed by
83-
https://tools.ietf.org/html/rfc7239[RFC 7239], a proposed spec aimed at consolidating forwarded header handling.
84-
85-
You should be able to do this:
86-
87-
----
88-
curl -v localhost:8080/employees \
89-
-H 'X-Forwarded-Proto: https' \
90-
-H 'X-Forwarded-Host: example.com' \
91-
-H 'X-Forwarded-Port: 9001'
92-
----
93-
94-
...and expect to see hypermedia rendered like this:
95-
96-
----
97-
{
98-
"_embedded": {
99-
"employees": [
100-
{
101-
"id": 1,
102-
"name": "Bilbo Baggins",
103-
"role": "burglar",
104-
"_links": {
105-
"self": {
106-
"href": "https://example.com:9001/employees/1"
107-
},
108-
"employees": {
109-
"href": "https://example.com:9001/employees"
110-
}
111-
}
112-
}
113-
]
114-
},
115-
"_links": {
116-
"self": {
117-
"href": "https://example.com:9001/employees"
118-
},
119-
"root": {
120-
"href": "https://example.com:9001"
121-
}
122-
}
123-
}
124-
----

src/main/asciidoc/index.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ NOTE: Copies of this document may be made for your own use and for distribution
1515
== Preface
1616
include::migrate-to-1.0.adoc[leveloffset=+2]
1717
include::fundamentals.adoc[leveloffset=+1]
18-
include::mediatypes.adoc[leveloffset=+1]
1918
include::server.adoc[leveloffset=+1]
19+
include::mediatypes.adoc[leveloffset=+1]
2020
include::configuration.adoc[leveloffset=+1]
2121
include::client.adoc[leveloffset=+1]

src/main/asciidoc/server.adoc

Lines changed: 94 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
[[server]]
22
= Server-side support
3+
:code-dir: ../../../src/docs/java/org/springframework/hateoas
4+
:resource-dir: ../../../src/docs/resources/org/springframework/hateoas
35

4-
[[server.link-builder]]
5-
== [[fundamentals.obtaining-links]] [[fundamentals.obtaining-links.builder]] Building links
6+
[[server.link-builder.webmvc]]
7+
== [[fundamentals.obtaining-links]] [[fundamentals.obtaining-links.builder]] Building links in Spring MVC
68

79
Now we have the domain vocabulary in place, but the main challenge remains: how to create the actual URIs to be wrapped into `Link` instances in a less fragile way. Right now, we would have to duplicate URI strings all over the place. Doing so is brittle and unmaintainable.
810

@@ -72,7 +74,8 @@ return new ResponseEntity<PersonModel>(headers, HttpStatus.CREATED);
7274
[[fundamentals.obtaining-links.builder.methods]]
7375
==== Building Links that Point to Methods
7476

75-
As of version 0.4, you can even build links that point to methods or create dummy controller method invocations. The first approach is to hand a `Method` instance to the `WebMvcLinkBuilder`.
77+
You can even build links that point to methods or create dummy controller method invocations.
78+
The first approach is to hand a `Method` instance to the `WebMvcLinkBuilder`.
7679
The following example shows how to do so:
7780

7881
====
@@ -102,14 +105,99 @@ assertThat(link.getHref()).endsWith("/people/2");
102105
* The return type has to be capable of proxying, as we need to expose the method invocation on it.
103106
* The parameters handed into the methods are generally neglected (except the ones referred to through `@PathVariable`, because they make up the URI).
104107

105-
[[server.link-builder.webmvc]]
106-
== Building links in Spring MVC
107-
108108
[[server.link-builder.webflux]]
109109
== Building links in Spring WebFlux
110110

111111
TODO
112112

113+
[[server.link-builder.forwarded-headers]]
114+
== Forwarded header handling
115+
116+
https://tools.ietf.org/html/rfc7239[RFC-7239 forwarding headers] are most commonly used when your application is behind a proxy, behind a load balancer, or in the cloud.
117+
The node that actually receives the web request is part of the infrastructure, and _forwards_ the request to your application.
118+
119+
Your application may be running on `localhost:8080`, but to the outside world, you're expected to be at `reallycoolsite.com` (and on web's standart port 80).
120+
By having the proxy include extra headers (which many already do), Spring HATEOAS can generate links properly as it uses Spring Framework functionality to obtain the base URI of the original request.
121+
122+
IMPORTANT: Anything that can change the root URI based on external inputs must be properly guarded.
123+
That's why, by default, forwarded header handling is *disabled*.
124+
You MUST enable it to be operational.
125+
If you are deploying to the cloud or into a configuration where you control the proxies and load balancers, then you'll certainly want to use this feature.
126+
127+
To enable forwarded header handling you need to register Spring's `ForwardedHeaderFilter` for Spring MVC (details https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#filters-forwarded-headers[here]) or `ForwardedHeaderTransformer` for Spring WebFlux (details https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-forwarded-headers[here]) in your application.
128+
In a Spring Boot application those components can be simply declared as Spring beans as described https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-web-applications.html#boot-features-embedded-container-servlets-filters-listeners-beans[here].
129+
130+
.Registering a `ForwardedHeaderFilter`
131+
====
132+
[source, java, tabsize=2, indent=0]
133+
----
134+
include::{code-dir}/ForwardedEnabledConfig.java[tags=code-1]
135+
----
136+
====
137+
138+
This will create a servlet filter that processes all the `X-Forwarded-…` headers.
139+
And it will register it properly with the servlet handlers.
140+
141+
For a Spring WebFlux application, the reactive counterpart is `ForwardedHeaderTransformer`:
142+
143+
.Registering a `ForwardedHeaderTransformer`
144+
====
145+
[source, java, tabsize=2, indent=0]
146+
----
147+
include::{code-dir}/ForwardedEnabledConfig.java[tags=code-2]
148+
----
149+
====
150+
151+
This will create a function that transforms reactive web requests, processing `X-Forwarded-…` headers.
152+
And it will register it properly with WebFlux.
153+
154+
With configuration as shown above in place, a request passing `X-Forwarded-…` headers will see those reflected in the links generated:
155+
156+
.A request using `X-Forwarded-…` headers
157+
====
158+
[source, bash]
159+
----
160+
curl -v localhost:8080/employees \
161+
-H 'X-Forwarded-Proto: https' \
162+
-H 'X-Forwarded-Host: example.com' \
163+
-H 'X-Forwarded-Port: 9001'
164+
----
165+
====
166+
167+
.The corresponding response with the links generated to consider those headers
168+
====
169+
[source, json]
170+
----
171+
{
172+
"_embedded": {
173+
"employees": [
174+
{
175+
"id": 1,
176+
"name": "Bilbo Baggins",
177+
"role": "burglar",
178+
"_links": {
179+
"self": {
180+
"href": "https://example.com:9001/employees/1"
181+
},
182+
"employees": {
183+
"href": "https://example.com:9001/employees"
184+
}
185+
}
186+
}
187+
]
188+
},
189+
"_links": {
190+
"self": {
191+
"href": "https://example.com:9001/employees"
192+
},
193+
"root": {
194+
"href": "https://example.com:9001"
195+
}
196+
}
197+
}
198+
----
199+
====
200+
113201
[[server.entity-links]]
114202
== [[fundamentals.obtaining-links.entity-links]] Using the `EntityLinks` interface
115203

0 commit comments

Comments
 (0)