Skip to content
This repository was archived by the owner on Jul 1, 2024. It is now read-only.

Commit 6c3f97d

Browse files
authored
OPAClient: convert last argument into options grab-bag (#67)
* OPAClient: convert last argument into options grab-bag ...allowing the control of low-level fetch() options, too. Signed-off-by: Stephan Renatus <stephan@styra.com>
1 parent 84f5751 commit 6c3f97d

File tree

2 files changed

+43
-11
lines changed

2 files changed

+43
-11
lines changed

src/opaclient.ts

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
} from "./sdk/models/operations";
77
import { SDKOptions } from "./lib/config";
88
import { HTTPClient } from "./lib/http";
9+
import { RequestOptions as FetchOptions } from "./lib/sdks";
910

1011
export type { Input, Result };
1112

@@ -29,6 +30,13 @@ export type Options = {
2930
sdk?: SDKOptions;
3031
};
3132

33+
/** Extra per-request options for using the high-level SDK's
34+
* evaluate/evaluateDefault methods.
35+
*/
36+
export interface RequestOptions<Res> extends FetchOptions {
37+
fromResult?: (res?: Result) => Res;
38+
}
39+
3240
/** OPAClient is the starting point for using the high-level API.
3341
*
3442
* Use {@link Opa} if you need some low-level customization.
@@ -60,50 +68,62 @@ export class OPAClient {
6068
*
6169
* @param path - The path to the policy, without `/v1/data`: use `authz/allow` to evaluate policy `data.authz.allow`.
6270
* @param input - The input to the policy, if needed.
63-
* @param fromResult - A function that is used to transform the policy evaluation result (which could be `undefined`).
71+
* @param opts - Per-request options to control how the policy evaluation result is to be transformed
72+
* into `Res` (via `fromResult`), and low-level fetch options.
6473
*/
6574
async evaluate<In extends Input | ToInput, Res>(
6675
path: string,
6776
input?: In,
68-
fromResult?: (res?: Result) => Res,
77+
opts?: RequestOptions<Res>,
6978
): Promise<Res> {
7079
let result: ExecutePolicyWithInputResponse | ExecutePolicyResponse;
7180

7281
if (input === undefined) {
73-
result = await this.opa.executePolicy({ path });
82+
result = await this.opa.executePolicy({ path }, opts);
7483
} else {
7584
let inp: Input;
7685
if (implementsToInput(input)) {
7786
inp = input.toInput();
7887
} else {
7988
inp = input;
8089
}
81-
result = await this.opa.executePolicyWithInput({
82-
path,
83-
requestBody: { input: inp },
84-
});
90+
result = await this.opa.executePolicyWithInput(
91+
{
92+
path,
93+
requestBody: { input: inp },
94+
},
95+
opts,
96+
);
8597
}
8698
if (!result.successfulPolicyEvaluation) throw `no result in API response`;
8799
const res = result.successfulPolicyEvaluation.result;
100+
const fromResult = opts?.fromResult;
88101
return fromResult ? fromResult(res) : (res as Res);
89102
}
90103

91104
/** `evaluateDefault` is used to evaluate the server's default policy with optional input.
92105
*
93106
* @param input - The input to the default policy, defaults to `{}`.
94-
* @param fromResult - A function that is used to transform the policy evaluation result (which could be `undefined`).
107+
* @param opts - Per-request options to control how the policy evaluation result is to be transformed
108+
* into `Res` (via `fromResult`), and low-level fetch options.
95109
*/
96110
async evaluateDefault<In extends Input | ToInput, Res>(
97111
input?: In,
98-
fromResult?: (res?: Result) => Res,
112+
opts?: RequestOptions<Res>,
99113
): Promise<Res> {
100114
let inp = input ?? {};
101115
if (implementsToInput(inp)) {
102116
inp = inp.toInput();
103117
}
104-
const resp = await this.opa.executeDefaultPolicyWithInput(inp);
118+
const resp = await this.opa.executeDefaultPolicyWithInput(
119+
inp,
120+
undefined, // pretty
121+
undefined, // gzipEncoding
122+
opts,
123+
);
105124
if (!resp.result) throw `no result in API response`;
106125
const res = resp.result;
126+
const fromResult = opts?.fromResult;
107127
return fromResult ? fromResult(res) : (res as Res);
108128
}
109129
}

tests/authorizer.test.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,10 @@ allow if {
229229
const res = await new OPAClient(serverURL).evaluate<any, boolean>(
230230
"test/compound_result",
231231
undefined, // input
232-
(r?: Result) => (r as Record<string, any>)["allowed"] ?? false,
232+
{
233+
fromResult: (r?: Result) =>
234+
(r as Record<string, any>)["allowed"] ?? false,
235+
},
233236
);
234237
assert.deepStrictEqual(res, true);
235238
});
@@ -248,6 +251,15 @@ allow if {
248251
assert.strictEqual(called, true);
249252
});
250253

254+
it("allows fetch options", async () => {
255+
const signal = AbortSignal.abort();
256+
assert.rejects(
257+
new OPAClient(serverURL).evaluate("test/p_bool", undefined, {
258+
fetchOptions: { signal },
259+
}),
260+
);
261+
});
262+
251263
it("allows custom headers", async () => {
252264
const authorization = "Bearer opensesame";
253265
const res = await new OPAClient(serverURL, {

0 commit comments

Comments
 (0)