Skip to content

Commit d27580f

Browse files
committed
Add Remote Address to WebGraphQlRequest
This commit makes available the client remote address to various GraphQL request implementations. Closes gh-945
1 parent 31f5075 commit d27580f

File tree

10 files changed

+89
-35
lines changed

10 files changed

+89
-35
lines changed

spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/WebGraphQlHandlerGraphQlTransport.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ CodecConfigurer getCodecConfigurer() {
7878
protected Mono<ExecutionGraphQlResponse> executeInternal(ExecutionGraphQlRequest executionRequest) {
7979

8080
WebGraphQlRequest request = new WebGraphQlRequest(
81-
this.url, this.headers, null, Collections.emptyMap(), executionRequest,
81+
this.url, this.headers, null, null, Collections.emptyMap(), executionRequest,
8282
idGenerator.generateId().toString(), null);
8383

8484
return this.graphQlHandler.handleRequest(request).cast(ExecutionGraphQlResponse.class);

spring-graphql/src/main/java/org/springframework/graphql/server/WebGraphQlRequest.java

+62-18
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.graphql.server;
1818

19+
import java.net.InetSocketAddress;
1920
import java.net.URI;
2021
import java.util.Collections;
2122
import java.util.Locale;
@@ -58,8 +59,51 @@ public class WebGraphQlRequest extends DefaultExecutionGraphQlRequest implements
5859

5960
private final MultiValueMap<String, HttpCookie> cookies;
6061

62+
@Nullable
63+
private final InetSocketAddress remoteAddress;
64+
6165
private final Map<String, Object> attributes;
6266

67+
/**
68+
* Create an instance.
69+
* @param uri the URL for the HTTP request or WebSocket handshake
70+
* @param headers the HTTP request headers
71+
* @param cookies the HTTP request cookies
72+
* @param remoteAddress the HTTP client remote address
73+
* @param attributes request attributes
74+
* @param body the deserialized content of the GraphQL request
75+
* @param id an identifier for the GraphQL request
76+
* @param locale the locale from the HTTP request, if any
77+
* @since 1.3.0
78+
*/
79+
public WebGraphQlRequest(URI uri, HttpHeaders headers, @Nullable MultiValueMap<String, HttpCookie> cookies,
80+
@Nullable InetSocketAddress remoteAddress, Map<String, Object> attributes,
81+
GraphQlRequest body, String id, @Nullable Locale locale) {
82+
this(uri, headers, cookies, remoteAddress, attributes, body.getDocument(),
83+
body.getOperationName(), body.getVariables(), body.getExtensions(), id, locale);
84+
}
85+
86+
/**
87+
* Variant of {@link #WebGraphQlRequest(URI, HttpHeaders, MultiValueMap, Map, GraphQlRequest, String, Locale)}
88+
* with a Map for the request body.
89+
* @param uri the URL for the HTTP request or WebSocket handshake
90+
* @param headers the HTTP request headers
91+
* @param cookies the HTTP request cookies
92+
* @param remoteAddress the HTTP client remote address
93+
* @param attributes request attributes
94+
* @param body the deserialized content of the GraphQL request
95+
* @param id an identifier for the GraphQL request
96+
* @param locale the locale from the HTTP request, if any
97+
* @since 1.3.0
98+
*/
99+
public WebGraphQlRequest(
100+
URI uri, HttpHeaders headers, @Nullable MultiValueMap<String, HttpCookie> cookies,
101+
@Nullable InetSocketAddress remoteAddress, Map<String, Object> attributes,
102+
Map<String, Object> body, String id, @Nullable Locale locale) {
103+
104+
this(uri, headers, cookies, remoteAddress, attributes, getQuery(body), getOperation(body),
105+
getMap(VARIABLES_KEY, body), getMap(EXTENSIONS_KEY, body), id, locale);
106+
}
63107

64108
/**
65109
* Create an instance.
@@ -71,12 +115,14 @@ public class WebGraphQlRequest extends DefaultExecutionGraphQlRequest implements
71115
* @param id an identifier for the GraphQL request
72116
* @param locale the locale from the HTTP request, if any
73117
* @since 1.2.5
118+
* @deprecated since 1.3.0 in favor {@link #WebGraphQlRequest(URI, HttpHeaders, MultiValueMap, InetSocketAddress, Map, Map, String, Locale)}
74119
*/
120+
@Deprecated(since = "1.3.0", forRemoval = true)
75121
public WebGraphQlRequest(
76122
URI uri, HttpHeaders headers, @Nullable MultiValueMap<String, HttpCookie> cookies,
77123
Map<String, Object> attributes, GraphQlRequest body, String id, @Nullable Locale locale) {
78124

79-
this(uri, headers, cookies, attributes, body.getDocument(),
125+
this(uri, headers, cookies, null, attributes, body.getDocument(),
80126
body.getOperationName(), body.getVariables(), body.getExtensions(), id, locale);
81127
}
82128

@@ -91,12 +137,14 @@ public WebGraphQlRequest(
91137
* @param id an identifier for the GraphQL request
92138
* @param locale the locale from the HTTP request, if any
93139
* @since 1.1.3
140+
* @deprecated since 1.3.0 in favor {@link #WebGraphQlRequest(URI, HttpHeaders, MultiValueMap, InetSocketAddress, Map, Map, String, Locale)}
94141
*/
142+
@Deprecated(since = "1.3.0", forRemoval = true)
95143
public WebGraphQlRequest(
96144
URI uri, HttpHeaders headers, @Nullable MultiValueMap<String, HttpCookie> cookies,
97145
Map<String, Object> attributes, Map<String, Object> body, String id, @Nullable Locale locale) {
98146

99-
this(uri, headers, cookies, attributes, getQuery(body), getOperation(body),
147+
this(uri, headers, cookies, null, attributes, getQuery(body), getOperation(body),
100148
getMap(VARIABLES_KEY, body), getMap(EXTENSIONS_KEY, body), id, locale);
101149
}
102150

@@ -127,24 +175,10 @@ private static Map<String, Object> getMap(String key, Map<String, Object> body)
127175
return (Map<String, Object>) value;
128176
}
129177

130-
/**
131-
* Create an instance.
132-
* @param uri the URL for the HTTP request or WebSocket handshake
133-
* @param headers the HTTP request headers
134-
* @param body the deserialized content of the GraphQL request
135-
* @param id an identifier for the GraphQL request
136-
* @param locale the locale from the HTTP request, if any
137-
* @deprecated as of 1.1.3 in favor of
138-
* {@link #WebGraphQlRequest(URI, HttpHeaders, MultiValueMap, Map, GraphQlRequest, String, Locale)}
139-
*/
140-
@Deprecated(since = "1.1.3", forRemoval = true)
141-
public WebGraphQlRequest(URI uri, HttpHeaders headers, Map<String, Object> body, String id, @Nullable Locale locale) {
142-
this(uri, headers, null, Collections.emptyMap(), body, id, locale);
143-
}
144-
145178
private WebGraphQlRequest(
146179
URI uri, HttpHeaders headers, @Nullable MultiValueMap<String, HttpCookie> cookies,
147-
Map<String, Object> attributes, String document, @Nullable String operationName,
180+
@Nullable InetSocketAddress remoteAddress, Map<String, Object> attributes,
181+
String document, @Nullable String operationName,
148182
@Nullable Map<String, Object> variables, @Nullable Map<String, Object> extensions,
149183
String id, @Nullable Locale locale) {
150184

@@ -156,6 +190,7 @@ private WebGraphQlRequest(
156190
this.uri = UriComponentsBuilder.fromUri(uri).build(true);
157191
this.headers = headers;
158192
this.cookies = (cookies != null) ? CollectionUtils.unmodifiableMultiValueMap(cookies) : EMPTY_COOKIES;
193+
this.remoteAddress = remoteAddress;
159194
this.attributes = Collections.unmodifiableMap(attributes);
160195
}
161196

@@ -182,6 +217,15 @@ public MultiValueMap<String, HttpCookie> getCookies() {
182217
return this.cookies;
183218
}
184219

220+
/**
221+
* Return the remote address of the client, if available.
222+
* @since 1.3.0
223+
*/
224+
@Nullable
225+
public InetSocketAddress getRemoteAddress() {
226+
return this.remoteAddress;
227+
}
228+
185229
/**
186230
* Return the request or WebSocket session attributes.
187231
* @since 1.1.3

spring-graphql/src/main/java/org/springframework/graphql/server/WebSocketGraphQlRequest.java

+15-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2023 the original author or authors.
2+
* Copyright 2020-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,8 +17,8 @@
1717
package org.springframework.graphql.server;
1818

1919

20+
import java.net.InetSocketAddress;
2021
import java.net.URI;
21-
import java.util.Collections;
2222
import java.util.Locale;
2323
import java.util.Map;
2424

@@ -45,38 +45,43 @@ public class WebSocketGraphQlRequest extends WebGraphQlRequest {
4545
* Create an instance.
4646
* @param uri the URL for the HTTP request or WebSocket handshake
4747
* @param headers the HTTP request headers
48+
* @param cookies the HTTP request cookies
49+
* @param attributes session attributes
4850
* @param body the deserialized content of the GraphQL request
4951
* @param id the id from the GraphQL over WebSocket {@code "subscribe"} message
5052
* @param locale the locale from the HTTP request, if any
5153
* @param sessionInfo the WebSocket session id
52-
* @deprecated as of 1.1.3 in favor of the constructor with cookies
54+
* @since 1.1.3
55+
* @deprecated in favor of {@link #WebSocketGraphQlRequest(URI, HttpHeaders, MultiValueMap, InetSocketAddress, Map, Map, String, Locale, WebSocketSessionInfo)}
5356
*/
54-
@Deprecated(since = "1.1.3", forRemoval = true)
57+
@Deprecated(since = "1.3.0", forRemoval = true)
5558
public WebSocketGraphQlRequest(
56-
URI uri, HttpHeaders headers, Map<String, Object> body, String id, @Nullable Locale locale,
59+
URI uri, HttpHeaders headers, @Nullable MultiValueMap<String, HttpCookie> cookies,
60+
Map<String, Object> attributes, Map<String, Object> body, String id, @Nullable Locale locale,
5761
WebSocketSessionInfo sessionInfo) {
5862

59-
this(uri, headers, null, Collections.emptyMap(), body, id, locale, sessionInfo);
63+
this(uri, headers, cookies, null, attributes, body, id, locale, sessionInfo);
6064
}
6165

6266
/**
6367
* Create an instance.
6468
* @param uri the URL for the HTTP request or WebSocket handshake
6569
* @param headers the HTTP request headers
6670
* @param cookies the HTTP request cookies
71+
* @param remoteAddress the client remote address
6772
* @param attributes session attributes
6873
* @param body the deserialized content of the GraphQL request
6974
* @param id the id from the GraphQL over WebSocket {@code "subscribe"} message
7075
* @param locale the locale from the HTTP request, if any
7176
* @param sessionInfo the WebSocket session id
72-
* @since 1.1.3
77+
* @since 1.3.0
7378
*/
7479
public WebSocketGraphQlRequest(
7580
URI uri, HttpHeaders headers, @Nullable MultiValueMap<String, HttpCookie> cookies,
76-
Map<String, Object> attributes, Map<String, Object> body, String id, @Nullable Locale locale,
77-
WebSocketSessionInfo sessionInfo) {
81+
@Nullable InetSocketAddress remoteAddress, Map<String, Object> attributes, Map<String, Object> body,
82+
String id, @Nullable Locale locale, WebSocketSessionInfo sessionInfo) {
7883

79-
super(uri, headers, cookies, attributes, body, id, locale);
84+
super(uri, headers, cookies, remoteAddress, attributes, body, id, locale);
8085
Assert.notNull(sessionInfo, "WebSocketSessionInfo is required");
8186
this.sessionInfo = sessionInfo;
8287
}

spring-graphql/src/main/java/org/springframework/graphql/server/webflux/GraphQlHttpHandler.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ public Mono<ServerResponse> handleRequest(ServerRequest serverRequest) {
7474
.flatMap((body) -> {
7575
WebGraphQlRequest graphQlRequest = new WebGraphQlRequest(
7676
serverRequest.uri(), serverRequest.headers().asHttpHeaders(),
77-
serverRequest.cookies(), serverRequest.attributes(), body,
77+
serverRequest.cookies(), serverRequest.remoteAddress().orElse(null),
78+
serverRequest.attributes(), body,
7879
serverRequest.exchange().getRequest().getId(),
7980
serverRequest.exchange().getLocaleContext().getLocale());
8081
if (logger.isDebugEnabled()) {

spring-graphql/src/main/java/org/springframework/graphql/server/webflux/GraphQlSseHandler.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ public Mono<ServerResponse> handleRequest(ServerRequest serverRequest) {
7070
.flatMap((body) -> {
7171
WebGraphQlRequest graphQlRequest = new WebGraphQlRequest(
7272
serverRequest.uri(), serverRequest.headers().asHttpHeaders(),
73-
serverRequest.cookies(), serverRequest.attributes(), body,
73+
serverRequest.cookies(), serverRequest.remoteAddress().orElse(null),
74+
serverRequest.attributes(), body,
7475
serverRequest.exchange().getRequest().getId(),
7576
serverRequest.exchange().getLocaleContext().getLocale());
7677
if (logger.isDebugEnabled()) {

spring-graphql/src/main/java/org/springframework/graphql/server/webflux/GraphQlWebSocketHandler.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,8 @@ public Mono<Void> handle(WebSocketSession session) {
172172
}
173173
WebSocketGraphQlRequest request = new WebSocketGraphQlRequest(
174174
handshakeInfo.getUri(), handshakeInfo.getHeaders(), handshakeInfo.getCookies(),
175-
handshakeInfo.getAttributes(), payload, id, null, sessionInfo);
175+
handshakeInfo.getRemoteAddress(), handshakeInfo.getAttributes(),
176+
payload, id, null, sessionInfo);
176177
if (logger.isDebugEnabled()) {
177178
logger.debug("Executing: " + request);
178179
}

spring-graphql/src/main/java/org/springframework/graphql/server/webmvc/GraphQlHttpHandler.java

+1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ public ServerResponse handleRequest(ServerRequest serverRequest) throws ServletE
8181

8282
WebGraphQlRequest graphQlRequest = new WebGraphQlRequest(
8383
serverRequest.uri(), serverRequest.headers().asHttpHeaders(), initCookies(serverRequest),
84+
serverRequest.remoteAddress().orElse(null),
8485
serverRequest.attributes(), readBody(serverRequest), this.idGenerator.generateId().toString(),
8586
LocaleContextHolder.getLocale());
8687

spring-graphql/src/main/java/org/springframework/graphql/server/webmvc/GraphQlSseHandler.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ public ServerResponse handleRequest(ServerRequest serverRequest) throws ServletE
6969

7070
WebGraphQlRequest graphQlRequest = new WebGraphQlRequest(
7171
serverRequest.uri(), serverRequest.headers().asHttpHeaders(), initCookies(serverRequest),
72-
serverRequest.attributes(), readBody(serverRequest), this.idGenerator.generateId().toString(),
72+
serverRequest.remoteAddress().orElse(null), serverRequest.attributes(),
73+
readBody(serverRequest), this.idGenerator.generateId().toString(),
7374
LocaleContextHolder.getLocale());
7475

7576
if (logger.isDebugEnabled()) {

spring-graphql/src/main/java/org/springframework/graphql/server/webmvc/GraphQlWebSocketHandler.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ private void handleInternal(WebSocketSession session, TextMessage webSocketMessa
230230
Assert.notNull(uri, "Expected handshake url");
231231
HttpHeaders headers = session.getHandshakeHeaders();
232232
WebSocketGraphQlRequest request = new WebSocketGraphQlRequest(
233-
uri, headers, null, session.getAttributes(), payload, id, null, state.getSessionInfo());
233+
uri, headers, null, session.getRemoteAddress(), session.getAttributes(), payload, id, null, state.getSessionInfo());
234234
if (logger.isDebugEnabled()) {
235235
logger.debug("Executing: " + request);
236236
}

spring-graphql/src/test/java/org/springframework/graphql/server/webmvc/TestWebSocketSession.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public InetSocketAddress getLocalAddress() {
8585

8686
@Override
8787
public InetSocketAddress getRemoteAddress() {
88-
throw new UnsupportedOperationException();
88+
return null;
8989
}
9090

9191
@Override

0 commit comments

Comments
 (0)