https://github.com/lbovet/vertx-rest-storage
Persistence for REST resources in the filesystem or a redis database
https://github.com/lbovet/vertx-rest-storage
Last synced: 15 days ago
JSON representation
Persistence for REST resources in the filesystem or a redis database
- Host: GitHub
- URL: https://github.com/lbovet/vertx-rest-storage
- Owner: lbovet
- License: other
- Created: 2013-02-08T21:14:21.000Z (about 12 years ago)
- Default Branch: master
- Last Pushed: 2017-06-09T06:36:09.000Z (almost 8 years ago)
- Last Synced: 2025-04-15T21:47:52.168Z (15 days ago)
- Language: Java
- Size: 3.61 MB
- Stars: 11
- Watchers: 4
- Forks: 10
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# vertx-rest-storage
[](https://drone.io/github.com/swisspush/vertx-rest-storage/latest)
[]()Persistence for REST resources in the filesystem or a redis database.
Stores resources in a hierarchical way according to their URI. It actually implements a generic CRUD REST service.
It uses usual mime mapping to determine content type so you can also use it as a web server. Without extension, JSON is assumed.
The following methods are supported on leaves (documents):
* GET: Returns the content of the resource.
* PUT: Stores the request body in the resource.
* DELETE: Deletes the resource.The following methods are supported on intermediate nodes (collections):
* GET: Returns the list of collection members. Serves JSON and HTML representations.
* POST (StorageExpand): Returns the expanded content of the sub resources of the (collection) resource. The depth is limited to 1 level. See description below
* DELETE: Delete the collection and all its members.Runs either as a module or can be integrated into an existing application by instantiating the RestStorageHandler class directly.
## Run it
1. clone the repository.
1. run `gradle build -x test`
1. run the fatjar with `java -jar build/libs/rest-storage-x.x.x-all.jar
1. you get a rest-storage, that stores to the filesystem in the directory where you started it. If you want to use the rest-storage with redis, you have to pass the configuration over a json file with `-conf conf.json`## Features
### GET
Invoking GET request on a leave (document) returns the content of the resource.
> GET /storage/resources/resource_1Invoking GET request on a collection returns a list of collection members.
> GET /storage/resources/#### Parameters
| Parameter | Description |
|:--------- | :----------- |
| limit | defines the amount of returned resources |
| offset | defines the amount of resources to skip. Can be used in combination with limit to provide pageing functionality |##### Examples
Given a collection of ten items (res1-res10) under the path /server/tests/offset/resources/| Request | Returned items |
|:--------- | :----------- |
| **GET** /server/tests/offset/resources/?limit=10 | all |
| **GET** /server/tests/offset/resources/?limit=99 | all |
| **GET** /server/tests/offset/resources/?limit=5 | res1,res10,res2,res3,res4 |
| **GET** /server/tests/offset/resources/?offset=2 | res2,res3,res4,res5,res6,res7,res8,res9 |
| **GET** /server/tests/offset/resources/?offset=11 | no items (empty array) |
| **GET** /server/tests/offset/resources/?offset=2&limit=-1 | res2,res3,res4,res5,res6,res7,res8,res9 |
| **GET** /server/tests/offset/resources/?offset=0&limit=3 | res1,res10,res2 |
| **GET** /server/tests/offset/resources/?offset=1&limit=10 | res10,res2,res3,res4,res5,res6,res7,res8,res9 |The returned json response look like this:
```json
{
"resources": [
"res1",
"res10",
"res2",
"res3",
"res4"
]
}
```### StorageExpand
The StorageExpand feature expands the hierarchical resources and returns them as a single concatenated json resource.
Having the following resources in the storage
```sh
key: data:test:collection:resource1 value: {"myProp1": "myVal1"}
key: data:test:collection:resource2 value: {"myProp2": "myVal2"}
key: data:test:collection:resource3 value: {"myProp3": "myVal3"}
```
would lead to this result```json
{
"collection" : {
"resource1" : {
"myProp1": "myVal1"
},
"resource2" : {
"myProp2": "myVal2"
},
"resource3" : {
"myProp3": "myVal3"
}
}
}
```
##### UsageTo use the StorageExpand feature you have to make a POST request to the desired collection to expand having the url paramter **storageExpand=true**. Also you wil have
to send the names of the subresources in the body of the request. Using the example above, the request would look like this:**POST /yourStorageURL/collection** with the body:
```json
{
"subResources" : ["resource1", "resource2", "resource3"]
}
```
### Lock Mechanism
The lock mechanism allows you to lock a resource for a specified time. This way only the owner of the lock is able to write or delete the given resource.
To lock a resource, you have to add the following headers to your PUT / DELETE request.| Headers | Type | Default value | Description |
|:------- | :--- | :------------ | :---------- |
|x-lock | String | | The owner of the lock. |
|x-lock-mode | silent | **silent** | Any PUT or DELETE performed on this resource without the valid owner will have no effect and get *200 OK* back. |
| | reject | | Any PUT or DELETE performed on this resource without the valid owner will have no effect and get *409 Conflict* back. |
|x-lock-expire-after | long | **300** | Defines the lock lifetime. The default value is set to *300* seconds. |
|x-expire-after | long | | Defines the lifetime of a resource |`Warning:` The lock will be always removed if you perform a DELETE on a collection containing a locked resource. There is no check for locks in collections.
### Store data compressed
In order to optimize the memory usage when using the redis storage, it's possible to store resources compressed using
the gzip compression algorithm.To store a resource compressed, add the following header to the PUT request:
> x-stored-compressed: trueWhen making a GET request to a compressed resource, the resource will be uncompressed before returning. No additional header is required!
**Restrictions**
The data compression feature is not compatible with all vertx-rest-storage features. The following listing contains the restrictions of this feature:
* Data compression is available in redis storage only
* Data compression cannot be used with _merge=true_ url parameter concurrently. Such PUT requests will be rejected.
* Compressed resources cannot be used in _storageExpand_ requests. _storageExpand_ requests to a collection containing a compressed resource will be rejected.
* If a resource is already stored in a different compression state (state = not compressed, compressed) as the compression of sent resource, the stored resource will be overwritten in every case. Like this we prevent unexpected behaviour considering the etag mechanism.## Configuration
The following configuration values are available:
| Property | Type | Default value | Description |
|:--------- | :----------- | :----------- | :----------- |
| root | common | . | The prefix for the directory or redis key |
| storageType | common | filesystem | The storage implementation to use. Choose between filesystem or redis |
| port | common | 8989 | The port the mod listens to. |
| prefix | common | / | The part of the URL path before this handler (aka "context path" in JEE terminology) |
| storageAddress | common | resource-storage | The eventbus address the mod listens to. |
| editorConfig | common | | Additional configuration values for the editor |
| redisHost | redis | localhost | The host where redis is running on |
| redisPort | redis | 6379 | The port where redis is running on |
| expirablePrefix | redis | rest-storage:expirable | The prefix for expirable data redis keys |
| resourcesPrefix | redis | rest-storage:resources | The prefix for resources redis keys |
| collectionsPrefix | redis | rest-storage:collections | The prefix for collections redis keys |
| deltaResourcesPrefix | redis | delta:resources | The prefix for delta resources redis keys |
| deltaEtagsPrefix | redis | delta:etags | The prefix for delta etags redis keys |
| lockPrefix | redis | rest-storage:locks | The prefix for lock redis keys |
| resourceCleanupAmount | redis | 100000 | The maximum amount of resources to clean in a single cleanup run |### Configuration util
The configurations have to be passed as JsonObject to the module. For a simplyfied configuration the _ModuleConfigurationBuilder_ can be used.
Example:
```java
ModuleConfiguration config = with()
.redisHost("anotherhost")
.redisPort(1234)
.editorConfig(new JsonObject().put("myKey", "myValue"))
.build();JsonObject json = config.asJsonObject();
```Properties not overriden will not be changed. Thus remaining default.
To use default values only, the _ModuleConfiguration_ constructor without parameters can be used:
```java
JsonObject json = new ModuleConfiguration().asJsonObject();
```## Storage types
Currently there are two storage types supported. File system storage and redis storage.
### File System Storage
The data is stored hierarchically on the file system. This is the default storage type when not overriden in the configuration.### Redis Storage
The data is stored in a redis database.
Caution: The redis storage implementation does not currently support streaming. Avoid transfering too big payloads since they will be entirely copied in memory.## Dependencies
This module uses Vert.x v3.2.0 (or later), so **Java 8** is required.## Use gradle with alternative repositories
As standard the default maven repositories are set.
You can overwrite these repositories by setting these properties (`-Pproperty=value`):* `repository` this is the repository where resources are fetched
* `uploadRepository` the repository used in `uploadArchives` for releases
* `snapshotRepository` the repository used in `uploadArchives` for snapshot
* `repoUsername` the username for uploading archives
* `repoPassword` the password for uploading archives[](https://bitdeli.com/free "Bitdeli Badge")