mirror of
https://github.com/TeamPiped/reqwest4j.git
synced 2024-08-14 23:54:39 +00:00
Compare commits
No commits in common. "main" and "1.0.8" have entirely different histories.
12 changed files with 386 additions and 615 deletions
30
.github/workflows/ci.yml
vendored
30
.github/workflows/ci.yml
vendored
|
@ -1,30 +0,0 @@
|
|||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
build-and-test:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
java: [ 21 ]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: |
|
||||
reqwest-jni
|
||||
- run: cargo install cross
|
||||
- name: set up JDK ${{ matrix.java }}
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: ${{ matrix.java }}
|
||||
distribution: zulu
|
||||
cache: "gradle"
|
||||
- name: Run Build
|
||||
run: ./gradlew shadowJar
|
8
.github/workflows/publish-maven.yml
vendored
8
.github/workflows/publish-maven.yml
vendored
|
@ -12,7 +12,7 @@ jobs:
|
|||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
|
@ -20,10 +20,10 @@ jobs:
|
|||
reqwest-jni
|
||||
- run: cargo install cross
|
||||
- name: set up JDK
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: 21
|
||||
distribution: zulu
|
||||
java-version: 17
|
||||
distribution: temurin
|
||||
check-latest: true
|
||||
cache: "gradle"
|
||||
- name: Save Private Key
|
||||
|
|
16
build.gradle
16
build.gradle
|
@ -3,7 +3,7 @@ plugins {
|
|||
id "maven-publish"
|
||||
id "signing"
|
||||
id "fr.stardustenterprises.rust.importer" version "3.2.5"
|
||||
id 'com.github.johnrengelman.shadow' version '8.1.1'
|
||||
id 'com.github.johnrengelman.shadow' version '7.1.2'
|
||||
}
|
||||
|
||||
repositories {
|
||||
|
@ -17,14 +17,14 @@ dependencies {
|
|||
// javac -h
|
||||
tasks.register('generateJniHeaders', JavaCompile) {
|
||||
classpath = sourceSets.main.compileClasspath
|
||||
destinationDir file("${layout.buildDirectory}/generated/jni")
|
||||
destinationDir file("${buildDir}/generated/jni")
|
||||
source = sourceSets.main.java
|
||||
options.compilerArgs += [
|
||||
'-h', file("${layout.buildDirectory}/generated/jni"),
|
||||
'-d', file("${layout.buildDirectory}/generated/jni-classes"),
|
||||
'-h', file("${buildDir}/generated/jni"),
|
||||
'-d', file("${buildDir}/generated/jni-classes"),
|
||||
]
|
||||
doLast {
|
||||
delete file("${layout.buildDirectory}/generated/jni-classes")
|
||||
delete file("${buildDir}/generated/jni-classes")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,8 +36,6 @@ rustImport {
|
|||
java {
|
||||
withSourcesJar()
|
||||
withJavadocJar()
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
}
|
||||
|
||||
signing {
|
||||
|
@ -45,7 +43,9 @@ signing {
|
|||
}
|
||||
|
||||
group = 'rocks.kavin'
|
||||
version = '1.0.14'
|
||||
version = '1.0.8'
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
|
||||
publishing {
|
||||
repositories {
|
||||
|
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
3
gradle/wrapper/gradle-wrapper.properties
vendored
3
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,7 +1,6 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
|
||||
distributionUrl=https\://downloads.gradle.org/distributions/gradle-7.6-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
34
gradlew
vendored
34
gradlew
vendored
|
@ -15,8 +15,6 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
|
@ -57,7 +55,7 @@
|
|||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
|
@ -85,9 +83,10 @@ done
|
|||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
||||
' "$PWD" ) || exit
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
@ -134,13 +133,10 @@ location of your Java installation."
|
|||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
|
@ -148,7 +144,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
|||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
# shellcheck disable=SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
|
@ -156,7 +152,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
|||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
# shellcheck disable=SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
|
@ -201,15 +197,11 @@ if "$cygwin" || "$msys" ; then
|
|||
done
|
||||
fi
|
||||
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
|
|
22
gradlew.bat
vendored
22
gradlew.bat
vendored
|
@ -13,8 +13,6 @@
|
|||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
|
@ -45,11 +43,11 @@ set JAVA_EXE=java.exe
|
|||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
|
@ -59,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
|||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
|
|
|
@ -13,5 +13,6 @@
|
|||
"automerge": true,
|
||||
"platformAutomerge": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"enabledManagers": ["cargo", "github-actions"]
|
||||
}
|
696
reqwest-jni/Cargo.lock
generated
696
reqwest-jni/Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -7,11 +7,8 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
jni = "0.21.1"
|
||||
reqwest = {version = "0.12.4", features = ["rustls-tls", "stream", "brotli", "gzip", "socks"], default-features = false}
|
||||
tokio = {version = "1.37.0", features = ["rt-multi-thread", "time"], default-features = false}
|
||||
reqwest = {version = "0.11.18", features = ["rustls-tls", "stream", "brotli", "gzip", "socks"], default-features = false}
|
||||
tokio = {version = "1.29.1", features = ["full"]}
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, OnceLock};
|
||||
use std::time::Duration;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
use jni::objects::{JByteArray, JClass, JMap, JObject, JString};
|
||||
use jni::sys::jobject;
|
||||
|
@ -16,8 +15,6 @@ pub extern "system" fn Java_rocks_kavin_reqwest4j_ReqwestUtils_init(
|
|||
mut env: JNIEnv,
|
||||
_: JClass,
|
||||
proxy: JString,
|
||||
user: JString,
|
||||
pass: JString,
|
||||
) {
|
||||
let builder = Client::builder()
|
||||
.user_agent("Mozilla/5.0 (Windows NT 10.0; rv:102.0) Gecko/20100101 Firefox/102.0");
|
||||
|
@ -26,27 +23,12 @@ pub extern "system" fn Java_rocks_kavin_reqwest4j_ReqwestUtils_init(
|
|||
Ok(proxy) => {
|
||||
let proxy = proxy.to_str().unwrap();
|
||||
let proxy = reqwest::Proxy::all(proxy).unwrap();
|
||||
let proxy = match env.get_string(&user) {
|
||||
Ok(user) => {
|
||||
let user = user.to_str().unwrap();
|
||||
let pass = env.get_string(&pass).unwrap();
|
||||
let pass = pass.to_str().unwrap();
|
||||
proxy.basic_auth(user, pass)
|
||||
}
|
||||
Err(_) => proxy,
|
||||
};
|
||||
builder.proxy(proxy)
|
||||
}
|
||||
Err(_) => builder,
|
||||
};
|
||||
|
||||
let client = builder
|
||||
// timeout for establishing connection
|
||||
.connect_timeout(Duration::from_secs(10))
|
||||
// timeout for entire request, till body is read
|
||||
.timeout(Duration::from_secs(30))
|
||||
.build()
|
||||
.unwrap();
|
||||
let client = builder.build().unwrap();
|
||||
CLIENT.set(client).unwrap();
|
||||
RUNTIME.set(Runtime::new().unwrap()).unwrap();
|
||||
}
|
||||
|
@ -119,111 +101,89 @@ pub extern "system" fn Java_rocks_kavin_reqwest4j_ReqwestUtils_fetch(
|
|||
|
||||
// `JNIEnv` cannot be sent between threads safely
|
||||
let jvm = env.get_java_vm().unwrap();
|
||||
let jvm = Arc::new(jvm);
|
||||
|
||||
// create CompletableFuture
|
||||
let _future = env
|
||||
.new_object("java/util/concurrent/CompletableFuture", "()V", &[])
|
||||
.unwrap();
|
||||
let future = env.new_global_ref(&_future).unwrap();
|
||||
let future = Arc::new(future);
|
||||
|
||||
let runtime = RUNTIME.get().unwrap();
|
||||
|
||||
// send request in a async task
|
||||
{
|
||||
let jvm = Arc::clone(&jvm);
|
||||
let future = Arc::clone(&future);
|
||||
runtime.spawn_blocking(move || {
|
||||
// send request
|
||||
let response = runtime.block_on(async { request.send().await });
|
||||
|
||||
runtime.spawn(async move {
|
||||
// send request
|
||||
let response = request.send().await;
|
||||
let mut env = jvm.attach_current_thread().unwrap();
|
||||
|
||||
match response {
|
||||
Ok(response) => {
|
||||
// get response
|
||||
let status = response.status().as_u16() as i32;
|
||||
if let Err(error) = response {
|
||||
let error = error.to_string();
|
||||
let error = env.new_string(error).unwrap();
|
||||
// create Exception
|
||||
let exception = env
|
||||
.new_object(
|
||||
"java/lang/Exception",
|
||||
"(Ljava/lang/String;)V",
|
||||
&[(&error).into()],
|
||||
)
|
||||
.unwrap();
|
||||
// pass error to CompletableFuture
|
||||
env.call_method(
|
||||
future,
|
||||
"completeExceptionally",
|
||||
"(Ljava/lang/Throwable;)Z",
|
||||
&[(&exception).into()],
|
||||
)
|
||||
.unwrap();
|
||||
return;
|
||||
}
|
||||
|
||||
let final_url = response.url().to_string();
|
||||
let response = response.unwrap();
|
||||
|
||||
let response_headers = response.headers().clone();
|
||||
// get response
|
||||
let status = response.status().as_u16() as i32;
|
||||
|
||||
let body = response.bytes().await.unwrap_or_default().to_vec();
|
||||
let headers = env.new_object("java/util/HashMap", "()V", &[]).unwrap();
|
||||
let headers: JMap = JMap::from_env(&mut env, &headers).unwrap();
|
||||
|
||||
// send response in a blocking task
|
||||
runtime.spawn_blocking(move || {
|
||||
let mut env = jvm.attach_current_thread().unwrap();
|
||||
|
||||
let final_url = env.new_string(final_url).unwrap();
|
||||
|
||||
let body = env.byte_array_from_slice(&body).unwrap();
|
||||
|
||||
let headers = env.new_object("java/util/HashMap", "()V", &[]).unwrap();
|
||||
let headers: JMap = JMap::from_env(&mut env, &headers).unwrap();
|
||||
|
||||
response_headers.iter().for_each(|(key, value)| {
|
||||
let key = env.new_string(key.as_str()).unwrap();
|
||||
let value = env.new_string(value.to_str().unwrap()).unwrap();
|
||||
headers
|
||||
.put(&mut env, &JObject::from(key), &JObject::from(value))
|
||||
.unwrap();
|
||||
});
|
||||
|
||||
// return response to CompletableFuture
|
||||
let response = env
|
||||
.new_object(
|
||||
"rocks/kavin/reqwest4j/Response",
|
||||
"(ILjava/util/Map;[BLjava/lang/String;)V",
|
||||
&[
|
||||
status.into(),
|
||||
(&headers).into(),
|
||||
(&body).into(),
|
||||
(&final_url).into(),
|
||||
],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let future = future.as_obj();
|
||||
env.call_method(
|
||||
future,
|
||||
"complete",
|
||||
"(Ljava/lang/Object;)Z",
|
||||
&[(&response).into()],
|
||||
)
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
Err(error) => {
|
||||
// send error in a blocking task
|
||||
runtime.spawn_blocking(move || {
|
||||
let mut env = jvm.attach_current_thread().unwrap();
|
||||
|
||||
let error = error.to_string();
|
||||
let error = env.new_string(error).unwrap();
|
||||
// create Exception
|
||||
let exception = env
|
||||
.new_object(
|
||||
"java/lang/Exception",
|
||||
"(Ljava/lang/String;)V",
|
||||
&[(&error).into()],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let future = future.as_obj();
|
||||
|
||||
// pass error to CompletableFuture
|
||||
env.call_method(
|
||||
future,
|
||||
"completeExceptionally",
|
||||
"(Ljava/lang/Throwable;)Z",
|
||||
&[(&exception).into()],
|
||||
)
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
}
|
||||
response.headers().iter().for_each(|(key, value)| {
|
||||
let key = env.new_string(key.as_str()).unwrap();
|
||||
let value = env.new_string(value.to_str().unwrap()).unwrap();
|
||||
headers
|
||||
.put(&mut env, &JObject::from(key), &JObject::from(value))
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
let final_url = response.url().to_string();
|
||||
let final_url = env.new_string(final_url).unwrap();
|
||||
|
||||
let body = runtime.block_on(async { response.bytes().await.unwrap_or_default().to_vec() });
|
||||
|
||||
let body = env.byte_array_from_slice(&body).unwrap();
|
||||
|
||||
// return response to CompletableFuture
|
||||
let response = env
|
||||
.new_object(
|
||||
"rocks/kavin/reqwest4j/Response",
|
||||
"(ILjava/util/Map;[BLjava/lang/String;)V",
|
||||
&[
|
||||
status.into(),
|
||||
(&headers).into(),
|
||||
(&body).into(),
|
||||
(&final_url).into(),
|
||||
],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let future = future.as_obj();
|
||||
env.call_method(
|
||||
future,
|
||||
"complete",
|
||||
"(Ljava/lang/Object;)Z",
|
||||
&[(&response).into()],
|
||||
)
|
||||
.unwrap();
|
||||
});
|
||||
|
||||
_future.into_raw()
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ public class ReqwestUtils {
|
|||
System.load(nativeFile.getAbsolutePath());
|
||||
}
|
||||
|
||||
public static native void init(String proxy, String user, String pass);
|
||||
public static native void init(String proxy);
|
||||
|
||||
public static native CompletableFuture<Response> fetch(String url, String method, byte[] body,
|
||||
Map<String, String> headers);
|
||||
|
|
Loading…
Reference in a new issue