{"id":26261919,"url":"https://github.com/robothy/local-s3","last_synced_at":"2026-03-27T21:00:15.804Z","repository":{"id":90161646,"uuid":"561715376","full_name":"Robothy/local-s3","owner":"Robothy","description":"An Amazon S3 service implementation based on Netty.","archived":false,"fork":false,"pushed_at":"2026-03-27T08:18:56.000Z","size":898,"stargazers_count":63,"open_issues_count":6,"forks_count":7,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-03-27T19:51:15.868Z","etag":null,"topics":["amazon-s3","amazons3","aws-s3","docker","graalvm","graalvm-native-image","integration-testing","java","junit5","local-s3","s3","s3-bucket","s3-docoker","s3mock","s3vectors","testcontainers","testing","vector-database"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Robothy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-11-04T10:23:36.000Z","updated_at":"2026-03-27T08:18:01.000Z","dependencies_parsed_at":null,"dependency_job_id":"08e75a6b-3ec9-4194-b7b1-985b92ed5739","html_url":"https://github.com/Robothy/local-s3","commit_stats":null,"previous_names":[],"tags_count":35,"template":false,"template_full_name":null,"purl":"pkg:github/Robothy/local-s3","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Robothy%2Flocal-s3","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Robothy%2Flocal-s3/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Robothy%2Flocal-s3/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Robothy%2Flocal-s3/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Robothy","download_url":"https://codeload.github.com/Robothy/local-s3/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Robothy%2Flocal-s3/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31060543,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-27T19:32:53.857Z","status":"ssl_error","status_checked_at":"2026-03-27T19:32:45.136Z","response_time":164,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["amazon-s3","amazons3","aws-s3","docker","graalvm","graalvm-native-image","integration-testing","java","junit5","local-s3","s3","s3-bucket","s3-docoker","s3mock","s3vectors","testcontainers","testing","vector-database"],"created_at":"2025-03-14T00:16:40.332Z","updated_at":"2026-03-27T21:00:11.216Z","avatar_url":"https://github.com/Robothy.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# LocalS3\n\n[![Build](https://github.com/Robothy/local-s3/actions/workflows/build.yml/badge.svg)](https://github.com/Robothy/local-s3/actions/workflows/build.yml)\n[![Apache 2.0 License](https://img.shields.io/badge/license-Apache%202.0-green.svg)](https://github.com/robothy/local-s3/blob/main/LICENSE)\n[![Maven Central](https://img.shields.io/maven-central/v/io.github.robothy/local-s3-rest.svg)](https://search.maven.org/artifact/io.github.robothy/local-s3-rest/)\n[![Docker](https://img.shields.io/badge/docker-%230db7ed.svg?logo=docker\u0026logoColor=white)](https://hub.docker.com/r/luofuxiang/local-s3)\n[![codecov](https://codecov.io/gh/Robothy/local-s3/branch/main/graph/badge.svg?token=9YLOKDU03D)](https://codecov.io/gh/Robothy/local-s3)\n\nLocalS3 is an Amazon S3 mock service for testing and local development. LocalS3 is based on Netty\nand without heavy dependencies, it starts up quickly and handles requests efficiently.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eSupported Amazon S3 APIs\u003c/b\u003e\u003c/summary\u003e\n\n+ AbortMultipartUpload\n+ CopyObject\n+ CreateBucket\n+ CreateMultipartUpload\n+ CompleteMultipartUpload\n+ DeleteBucket\n+ DeleteBucketEncryption\n+ DeleteBucketPolicy\n+ DeleteBucketReplication\n+ DeleteBucketTagging\n+ DeleteObject\n+ DeleteObjects\n+ DeleteObjectTagging\n+ GetObject\n+ GetObjectTagging\n+ GetBucketAcl\n+ GetBucketEncryption\n+ GetBucketPolicy\n+ GetBucketReplication\n+ GetBucketVersioning\n+ GetBucketTagging\n+ GetBucketLocation\n+ HeadBucket\n+ HeadObject\n+ ListBuckets\n+ ListObjects\n+ ListObjectsV2\n+ ListObjectVersions\n+ ListParts\n+ PutBucketAcl\n+ PutBucketEncryption\n+ PutBucketPolicy\n+ PutBucketReplication\n+ PutBucketVersioning\n+ PutBucketTagging\n+ PutObject\n+ PutObjectTagging\n+ UploadPart\n+ PubPublicAccessBlock\n+ GetPublicAccessBlock\n+ DeletePublicAccessBlock\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eSupported Amazon S3 Vectors APIs\u003c/b\u003e\u003c/summary\u003e\n\n**Vector Bucket Operations:**\n+ CreateVectorBucket\n+ GetVectorBucket\n+ ListVectorBuckets\n+ DeleteVectorBucket\n\n**Vector Index Operations:**\n+ CreateIndex\n+ GetIndex\n+ ListIndexes\n+ DeleteIndex\n\n**Vector Data Operations:**\n+ PutVectors\n+ QueryVectors\n+ GetVectors\n+ ListVectors\n+ DeleteVectors\n\n**Vector Bucket Policy Operations:**\n+ PutVectorBucketPolicy\n+ GetVectorBucketPolicy\n+ DeleteVectorBucketPolicy\n\u003c/details\u003e\n\n\n## Features\n\n+ Support S3 object versioning.\n+ Support S3 Vectors for vector storage and similarity search.\n+ In memory and persistence mode.\n\n## Usages\n\n### Programming with LocalS3\n\nDevelopers could integrate LocalS3 into their own Java applications or testing frameworks via Java APIs.\n\n#### Dependency\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.github.robothy\u003c/groupId\u003e\n    \u003cartifactId\u003elocal-s3-rest\u003c/artifactId\u003e\n\u003c/dependency\u003e\n```\n#### Run LocalS3 in In-Memory mode\n\nBy default, LocalS3 runs in In-Memory mode; all data and metadata retain in the memory.\n\n```java\nLocalS3 localS3 = LocalS3.builder()\n    .port(19090)\n    .build();\n\nlocalS3.start();\n```\n\nCall the stop method to shut down the service gracefully.\n\n```java\nlocalS3.shutdown();\n```\n\n\n#### Run LocalS3 in Persistence mode\n\nWhen LocalS3 runs in persistence mode, a data path is required. LocalS3 loads data from and stores all data into \nthe specified path.\n\n```java\nLocalS3 localS3 = LocalS3.builder()\n    .port(19090)\n    .mode(LocalS3Mode.PERSISTENCE)\n    .dataDirectory(\"C://local-s3\")\n    .build();\n\nlocalS3.start();\n```\n\n#### Run LocalS3 in In-Memory mode with initial data.\n\nLocalS3 loads initial data from the specified path. Changes on such LocalS3 instance only modify the\ndata in memory, not persist to the disk.\n\n```java\nLocalS3 localS3 = LocalS3.builder()\n    .port(-1) // assign a random port\n    .dataDirectory(\"/data\")\n    .build();\n\nlocalS3.start();\n```\n\n### LocalS3 for Junit5\n\nLocalS3 for Junit5 provides a Java annotation `@LocalS3` helps you easily launch S3 services for your tests.\n\n#### Dependency\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.github.robothy\u003c/groupId\u003e\n    \u003cartifactId\u003elocal-s3-jupiter\u003c/artifactId\u003e\n    \u003cscope\u003etest\u003c/scope\u003e\n\u003c/dependency\u003e\n```\n\nWhen you annotate it on test classes or test methods, the LocalS3 extension automatically inject instances with \nthe following parameter types of test methods or lifecycle methods.\n\n+ `AmazonS3`\n+ `S3Client`\n+ `S3VectorsClient`\n+ `LocalS3Endpoint`\n\nExample 1: Inject a `AmazonS3` object to the test method parameter.\n\n```java\n@LocalS3\nclass AppTest {\n  @Test\n  void test(AmazonS3 s3) {\n    s3.createBucket(\"my-bucket\");\n  }\n}\n\n```\n\nExample 2: Inject a `S3Client` object to the test method parameter\n\n```java\nclass AppTest {\n  @Test\n  @LocalS3\n  void test(S3Client client) {\n    client.createBucket(b -\u003e b.bucket(\"my-bucket\"));\n  }\n}\n```\n\nExample 3: Inject a `S3VectorsClient` object to the test method parameter\n\n```java\nclass AppTest {\n  @Test\n  @LocalS3\n  void test(S3VectorsClient vectorsClient) {\n    vectorsClient.createVectorBucket(b -\u003e b.vectorBucketName(\"my-vector-bucket\"));\n  }\n}\n```\n\nExample 4: Inject instances to junit5 lifecycle methods.\n\n```java\n@LocalS3\nclass AppTest {\n  \n  @BeforeAll\n  static void beforeAll(S3Client client) {\n    client.createBucket(b -\u003e b.bucket(\"my-bucket\"));\n  }\n  \n  @Test\n  void test(S3Client client) {\n    client.headBucket(b -\u003e b.bucket(\"my-bucket\"));\n  }\n  \n  @AfterAll\n  static void afterAll(S3Client client) {\n    client.deleteBucket(b -\u003e b.bucket(\"my-bucket\"));\n  }\n}\n```\n\n#### Difference between `@LocalS3` on test classes and test methods\n\nIf `@LocalS3` is on a test class, the Junit5 extension will create a shared service for all test methods in the class\nand shut it down in the \"after all\" callback.\nIf `@LocalS3` is on a test method, the extension creates an exclusive service for the method and shut down the\nservice in the \"after each\" callback.\n\n### Run LocalS3 in Docker\n\nYou can run LocalS3 in Docker since it's image is published to [DockerHub](https://hub.docker.com/r/luofuxiang/local-s3).\n\n```shell\ndocker run --name s3 -d -v C:\\\\local-s3:/data -p 8080:80 luofuxiang/local-s3\n```\n\n### LocalS3 test container\n\nLocalS3 provides a [testcontainers](https://www.testcontainers.org/) implementation. You can run LocalS3 in your tests \nwith testcontainers API.\n\n#### Dependency\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.github.robothy\u003c/groupId\u003e\n    \u003cartifactId\u003elocal-s3-testcontainers\u003c/artifactId\u003e\n\u003c/dependency\u003e\n```\n\n#### Start LocalS3 with testcontainers\n\n```java\n@Testcontainers\npublic class AppTest {\n\n  @Container\n  public LocalS3Container container = new LocalS3Container(\"latest\")\n      .withMode(LocalS3Container.Mode.IN_MEMORY)\n      .withRandomHttpPort();\n  \n  @Test\n  void testS3Operations() {\n    assertTrue(container.isRunning());\n    int port = container.getPort();\n    \n    // Create S3Client for regular S3 operations\n    S3Client s3Client = S3Client.builder()\n        .endpointOverride(URI.create(\"http://localhost:\" + port))\n        .region(Region.US_EAST_1)\n        .credentialsProvider(StaticCredentialsProvider.create(\n            AwsBasicCredentials.create(\"test\", \"test\")))\n        .serviceConfiguration(S3Configuration.builder()\n            .pathStyleAccessEnabled(true)\n            .build())\n        .build();\n    \n    // Test regular S3 operations\n    s3Client.createBucket(b -\u003e b.bucket(\"my-bucket\"));\n    s3Client.putObject(b -\u003e b.bucket(\"my-bucket\").key(\"test.txt\"), \n        RequestBody.fromString(\"Hello World\"));\n  }\n  \n  @Test\n  void testS3VectorOperations() {\n    assertTrue(container.isRunning());\n    int port = container.getPort();\n    \n    // Create S3VectorsClient for vector operations\n    S3VectorsClient vectorsClient = S3VectorsClient.builder()\n        .endpointOverride(URI.create(\"http://localhost:\" + port))\n        .region(Region.US_EAST_1)\n        .credentialsProvider(StaticCredentialsProvider.create(\n            AwsBasicCredentials.create(\"test\", \"test\")))\n        .build();\n    \n    // Test vector operations\n    vectorsClient.createVectorBucket(b -\u003e b.vectorBucketName(\"my-vector-bucket\"));\n    vectorsClient.createIndex(b -\u003e b\n        .vectorBucketName(\"my-vector-bucket\")\n        .indexName(\"my-index\")\n        .dimension(128)\n        .dataType(DataType.FLOAT32)\n        .distanceMetric(DistanceMetric.COSINE));\n  }\n  \n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobothy%2Flocal-s3","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobothy%2Flocal-s3","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobothy%2Flocal-s3/lists"}