Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[remoteopenhab] Avoid registering conflicting filters for SSE connection #10870

Merged
merged 3 commits into from
Jun 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -273,21 +273,44 @@ public void stop(boolean waitingForCompletion) {

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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
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;
Expand All @@ -21,6 +22,8 @@

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.
Expand All @@ -30,20 +33,28 @@
@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);
}
}