Skip to content

Commit

Permalink
feat: add JWT support for all the clients (#13)
Browse files Browse the repository at this point in the history
* feat: add JWT support for all the clients

* chore: remove ApiClient in lib.rs

* chore: various fixes including name changes on classes across clients

* chore: do JWT instead of JWTToken for rust

* chore: make FliptClient private
  • Loading branch information
yquansah authored Jan 10, 2024
1 parent 3003ce5 commit 13496e2
Show file tree
Hide file tree
Showing 15 changed files with 191 additions and 104 deletions.
21 changes: 14 additions & 7 deletions flipt-client-java/src/main/java/com/flipt/api/FliptClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
import okhttp3.OkHttpClient;

public class FliptClient {
private Evaluation evaluation;
private final Evaluation evaluation;

public FliptClient(String url, String token, int timeout) {
private FliptClient(String url, String clientToken, String jwtToken, int timeout) {
OkHttpClient httpClient =
new OkHttpClient.Builder().callTimeout(Duration.ofSeconds(timeout)).build();
this.evaluation = new Evaluation(httpClient, url, token);
this.evaluation = new Evaluation(httpClient, url, clientToken, jwtToken);
}

public Evaluation evaluation() {
Expand All @@ -24,7 +24,9 @@ public static FliptClientBuilder builder() {
public static final class FliptClientBuilder {
private String baseURL = "http://localhost:8080";

private String token = "";
private String clientToken = "";

private String jwtToken = "";

private int timeout = 60;

Expand All @@ -35,8 +37,13 @@ public FliptClientBuilder url(String url) {
return this;
}

public FliptClientBuilder token(String token) {
this.token = token;
public FliptClientBuilder clientToken(String token) {
this.clientToken = token;
return this;
}

public FliptClientBuilder jwtToken(String token) {
this.jwtToken = token;
return this;
}

Expand All @@ -46,7 +53,7 @@ public FliptClientBuilder timeout(int timeout) {
}

public FliptClient build() {
return new FliptClient(baseURL, token, timeout);
return new FliptClient(baseURL, clientToken, jwtToken, timeout);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@
public class Evaluation {
private final OkHttpClient httpClient;
private final String baseURL;
private final String token;
private final String clientToken;
private final String jwtToken;
private final ObjectMapper objectMapper;

public Evaluation(OkHttpClient httpClient, String baseURL, String token) {
public Evaluation(OkHttpClient httpClient, String baseURL, String clientToken, String jwtToken) {
this.httpClient = httpClient;
this.baseURL = baseURL;
this.token = token;
this.clientToken = clientToken;
this.jwtToken = jwtToken;
this.objectMapper =
JsonMapper.builder()
.addModule(new Jdk8Module())
Expand Down Expand Up @@ -66,8 +68,10 @@ private Request.Builder makeRequest(EvaluationRequest request, URL url) {

Request.Builder httpRequest = new Request.Builder().url(url).method("POST", body);

if (!this.token.isEmpty()) {
httpRequest.addHeader("Authorization", String.format("Bearer %s", this.token));
if (!this.clientToken.isEmpty()) {
httpRequest.addHeader("Authorization", String.format("Bearer %s", this.clientToken));
} else if (!this.jwtToken.isEmpty()) {
httpRequest.addHeader("Authorization", String.format("JWT %s", this.jwtToken));
}

return httpRequest;
Expand Down Expand Up @@ -118,8 +122,10 @@ public BatchEvaluationResponse batch(BatchEvaluationRequest request) {

Request.Builder httpRequest = new Request.Builder().url(url).method("POST", body);

if (!this.token.isEmpty()) {
httpRequest.addHeader("Authorization", String.format("Bearer %s", this.token));
if (!this.clientToken.isEmpty()) {
httpRequest.addHeader("Authorization", String.format("Bearer %s", this.clientToken));
} else if (!this.jwtToken.isEmpty()) {
httpRequest.addHeader("Authorization", String.format("JWT %s", this.jwtToken));
}

try {
Expand Down
6 changes: 3 additions & 3 deletions flipt-client-java/src/test/java/TestFliptClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ void testVariant() {
assert !fliptURL.isEmpty();
assert !authToken.isEmpty();

FliptClient fc = FliptClient.builder().url(fliptURL).token(authToken).build();
FliptClient fc = FliptClient.builder().url(fliptURL).clientToken(authToken).build();

Map<String, String> context = new HashMap<>();
context.put("fizz", "buzz");
Expand All @@ -35,7 +35,7 @@ void testBoolean() {
assert !fliptURL.isEmpty();
assert !authToken.isEmpty();

FliptClient fc = FliptClient.builder().url(fliptURL).token(authToken).build();
FliptClient fc = FliptClient.builder().url(fliptURL).clientToken(authToken).build();

Map<String, String> context = new HashMap<>();
context.put("fizz", "buzz");
Expand All @@ -57,7 +57,7 @@ void testBatch() {
assert !fliptURL.isEmpty();
assert !authToken.isEmpty();

FliptClient fc = FliptClient.builder().url(fliptURL).token(authToken).build();
FliptClient fc = FliptClient.builder().url(fliptURL).clientToken(authToken).build();

Map<String, String> context = new HashMap<>();
context.put("fizz", "buzz");
Expand Down
44 changes: 23 additions & 21 deletions flipt-client-node/src/evaluation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,34 @@ import {

export class Evaluation {
private url: string;
private token: string;
private headers: object;
private timeout: number;

public constructor(url: string, token: string, timeout: number) {
public constructor(
url: string,
clientToken: string,
jwtToken: string,
timeout: number
) {
this.url = url;
this.token = token;
this.headers = {};
if (!!clientToken) {
this.headers["Authorization"] = `Bearer ${clientToken}`;
}
if (!!jwtToken) {
this.headers["Authorization"] = `JWT ${jwtToken}`;
}
this.timeout = timeout;
}

public async variant(
request: EvaluationRequest
): Promise<VariantEvaluationResponse> {
const headers = {};
if (this.token !== "") {
headers["Authorization"] = `Bearer ${this.token}`;
}

const response = await fetch(`${this.url}/evaluate/v1/variant`, {
method: "POST",
headers,
headers: {
...this.headers
},
body: JSON.stringify(request),
signal: AbortSignal.timeout(this.timeout * 1000)
});
Expand All @@ -46,14 +54,11 @@ export class Evaluation {
public async boolean(
request: EvaluationRequest
): Promise<BooleanEvaluationResponse> {
const headers = {};
if (this.token !== "") {
headers["Authorization"] = `Bearer ${this.token}`;
}

const response = await fetch(`${this.url}/evaluate/v1/boolean`, {
method: "POST",
headers,
headers: {
...this.headers
},
body: JSON.stringify(request),
signal: AbortSignal.timeout(this.timeout * 1000)
});
Expand All @@ -72,14 +77,11 @@ export class Evaluation {
public async batch(
request: BatchEvaluationRequest
): Promise<BatchEvaluationResponse> {
const headers = {};
if (this.token !== "") {
headers["Authorization"] = `Bearer ${this.token}`;
}

const response = await fetch(`${this.url}/evaluate/v1/batch`, {
method: "POST",
headers,
headers: {
...this.headers
},
body: JSON.stringify(request),
signal: AbortSignal.timeout(this.timeout * 1000)
});
Expand Down
26 changes: 18 additions & 8 deletions flipt-client-node/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,48 @@
import { Evaluation } from "./evaluation";

interface FliptApiClientOptions {
interface FliptClientOptions {
url?: string;
token?: string;
clientToken?: string;
jwtToken?: string;
timeout?: number;
}

const defaultFliptClientOptions: FliptApiClientOptions = {
const defaultFliptClientOptions: FliptClientOptions = {
url: "http://localhost:8080",
token: "",
clientToken: "",
jwtToken: "",
timeout: 60
};

export class FliptClient {
public evaluation: Evaluation;

public constructor(options?: FliptApiClientOptions) {
public constructor(options?: FliptClientOptions) {
const clientOptions = {
...defaultFliptClientOptions
};

if (options?.clientToken !== undefined && options?.jwtToken != undefined) {
throw new Error("can not define both client token and jwt token");
}

if (options?.url !== undefined) {
clientOptions.url = options.url;
}
if (options?.token !== undefined) {
clientOptions.token = options.token;
if (options?.clientToken !== undefined) {
clientOptions.clientToken = options.clientToken;
}
if (options?.jwtToken !== undefined) {
clientOptions.jwtToken = options.jwtToken;
}
if (options?.timeout !== undefined) {
clientOptions.timeout = options.timeout;
}

this.evaluation = new Evaluation(
clientOptions.url,
clientOptions.token,
clientOptions.clientToken,
clientOptions.jwtToken,
clientOptions.timeout
);
}
Expand Down
6 changes: 3 additions & 3 deletions flipt-client-node/src/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ if (!authToken) {
}

test("variant", async () => {
const client = new FliptClient({ url: fliptUrl, token: authToken });
const client = new FliptClient({ url: fliptUrl, clientToken: authToken });

const variant = await client.evaluation.variant({
namespaceKey: "default",
Expand All @@ -30,7 +30,7 @@ test("variant", async () => {
});

test("boolean", async () => {
const client = new FliptClient({ url: fliptUrl, token: authToken });
const client = new FliptClient({ url: fliptUrl, clientToken: authToken });

const boolean = await client.evaluation.boolean({
namespaceKey: "default",
Expand All @@ -45,7 +45,7 @@ test("boolean", async () => {
});

test("batch", async () => {
const client = new FliptClient({ url: fliptUrl, token: authToken });
const client = new FliptClient({ url: fliptUrl, clientToken: authToken });
const batch = await client.evaluation.batch({
requests: [
{
Expand Down
9 changes: 7 additions & 2 deletions flipt-client-python/flipt/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import typing
from .evaluation import Evaluation


class FliptClient:
def __init__(
self, url: str = "http://localhost:8080", token: str = "", timeout: int = 60
self,
url: str = "http://localhost:8080",
client_token: typing.Optional[str] = None,
jwt_token: typing.Optional[str] = None,
timeout: int = 60,
):
self.evaluation = Evaluation(url, token, timeout)
self.evaluation = Evaluation(url, client_token, jwt_token, timeout)
33 changes: 16 additions & 17 deletions flipt-client-python/flipt/evaluation/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import httpx
import typing
import json
from .models import (
BatchEvaluationRequest,
Expand All @@ -10,19 +11,25 @@


class Evaluation:
def __init__(self, url: str, token: str, timeout: int):
def __init__(
self,
url: str,
client_token: typing.Optional[str],
jwt_token: typing.Optional[str],
timeout: int,
):
self.url = url
self.token = token
self.headers = {}
if client_token != None:
self.headers["Authorization"] = f"Bearer {client_token}"
if jwt_token != None:
self.headers["Authorization"] = f"JWT {jwt_token}"
self.timeout = timeout

def variant(self, request: EvaluationRequest) -> VariantEvaluationResponse:
headers = {}
if self.token != "":
headers["Authorization"] = f"Bearer {self.token}"

response = httpx.post(
f"{self.url}/evaluate/v1/variant",
headers=headers,
headers=self.headers,
json=request.model_dump(),
timeout=self.timeout,
)
Expand All @@ -40,13 +47,9 @@ def variant(self, request: EvaluationRequest) -> VariantEvaluationResponse:
return VariantEvaluationResponse.model_validate_json(variant_response)

def boolean(self, request: EvaluationRequest) -> BooleanEvaluationResponse:
headers = {}
if self.token != "":
headers["Authorization"] = f"Bearer {self.token}"

response = httpx.post(
f"{self.url}/evaluate/v1/boolean",
headers=headers,
headers=self.headers,
json=request.model_dump(),
timeout=self.timeout,
)
Expand All @@ -64,13 +67,9 @@ def boolean(self, request: EvaluationRequest) -> BooleanEvaluationResponse:
return BooleanEvaluationResponse.model_validate_json(boolean_response)

def batch(self, request: BatchEvaluationRequest) -> BatchEvaluationResponse:
headers = {}
if self.token != "":
headers["Authorization"] = f"Bearer {self.token}"

response = httpx.post(
f"{self.url}/evaluate/v1/batch",
headers=headers,
headers=self.headers,
json=request.model_dump(),
timeout=self.timeout,
)
Expand Down
2 changes: 1 addition & 1 deletion flipt-client-python/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def setUp(self) -> None:
if auth_token is None:
raise Exception("FLIPT_AUTH_TOKEN not set")

self.flipt_client = FliptClient(url=flipt_url, token=auth_token)
self.flipt_client = FliptClient(url=flipt_url, client_token=auth_token)

def test_variant(self):
variant = self.flipt_client.evaluation.variant(
Expand Down
3 changes: 3 additions & 0 deletions flipt-client-rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ author = ["Flipt Devs <[email protected]>"]
license = "MIT"
keywords = ["flipt"]

[features]
flipt_integration = []

[dependencies]
chrono = { version = "0.4.23", default-features = false, features = ["serde", "clock"] }
reqwest = { version = "0.11.13", default-features = false, features = ["json", "rustls-tls"] }
Expand Down
Loading

0 comments on commit 13496e2

Please sign in to comment.