private SseEventSource createEventSource(String restSseUrl) {
String credentialToken = restSseUrl.startsWith("https:") || authenticateAnyway ? this.credentialToken : "";
+
+ RemoteopenhabStreamingRequestFilter filter;
+ boolean filterRegistered = clientBuilder.getConfiguration()
+ .isRegistered(RemoteopenhabStreamingRequestFilter.class);
+ if (filterRegistered) {
+ filter = clientBuilder.getConfiguration().getInstances().stream()
+ .filter(instance -> instance instanceof RemoteopenhabStreamingRequestFilter)
+ .map(instance -> (RemoteopenhabStreamingRequestFilter) instance).findAny().orElseThrow();
+ } else {
+ filter = new RemoteopenhabStreamingRequestFilter();
+ }
+ filter.setCredentialToken(restSseUrl, credentialToken);
+
Client client;
// Avoid a timeout exception after 1 minute by setting the read timeout to 0 (infinite)
if (trustedCertificate) {
- client = clientBuilder.sslContext(httpClient.getSslContextFactory().getSslContext())
- .hostnameVerifier(new HostnameVerifier() {
- @Override
- public boolean verify(@Nullable String hostname, @Nullable SSLSession session) {
- return true;
- }
- }).readTimeout(0, TimeUnit.SECONDS)
- .register(new RemoteopenhabStreamingRequestFilter(credentialToken)).build();
+ HostnameVerifier alwaysValidHostname = new HostnameVerifier() {
+ @Override
+ public boolean verify(@Nullable String hostname, @Nullable SSLSession session) {
+ return true;
+ }
+ };
+ if (filterRegistered) {
+ client = clientBuilder.sslContext(httpClient.getSslContextFactory().getSslContext())
+ .hostnameVerifier(alwaysValidHostname).readTimeout(0, TimeUnit.SECONDS).build();
+ } else {
+ client = clientBuilder.sslContext(httpClient.getSslContextFactory().getSslContext())
+ .hostnameVerifier(alwaysValidHostname).readTimeout(0, TimeUnit.SECONDS).register(filter)
+ .build();
+ }
} else {
- client = clientBuilder.readTimeout(0, TimeUnit.SECONDS)
- .register(new RemoteopenhabStreamingRequestFilter(credentialToken)).build();
+ if (filterRegistered) {
+ client = clientBuilder.readTimeout(0, TimeUnit.SECONDS).build();
+ } else {
+ client = clientBuilder.readTimeout(0, TimeUnit.SECONDS).register(filter).build();
+ }
}
+
SseEventSource eventSource = eventSourceFactory.newSource(client.target(restSseUrl));
eventSource.register(this::onEvent, this::onError, this::onComplete);
return eventSource;
package org.openhab.binding.remoteopenhab.internal.rest;
import java.io.IOException;
+import java.util.concurrent.ConcurrentHashMap;
import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientRequestFilter;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Inserts Authorization and Cache-Control headers for requests on the streaming REST API.
@NonNullByDefault
public class RemoteopenhabStreamingRequestFilter implements ClientRequestFilter {
- private final String credentialToken;
+ private final Logger logger = LoggerFactory.getLogger(RemoteopenhabStreamingRequestFilter.class);
- public RemoteopenhabStreamingRequestFilter(String credentialToken) {
- this.credentialToken = credentialToken;
- }
+ private final ConcurrentHashMap<String, String> credentialTokens = new ConcurrentHashMap<>();
@Override
public void filter(@Nullable ClientRequestContext requestContext) throws IOException {
if (requestContext != null) {
MultivaluedMap<String, Object> headers = requestContext.getHeaders();
- if (!credentialToken.isEmpty()) {
- headers.putSingle(HttpHeaders.AUTHORIZATION, "Basic " + credentialToken);
+ String credentialToken = credentialTokens.get(requestContext.getUri().toString());
+ if (credentialToken != null) {
+ if (!credentialToken.isEmpty()) {
+ headers.putSingle(HttpHeaders.AUTHORIZATION, "Basic " + credentialToken);
+ }
+ } else {
+ logger.warn("No credential token set! uri={}", requestContext.getUri());
}
headers.putSingle(HttpHeaders.CACHE_CONTROL, "no-cache");
}
}
+
+ public void setCredentialToken(String target, String token) {
+ logger.debug("Set credential token. target={}, token={}", target, token);
+ credentialTokens.put(target, token);
+ }
}