17
17
package org .springframework .boot .autoconfigure .elasticsearch ;
18
18
19
19
import java .net .URI ;
20
- import java .net .URISyntaxException ;
21
20
import java .time .Duration ;
21
+ import java .util .List ;
22
+ import java .util .stream .Stream ;
22
23
23
24
import org .apache .http .HttpHost ;
24
25
import org .apache .http .auth .AuthScope ;
37
38
import org .springframework .boot .autoconfigure .condition .ConditionalOnClass ;
38
39
import org .springframework .boot .autoconfigure .condition .ConditionalOnMissingBean ;
39
40
import org .springframework .boot .autoconfigure .condition .ConditionalOnSingleCandidate ;
41
+ import org .springframework .boot .autoconfigure .elasticsearch .ElasticsearchConnectionDetails .Node ;
42
+ import org .springframework .boot .autoconfigure .elasticsearch .ElasticsearchConnectionDetails .Node .Protocol ;
40
43
import org .springframework .boot .context .properties .PropertyMapper ;
41
44
import org .springframework .context .annotation .Bean ;
42
45
import org .springframework .context .annotation .Configuration ;
47
50
*
48
51
* @author Stephane Nicoll
49
52
* @author Filip Hrisafov
53
+ * @author Moritz Halbritter
54
+ * @author Andy Wilkinson
55
+ * @author Phillip Webb
50
56
*/
51
57
class ElasticsearchRestClientConfigurations {
52
58
@@ -56,20 +62,27 @@ static class RestClientBuilderConfiguration {
56
62
57
63
private final ElasticsearchProperties properties ;
58
64
59
- RestClientBuilderConfiguration (ElasticsearchProperties properties ) {
65
+ private final ElasticsearchConnectionDetails connectionDetails ;
66
+
67
+ RestClientBuilderConfiguration (ElasticsearchProperties properties ,
68
+ ObjectProvider <ElasticsearchConnectionDetails > connectionDetails ) {
60
69
this .properties = properties ;
70
+ this .connectionDetails = connectionDetails
71
+ .getIfAvailable (() -> new PropertiesElasticsearchConnectionDetails (properties ));
61
72
}
62
73
63
74
@ Bean
64
75
RestClientBuilderCustomizer defaultRestClientBuilderCustomizer () {
65
- return new DefaultRestClientBuilderCustomizer (this .properties );
76
+ return new DefaultRestClientBuilderCustomizer (this .properties , this . connectionDetails );
66
77
}
67
78
68
79
@ Bean
69
80
RestClientBuilder elasticsearchRestClientBuilder (
70
81
ObjectProvider <RestClientBuilderCustomizer > builderCustomizers ) {
71
- HttpHost [] hosts = this .properties .getUris ().stream ().map (this ::createHttpHost ).toArray (HttpHost []::new );
72
- RestClientBuilder builder = RestClient .builder (hosts );
82
+ RestClientBuilder builder = RestClient .builder (this .connectionDetails .getNodes ()
83
+ .stream ()
84
+ .map ((node ) -> new HttpHost (node .hostname (), node .port (), node .protocol ().getScheme ()))
85
+ .toArray (HttpHost []::new ));
73
86
builder .setHttpClientConfigCallback ((httpClientBuilder ) -> {
74
87
builderCustomizers .orderedStream ().forEach ((customizer ) -> customizer .customize (httpClientBuilder ));
75
88
return httpClientBuilder ;
@@ -78,36 +91,14 @@ RestClientBuilder elasticsearchRestClientBuilder(
78
91
builderCustomizers .orderedStream ().forEach ((customizer ) -> customizer .customize (requestConfigBuilder ));
79
92
return requestConfigBuilder ;
80
93
});
81
- if (this .properties .getPathPrefix () != null ) {
82
- builder .setPathPrefix (this .properties .getPathPrefix ());
94
+ String pathPrefix = this .connectionDetails .getPathPrefix ();
95
+ if (pathPrefix != null ) {
96
+ builder .setPathPrefix (pathPrefix );
83
97
}
84
98
builderCustomizers .orderedStream ().forEach ((customizer ) -> customizer .customize (builder ));
85
99
return builder ;
86
100
}
87
101
88
- private HttpHost createHttpHost (String uri ) {
89
- try {
90
- return createHttpHost (URI .create (uri ));
91
- }
92
- catch (IllegalArgumentException ex ) {
93
- return HttpHost .create (uri );
94
- }
95
- }
96
-
97
- private HttpHost createHttpHost (URI uri ) {
98
- if (!StringUtils .hasLength (uri .getUserInfo ())) {
99
- return HttpHost .create (uri .toString ());
100
- }
101
- try {
102
- return HttpHost .create (new URI (uri .getScheme (), null , uri .getHost (), uri .getPort (), uri .getPath (),
103
- uri .getQuery (), uri .getFragment ())
104
- .toString ());
105
- }
106
- catch (URISyntaxException ex ) {
107
- throw new IllegalStateException (ex );
108
- }
109
- }
110
-
111
102
}
112
103
113
104
@ Configuration (proxyBeanMethods = false )
@@ -146,8 +137,12 @@ static class DefaultRestClientBuilderCustomizer implements RestClientBuilderCust
146
137
147
138
private final ElasticsearchProperties properties ;
148
139
149
- DefaultRestClientBuilderCustomizer (ElasticsearchProperties properties ) {
140
+ private final ElasticsearchConnectionDetails connectionDetails ;
141
+
142
+ DefaultRestClientBuilderCustomizer (ElasticsearchProperties properties ,
143
+ ElasticsearchConnectionDetails connectionDetails ) {
150
144
this .properties = properties ;
145
+ this .connectionDetails = connectionDetails ;
151
146
}
152
147
153
148
@ Override
@@ -156,7 +151,7 @@ public void customize(RestClientBuilder builder) {
156
151
157
152
@ Override
158
153
public void customize (HttpAsyncClientBuilder builder ) {
159
- builder .setDefaultCredentialsProvider (new PropertiesCredentialsProvider (this .properties ));
154
+ builder .setDefaultCredentialsProvider (new ConnectionDetailsCredentialsProvider (this .connectionDetails ));
160
155
map .from (this .properties ::isSocketKeepAlive )
161
156
.to ((keepAlive ) -> builder
162
157
.setDefaultIOReactorConfig (IOReactorConfig .custom ().setSoKeepAlive (keepAlive ).build ()));
@@ -176,28 +171,20 @@ public void customize(RequestConfig.Builder builder) {
176
171
177
172
}
178
173
179
- private static class PropertiesCredentialsProvider extends BasicCredentialsProvider {
174
+ private static class ConnectionDetailsCredentialsProvider extends BasicCredentialsProvider {
180
175
181
- PropertiesCredentialsProvider ( ElasticsearchProperties properties ) {
182
- if ( StringUtils . hasText ( properties . getUsername ())) {
183
- Credentials credentials = new UsernamePasswordCredentials ( properties . getUsername (),
184
- properties .getPassword ());
176
+ ConnectionDetailsCredentialsProvider ( ElasticsearchConnectionDetails connectionDetails ) {
177
+ String username = connectionDetails . getUsername ();
178
+ if ( StringUtils . hasText ( username )) {
179
+ Credentials credentials = new UsernamePasswordCredentials ( username , connectionDetails .getPassword ());
185
180
setCredentials (AuthScope .ANY , credentials );
186
181
}
187
- properties .getUris ()
188
- .stream ()
189
- .map (this ::toUri )
190
- .filter (this ::hasUserInfo )
191
- .forEach (this ::addUserInfoCredentials );
182
+ Stream <URI > uris = getUris (connectionDetails );
183
+ uris .filter (this ::hasUserInfo ).forEach (this ::addUserInfoCredentials );
192
184
}
193
185
194
- private URI toUri (String uri ) {
195
- try {
196
- return URI .create (uri );
197
- }
198
- catch (IllegalArgumentException ex ) {
199
- return null ;
200
- }
186
+ private Stream <URI > getUris (ElasticsearchConnectionDetails connectionDetails ) {
187
+ return connectionDetails .getNodes ().stream ().map (Node ::toUri );
201
188
}
202
189
203
190
private boolean hasUserInfo (URI uri ) {
@@ -222,4 +209,59 @@ private Credentials createUserInfoCredentials(String userInfo) {
222
209
223
210
}
224
211
212
+ /**
213
+ * Adapts {@link ElasticsearchProperties} to {@link ElasticsearchConnectionDetails}.
214
+ */
215
+ private static class PropertiesElasticsearchConnectionDetails implements ElasticsearchConnectionDetails {
216
+
217
+ private final ElasticsearchProperties properties ;
218
+
219
+ PropertiesElasticsearchConnectionDetails (ElasticsearchProperties properties ) {
220
+ this .properties = properties ;
221
+ }
222
+
223
+ @ Override
224
+ public List <Node > getNodes () {
225
+ return this .properties .getUris ().stream ().map (this ::createNode ).toList ();
226
+ }
227
+
228
+ @ Override
229
+ public String getUsername () {
230
+ return this .properties .getUsername ();
231
+ }
232
+
233
+ @ Override
234
+ public String getPassword () {
235
+ return this .properties .getPassword ();
236
+ }
237
+
238
+ @ Override
239
+ public String getPathPrefix () {
240
+ return this .properties .getPathPrefix ();
241
+ }
242
+
243
+ private Node createNode (String uri ) {
244
+ if (!(uri .startsWith ("http://" ) || uri .startsWith ("https://" ))) {
245
+ uri = "http://" + uri ;
246
+ }
247
+ return createNode (URI .create (uri ));
248
+ }
249
+
250
+ private Node createNode (URI uri ) {
251
+ String userInfo = uri .getUserInfo ();
252
+ Protocol protocol = Protocol .forScheme (uri .getScheme ());
253
+ if (!StringUtils .hasLength (userInfo )) {
254
+ return new Node (uri .getHost (), uri .getPort (), protocol , null , null );
255
+ }
256
+ int separatorIndex = userInfo .indexOf (':' );
257
+ if (separatorIndex == -1 ) {
258
+ return new Node (uri .getHost (), uri .getPort (), protocol , userInfo , null );
259
+ }
260
+ String [] components = userInfo .split (":" );
261
+ return new Node (uri .getHost (), uri .getPort (), protocol , components [0 ],
262
+ (components .length > 1 ) ? components [1 ] : "" );
263
+ }
264
+
265
+ }
266
+
225
267
}
0 commit comments