Skip to content

Latest commit

 

History

11 Commits

Folders and files

Repository files navigation

Light OSS Java SDK

Chinese documentation

The synchronous Java 21 SDK for the Light OSS HTTP API. This library targets the Light OSS Go/Gin API; it is not an Amazon S3 client. Version 0.3.0 covers all 39 documented OpenAPI operations plus public custom-domain site GET and HEAD routing.

Requirements and dependency

  • Java 21 or newer
  • A Light OSS service origin, such as https://oss.example.com
<dependency>
  <groupId>com.onlikee</groupId>
  <artifactId>light-oss-sdk</artifactId>
  <version>0.3.0</version>
</dependency>

The client is immutable and thread-safe. It uses the JDK HTTP client, does not retry or follow redirects by default, and never performs automatic pagination.

Create a client

import com.onlikee.lightoss.LightOssClient;
import java.net.URI;

try (LightOssClient client = LightOssClient.builder(URI.create("https://oss.example.com"))
        .bearerToken(System.getenv("LIGHT_OSS_TOKEN"))
        .build()) {
    var buckets = client.buckets().list().data();
}

For rotating credentials, use a thread-safe provider. It is evaluated for every protected call:

LightOssClient client = LightOssClient.builder(URI.create("https://oss.example.com"))
        .tokenProvider(tokenStore::currentToken)
        .build();

The default connect timeout is 10 seconds and no total request timeout is set. A custom timeout, request-ID provider, or caller-owned HttpClient can be configured through the builder.

Upload and download

UploadSource supports Path, defensive-copy byte[], and repeatable input-stream suppliers. Path and stream bodies are sent incrementally.

import com.onlikee.lightoss.ObjectClient;
import com.onlikee.lightoss.model.Visibility;
import com.onlikee.lightoss.transfer.UploadSource;
import java.nio.file.Path;

var upload = ObjectClient.UploadObjectRequest.builder(
        "documents",
        "reports/2026.pdf",
        UploadSource.fromPath(Path.of("report.pdf"), "application/pdf"))
    .visibility(Visibility.PRIVATE)
    .allowOverwrite(false)
    .build();

var object = client.objects().upload(upload).data();

Downloads and ZIP archives are streaming responses and must be closed:

var request = ObjectClient.DownloadObjectRequest.builder("documents", "reports/2026.pdf")
        .forceDownload(true)
        .build();

try (var download = client.objects().download(request)) {
    download.body().transferTo(outputStream);
    download.etag().ifPresent(System.out::println);
}

Batch operations

Object and site multipart uploads keep the backend's whole-batch transaction semantics. The SDK generates file field names, boundaries, and the JSON manifest.

var items = List.of(
        new ObjectClient.UploadItem("assets/app.js", UploadSource.fromPath(Path.of("app.js"))),
        new ObjectClient.UploadItem("index.html", UploadSource.fromPath(Path.of("index.html"))));

var result = client.objects().uploadBatch(
        ObjectClient.UploadBatchRequest.builder("website", items)
                .visibility(Visibility.PUBLIC)
                .build())
        .data();

Explorer and recycle-bin batch results expose failedItems; they do not convert the backend's per-item result into an all-or-nothing SDK result.

Signed uploads, downloads, and public sites

Signed uploads reuse the same streamed source and object response as authenticated uploads. The SDK sends the returned path and headers without attaching its configured Bearer token:

var source = UploadSource.fromPath(Path.of("report.pdf"), "application/pdf");
var signedUpload = client.signing().signUpload(
        SigningClient.SignUploadRequest.builder("documents", "reports/2026.pdf", source.contentLength().orElseThrow())
                .originalFilename(source.filename())
                .contentType(source.contentType())
                .build()).data();
var object = client.objects().uploadSigned(signedUpload, source).data();

The signed maximum is an upper bound, so unknown-length streaming sources remain supported when the issuer selects an appropriate limit. Pass the original filename as raw text, not URL-encoded text: literal percent sequences are preserved. The SDK forwards every returned signed header, including additional headers introduced by the server, without replacing them with source metadata. Signed headers cannot carry credentials or override HTTP transport framing.

Signing returns a relative URI. Passing it to downloadSigned deliberately suppresses Bearer credentials:

var signed = client.signing()
        .signDownload(SigningClient.SignDownloadRequest.of("documents", "reports/2026.pdf"))
        .data();

try (var download = client.objects().downloadSigned(signed.path())) {
    download.body().transferTo(outputStream);
}

Public site routes by ID and absolute custom-domain routes also never carry a Bearer token:

try (var page = client.sites().downloadPublished(42, "guide/")) {
    page.body().transferTo(outputStream);
}

try (var page = client.sites().downloadDomain(URI.create("https://docs.example.com/guide/"))) {
    page.body().transferTo(outputStream);
}

Errors, pagination, and concurrency

All SDK exceptions are unchecked. LightOssApiException provides the HTTP status, backend code, service message, and request ID. Transport, timeout, protocol, configuration, and validation failures have dedicated exception types. A request ID generated before network I/O is preserved on transport failures. Status-only and non-JSON website errors use the explicit SDK code sdk_http_error while retaining their HTTP status.

try {
    client.buckets().create("example");
} catch (LightOssApiException error) {
    System.err.printf("HTTP %d, code=%s, request=%s%n",
            error.statusCode(), error.code(), error.requestId().orElse("unknown"));
}

Paginated calls return immutable Page<T> values with an explicit nextCursor; fetching another page always requires another method call. A shared client can be used from virtual threads:

try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    var first = executor.submit(() -> client.objects().list(
            ObjectClient.ListObjectsRequest.builder("photos").prefix("2026/").build()));
    var second = executor.submit(() -> client.buckets().list());
    first.get();
    second.get();
}

Domains

LightOssClient exposes health(), system(), buckets(), explorer(), objects(), recycleBin(), sites(), and signing(). Public response models do not expose Jackson, HttpRequest, or asynchronous types. Response enums that may grow are represented as open value types so unknown server values remain readable.

Build and contract verification

mvn.cmd -B clean test
mvn.cmd -B test "-Dlightoss.openapi.file=../onlikee-light-oss/backend/docs/openapi.apifox.json"
mvn.cmd -B clean package
./scripts/check-openapi-contract.ps1

The default test uses the checked-in contract snapshot. The property-based form validates the current local backend file without fetching, pulling, or starting the service. Maven Central packaging is documented in docs/maven-central-publishing.zh-CN.md.

Compatibility

The 0.3.x line treats published public signatures as stable. Public APIs are not removed or changed incompatibly except when required by a security issue or a breaking backend contract.

License

Apache License 2.0.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages