fix: fix usage with ws:// scheme

The URL constructor does not support the ws:// scheme, and would throw:

> java.net.MalformedURLException: unknown protocol: ws

Related:

- https://github.com/socketio/socket.io-client-java/issues/650
- https://github.com/socketio/socket.io-client-java/issues/555
- https://github.com/socketio/socket.io-client-java/issues/233
This commit is contained in:
Damien Arrachequesne
2021-04-26 10:27:29 +02:00
parent e2e24ea75d
commit 67fd5f34a3
3 changed files with 84 additions and 81 deletions

View File

@@ -7,7 +7,6 @@ import okhttp3.WebSocket;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -58,21 +57,16 @@ public class IO {
opts = new Options();
}
URL parsed = Url.parse(uri);
URI source;
try {
source = parsed.toURI();
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
String id = Url.extractId(parsed);
String path = parsed.getPath();
Url.ParsedURI parsed = Url.parse(uri);
URI source = parsed.uri;
String id = parsed.id;
boolean sameNamespace = managers.containsKey(id)
&& managers.get(id).nsps.containsKey(path);
&& managers.get(id).nsps.containsKey(source.getPath());
boolean newConnection = opts.forceNew || !opts.multiplex || sameNamespace;
Manager io;
String query = parsed.getQuery();
String query = source.getQuery();
if (query != null && (opts.query == null || opts.query.isEmpty())) {
opts.query = query;
}
@@ -92,7 +86,7 @@ public class IO {
io = managers.get(id);
}
return io.socket(parsed.getPath(), opts);
return io.socket(source.getPath(), opts);
}

View File

@@ -1,16 +1,11 @@
package io.socket.client;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Url {
private static Pattern PATTERN_HTTP = Pattern.compile("^http|ws$");
private static Pattern PATTERN_HTTPS = Pattern.compile("^(http|ws)s$");
/**
* Expected format: "[id:password@]host[:port]"
*/
@@ -18,11 +13,17 @@ public class Url {
private Url() {}
public static URL parse(String uri) throws URISyntaxException {
return parse(new URI(uri));
static class ParsedURI {
public final URI uri;
public final String id;
public ParsedURI(URI uri, String id) {
this.uri = uri;
this.id = id;
}
}
public static URL parse(URI uri) {
public static ParsedURI parse(URI uri) {
String protocol = uri.getScheme();
if (protocol == null || !protocol.matches("^https?|wss?$")) {
protocol = "https";
@@ -30,9 +31,9 @@ public class Url {
int port = uri.getPort();
if (port == -1) {
if (PATTERN_HTTP.matcher(protocol).matches()) {
if ("http".equals(protocol) || "ws".equals(protocol)) {
port = 80;
} else if (PATTERN_HTTPS.matcher(protocol).matches()) {
} else if ("https".equals(protocol) || "wss".equals(protocol)) {
port = 443;
}
}
@@ -50,35 +51,18 @@ public class Url {
// might happen on some of Samsung Devices such as S4.
_host = extractHostFromAuthorityPart(uri.getRawAuthority());
}
try {
return new URL(protocol + "://"
+ (userInfo != null ? userInfo + "@" : "")
+ _host
+ (port != -1 ? ":" + port : "")
+ path
+ (query != null ? "?" + query : "")
+ (fragment != null ? "#" + fragment : ""));
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
URI completeUri = URI.create(protocol + "://"
+ (userInfo != null ? userInfo + "@" : "")
+ _host
+ (port != -1 ? ":" + port : "")
+ path
+ (query != null ? "?" + query : "")
+ (fragment != null ? "#" + fragment : ""));
String id = protocol + "://" + _host + ":" + port;
return new ParsedURI(completeUri, id);
}
public static String extractId(String url) throws MalformedURLException {
return extractId(new URL(url));
}
public static String extractId(URL url) {
String protocol = url.getProtocol();
int port = url.getPort();
if (port == -1) {
if (PATTERN_HTTP.matcher(protocol).matches()) {
port = 80;
} else if (PATTERN_HTTPS.matcher(protocol).matches()) {
port = 443;
}
}
return protocol + "://" + url.getHost() + ":" + port;
}
private static String extractHostFromAuthorityPart(String authority)
{