|
1 | 1 | [[server]]
|
2 | 2 | = Server-side support
|
| 3 | +:code-dir: ../../../src/docs/java/org/springframework/hateoas |
| 4 | +:resource-dir: ../../../src/docs/resources/org/springframework/hateoas |
3 | 5 |
|
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 |
6 | 8 |
|
7 | 9 | 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.
|
8 | 10 |
|
@@ -72,7 +74,8 @@ return new ResponseEntity<PersonModel>(headers, HttpStatus.CREATED);
|
72 | 74 | [[fundamentals.obtaining-links.builder.methods]]
|
73 | 75 | ==== Building Links that Point to Methods
|
74 | 76 |
|
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`. |
76 | 79 | The following example shows how to do so:
|
77 | 80 |
|
78 | 81 | ====
|
@@ -102,14 +105,99 @@ assertThat(link.getHref()).endsWith("/people/2");
|
102 | 105 | * The return type has to be capable of proxying, as we need to expose the method invocation on it.
|
103 | 106 | * The parameters handed into the methods are generally neglected (except the ones referred to through `@PathVariable`, because they make up the URI).
|
104 | 107 |
|
105 |
| -[[server.link-builder.webmvc]] |
106 |
| -== Building links in Spring MVC |
107 |
| - |
108 | 108 | [[server.link-builder.webflux]]
|
109 | 109 | == Building links in Spring WebFlux
|
110 | 110 |
|
111 | 111 | TODO
|
112 | 112 |
|
| 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 | + |
113 | 201 | [[server.entity-links]]
|
114 | 202 | == [[fundamentals.obtaining-links.entity-links]] Using the `EntityLinks` interface
|
115 | 203 |
|
|
0 commit comments