|
| 1 | +# opa-async-java-client |
| 2 | + |
| 3 | + |
| 4 | +An asynchronous java client library for the [OpenPolicyAgent](https://www.openpolicyagent.org/) [REST API](https://www.openpolicyagent.org/docs/latest/rest-api/). |
| 5 | + |
| 6 | + |
| 7 | +This repository has two components: |
| 8 | + |
| 9 | +* `opa-async-java-client` is the actual client for the OPA [REST API](https://www.openpolicyagent.org/docs/latest/rest-api/) |
| 10 | +* `rego-java` a library that models the Open Policy Agent policy language [Rego](https://www.openpolicyagent.org/docs/how-do-i-write-policies.html) |
| 11 | + |
| 12 | + |
| 13 | +The design of the project is borrowed from [Bisnode/opa-java-client](https://github.com/Bisnode/opa-java-client), but |
| 14 | +uses an async programming model instead, which makes it suitable to be used in a reactive application stack. |
| 15 | + |
| 16 | +This client library uses the JDK11+ HttpClient by default, but allows you to plug in your own http-client by providing |
| 17 | +an implementation for the [OpaRestClient](https://github.com/xenit-eu/opa-async-java-client/blob/main/opa-async-java-client/src/main/java/eu/xenit/contentcloud/abac/opa/client/rest/OpaRestClient.java) |
| 18 | +interface. |
| 19 | + |
| 20 | +## Installation |
| 21 | + |
| 22 | +**Prerequisites:** Java 11 or higher |
| 23 | + |
| 24 | +Using Gradle: |
| 25 | + |
| 26 | +```groovy |
| 27 | +implementation "eu.xenit.contentcloud.abac:opa-async-java-client:${version}" |
| 28 | +``` |
| 29 | + |
| 30 | +Using Maven: |
| 31 | + |
| 32 | +```xml |
| 33 | +<dependency> |
| 34 | + <groupId>eu.xenit.contentcloud.abac</groupId> |
| 35 | + <artifactId>opa-async-java-client</artifactId> |
| 36 | + <version>${version}</version> |
| 37 | +</dependency> |
| 38 | +``` |
| 39 | + |
| 40 | +## Usage |
| 41 | + |
| 42 | +Create an `OpaClient` instance: |
| 43 | + |
| 44 | +``` |
| 45 | +OpaClient client = OpaClient.builder() |
| 46 | + .url("http://localhost:8181") |
| 47 | + .build(); |
| 48 | +``` |
| 49 | + |
| 50 | +### Policies |
| 51 | + |
| 52 | +#### List the ids of all policies: |
| 53 | +``` |
| 54 | +client.listPolicies().thenAccept(response -> { |
| 55 | + var policies = response.getResult(); |
| 56 | + policies.forEach(policy -> log.info("policy id: {}", policy.getId())); |
| 57 | +}); |
| 58 | +``` |
| 59 | + |
| 60 | +#### Get a policy: |
| 61 | +``` |
| 62 | +client.getPolicy("my-policy-id").thenAccept(response -> { |
| 63 | + AbstractSyntaxTree ast = response.getResult().getAst(); |
| 64 | + // do something with the `ast` |
| 65 | +}); |
| 66 | +``` |
| 67 | + |
| 68 | +#### Create a policy |
| 69 | +``` |
| 70 | +client.upsertPolicy("policy_id", "content of the policy").join(); |
| 71 | +``` |
| 72 | + |
| 73 | +### Data API |
| 74 | +### Query API |
| 75 | +### Compile API |
| 76 | + |
| 77 | +### Error handling |
| 78 | + |
| 79 | +Error handling is not yet properly supported. |
| 80 | + |
| 81 | +When the HTTP status code is 400 or higher, the returned |
| 82 | +`CompletableFuture<T>` will fail, with `HttpStatusException` as inner exception cause. |
| 83 | + |
| 84 | +Example: |
| 85 | + |
| 86 | +``` |
| 87 | +var result = client.upsertPolicy("my-policy", "invalid policy"); |
| 88 | +
|
| 89 | +result.handle((response, ex) -> { |
| 90 | + if (ex != null) { |
| 91 | + if (ex.getCause() instanceof HttpStatusException) { |
| 92 | + if (((HttpStatusException) ex.getCause()).getStatusCode() == 400) { |
| 93 | + throw new IllegalArgumentException("policy content is not valid"); |
| 94 | + } |
| 95 | + } |
| 96 | + throw RuntimeException(ex); |
| 97 | + } |
| 98 | +
|
| 99 | + // happy path |
| 100 | + return response; |
| 101 | +}); |
| 102 | +``` |
0 commit comments