Skip to content

Commit

Permalink
dbeaver/dbeaver#23361 New HTTP client API
Browse files Browse the repository at this point in the history
  • Loading branch information
serge-rider committed Nov 1, 2024
1 parent 221baa6 commit f4e4212
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public LibSqlConnection(
throw new SQLException(e);
}
// Verify connection
getMetaData().getDatabaseProductName();
LibSqlUtils.executeQuery(this, "SELECT 1");
}

public LibSqlClient getClient() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ private void readServerVersion() throws SQLException {
return;
}
try {
HttpURLConnection con = connection.getClient().openConnection("version");
HttpURLConnection con = connection.getClient().openSimpleConnection("version");
try (InputStream is = con.getInputStream()) {
serverVersion = IOUtils.readLine(is);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,18 @@
import org.jkiss.code.Nullable;
import org.jkiss.utils.CommonUtils;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.*;
import java.net.CookieManager;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.sql.SQLException;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.Executors;

/**
* The entry point to LibSQL client API.
Expand All @@ -34,10 +36,16 @@ public class LibSqlClient {

private final URL url;
private final String authToken;
private final HttpClient client;

public LibSqlClient(URL url, String authToken) {
this.url = url;
this.authToken = authToken;

HttpClient.Builder builder = HttpClient.newBuilder()
.executor(Executors.newSingleThreadExecutor())
.cookieHandler(new CookieManager());
this.client = builder.build();
}

/**
Expand All @@ -56,71 +64,80 @@ public LibSqlExecutionResult[] executeBatch(
@NotNull String[] stmts,
@Nullable Map<Object, Object>[] parameters) throws SQLException {
try {
HttpURLConnection conn = openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("User-Agent",
LibSqlConstants.DRIVER_INFO + " " +
LibSqlConstants.DRIVER_VERSION_MAJOR + "." + LibSqlConstants.DRIVER_VERSION_MINOR);
conn.setDoOutput(true);

try (OutputStream os = conn.getOutputStream()) {
executeQuery(stmts, parameters, os);
StringWriter requestBuffer = new StringWriter();
executeQuery(stmts, parameters, requestBuffer);

final HttpRequest.Builder builder = HttpRequest.newBuilder()
.uri(url.toURI())
.version(HttpClient.Version.HTTP_1_1)
//.header("Content-Type", "application/json")
.header("User-Agent",
LibSqlConstants.DRIVER_INFO + " " + LibSqlConstants.DRIVER_VERSION_MAJOR + "." + LibSqlConstants.DRIVER_VERSION_MAJOR)
.POST(HttpRequest.BodyPublishers.ofString(requestBuffer.toString()));
if (authToken != null) {
builder.header("Authorization", "Bearer " + authToken);
}
try (InputStreamReader in = new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8)) {
//String responseStr = IOUtils.readToString(in);
Response[] response = gson.fromJson(in, Response[].class);
LibSqlExecutionResult[] resultSets = new LibSqlExecutionResult[response.length];
for (int i = 0; i < response.length; i++) {
if (!CommonUtils.isEmpty(response[i].error)) {
throw new SQLException(response[i].error);

HttpResponse.BodyHandler<String> readerBodyHandler =
info -> HttpResponse.BodySubscribers.ofString(StandardCharsets.UTF_8);

final HttpResponse<String> httpResponse = client.send(
builder.build(),
readerBodyHandler
);
try {
String responseBody = httpResponse.body();
try (Reader isr = new StringReader(responseBody)) {
Response[] response;
if (responseBody.startsWith("[")) {
response = gson.fromJson(isr, Response[].class);
} else {
response = new Response[] {
gson.fromJson(isr, Response.class)
};
}
LibSqlExecutionResult[] resultSets = new LibSqlExecutionResult[response.length];
for (int i = 0; i < response.length; i++) {
if (!CommonUtils.isEmpty(response[i].error)) {
throw new SQLException(response[i].error);
}
resultSets[i] = response[i].results;
}
resultSets[i] = response[i].results;
return resultSets;
}
return resultSets;
} catch (IOException e) {
switch (conn.getResponseCode()) {
} catch (Exception e) {
switch (httpResponse.statusCode()) {
case HttpURLConnection.HTTP_UNAUTHORIZED ->
throw new SQLException("Authentication required", e);
case HttpURLConnection.HTTP_FORBIDDEN ->
throw new SQLException("Access denied", e);
}
throw e;
}
} catch (IOException e) {
} catch (Exception e) {
if (e instanceof SQLException sqle) {
throw sqle;
}
throw new SQLException(e);
}

}

public HttpURLConnection openConnection() throws IOException {
HttpURLConnection conn = (HttpURLConnection) this.url.openConnection();
setAuthParameters(conn);
return conn;
}

public HttpURLConnection openConnection(String endpoint) throws IOException {
public HttpURLConnection openSimpleConnection(String endpoint) throws IOException {
String baseURL = url.toString();
if (!baseURL.endsWith("/")) {
baseURL += "/";
}
baseURL += endpoint;
HttpURLConnection conn = (HttpURLConnection) new URL(baseURL).openConnection();
setAuthParameters(conn);
return conn;
}

private void setAuthParameters(HttpURLConnection conn) {
if (authToken != null) {
conn.setRequestProperty("Authorization", "Bearer " + authToken);
}
return (HttpURLConnection) new URL(baseURL).openConnection();
}

private void executeQuery(
@NotNull String[] queries,
@Nullable Map<Object, Object>[] parameters,
@NotNull OutputStream os
@NotNull Writer os
) throws IOException {
JsonWriter jsonWriter = new JsonWriter(new OutputStreamWriter(os, StandardCharsets.UTF_8));
JsonWriter jsonWriter = new JsonWriter(os);
jsonWriter.beginObject();
jsonWriter.name("statements");
jsonWriter.beginArray();
Expand Down

0 comments on commit f4e4212

Please sign in to comment.