Skip to content

Commit

Permalink
feat: cache busting
Browse files Browse the repository at this point in the history
  • Loading branch information
crowbait committed Dec 12, 2024
1 parent 5670561 commit beb2431
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 100 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ It also supports externally sourced variables for high flexibility and keeping s
- Neatly arranged in a nested, browsable tree structure with drag-and-drop reordering
- View response as dynamic (collapsible) JSON structure or rendered HTML where applicable; view raw if you want to
- 1 "temporary" call, which does not get saved to the workspace list and is synced between your VSCcode instances (open via button on top of call list)
- Cachebusting (optional)

## Variables

Expand Down
5 changes: 4 additions & 1 deletion src/Call-Temporary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class RESTCall_Temporary {
auth = callDefaults.auth;
headers = callDefaults.headers;
body = callDefaults.body;
bustCache = callDefaults.bustCache;

run = (): void => {
this.log.appendLine(`Running ${this.label}`);
Expand Down Expand Up @@ -58,14 +59,16 @@ class RESTCall_Temporary {
method: this.method ?? callDefaults.method,
auth: this.auth ?? callDefaults.auth,
headers: !this.headers ? callDefaults.headers : this.headers.filter((x) => x.header && x.value),
body: this.body ?? callDefaults.body
body: this.body ?? callDefaults.body,
bustCache: this.bustCache ?? callDefaults.bustCache
});
updateFromJsonObject = (json: Partial<JSONCallObject>): void => {
this.url = json.url ?? callDefaults.url;
this.method = json.method ?? callDefaults.method;
this.auth = json.auth ?? callDefaults.auth;
this.headers = json.headers ?? callDefaults.headers;
this.body = json.body ?? callDefaults.body;
this.bustCache = json.bustCache ?? callDefaults.bustCache;
};
saveAndUpdate = (): void => {
this.context.globalState.update(tempCallVscodeStateKey, this.getJsonObject());
Expand Down
9 changes: 7 additions & 2 deletions src/Call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ export const callDefaults: {
auth: string
headers: Array<{header: string, value: string}>
body: string
bustCache: boolean
} = {
url: '',
method: 'GET',
auth: '',
headers: [{header: 'Content-Type', value: 'application/json'}],
body: ''
body: '',
bustCache: false
};
export type JSONCallObject = {
contextValue: 'call'
Expand Down Expand Up @@ -50,6 +52,7 @@ class RESTCall extends ListEntry {
auth = callDefaults.auth;
headers = callDefaults.headers;
body = callDefaults.body;
bustCache = callDefaults.bustCache;

run = (): void => {
this.provider.log.appendLine(`Running ${this.label}`);
Expand Down Expand Up @@ -101,14 +104,16 @@ class RESTCall extends ListEntry {
method: this.method ?? callDefaults.method,
auth: this.auth ?? callDefaults.auth,
headers: !this.headers ? callDefaults.headers : this.headers.filter((x) => x.header && x.value),
body: this.body ?? callDefaults.body
body: this.body ?? callDefaults.body,
bustCache: this.bustCache ?? callDefaults.bustCache
});
updateFromJsonObject = (json: Partial<JSONCallObject>): void => {
this.url = json.url ?? callDefaults.url;
this.method = json.method ?? callDefaults.method;
this.auth = json.auth ?? callDefaults.auth;
this.headers = json.headers ?? callDefaults.headers;
this.body = json.body ?? callDefaults.body;
this.bustCache = json.bustCache ?? callDefaults.bustCache;
this.setIcon();
};
saveAndUpdate = (): void => this.provider.saveAndUpdate();
Expand Down
199 changes: 103 additions & 96 deletions src/CallEdit.html
Original file line number Diff line number Diff line change
Expand Up @@ -92,103 +92,106 @@ <h3 id="title-sub"></h3>
<vscode-tabs id="tabs">
<vscode-tab-header slot="header">UI</vscode-tab-header>
<vscode-tab-panel>
<div id="container-url">
<vscode-single-select id="select-method" placeholder="Method" combobox>
<vscode-option>HEAD</vscode-option>
<vscode-option>GET</vscode-option>
<vscode-option>POST</vscode-option>
<vscode-option>PUT</vscode-option>
<vscode-option>DELETE</vscode-option>
<vscode-option>PATCH</vscode-option>
<vscode-option>TRACE</vscode-option>
<vscode-option>CONNECT</vscode-option>
<vscode-option>OPTIONS</vscode-option>
<vscode-option>SEARCH</vscode-option>
</vscode-single-select>
<vscode-textfield id="input-url" placeholder="URL"></vscode-textfield>
<spacer></spacer>
<vscode-button id="button-run" icon="run">Run</vscode-button>
</div>

<br>

<div id="container-options">
<vscode-collapsible title="Variables">
<p>
Every text input accepts variables in the following formats (quotes are mandatory).<br>
Variables are substituted at runtime.
<br><br>
<vscode-table>
<vscode-table-body slot="body">
<vscode-table-row>
<vscode-table-cell><code>{{file "relative/path.file"}}</code></vscode-table-cell>
<vscode-table-cell>Read an entire local file as string, path relative to workspace</vscode-table-cell>
</vscode-table-row>
<vscode-table-row>
<vscode-table-cell><code>{{env "variable"}}</code></vscode-table-cell>
<vscode-table-cell>Replace with a system environment variable</vscode-table-cell>
</vscode-table-row>
<vscode-table-row>
<vscode-table-cell><code>{{.env "relative/path.file" "variable"}}</code></vscode-table-cell>
<vscode-table-cell>Read "variable" from .env file, path relative to workspace</vscode-table-cell>
</vscode-table-row>
</vscode-table-body>
</vscode-table>
<br>
You can also nest them: <code>{{file "{{.env "settings.env" "file"}}"}}</code>
</p>
</vscode-collapsible>

<vscode-divider></vscode-divider>

<vscode-collapsible title="Auth" open>
<p>
You can auto-construct auth headers using the following variables (quotes are mandatory).<br>
Patterns fitting the variables outlined above will still be substituted (quotes are still mandatory).<br>
Variables are substituted at runtime.
</p>
<ul>
<li><code>{{auth basic "username" "password"}}</code></li>
<li><code>{{auth bearer "token"}}</code></li>
</ul>
<p>
Example: <code>{{auth basic "{{env "systemuser"}}" "{{.env ".env" "API_PW"}}"}}</code>
</p>
<br>
<div style="display: flex; flex-direction: row; gap: 0.5rem; margin-left: 0.5rem; align-items: center;">
<span style="flex-grow: 0; flex-shrink: 0;">Authorization:</span>
<vscode-textfield id="input-auth" placeholder="Value" style="flex: 1; margin: 0.5rem;"></vscode-textfield>
</div>
</vscode-collapsible>

<vscode-divider></vscode-divider>

<vscode-collapsible title="Headers" open>
<div style="display: flex; flex-direction: column; margin: 0.5rem; gap: 0.5rem;">
<vscode-table>
<vscode-table-header slot="header">
<vscode-table-header-cell>Header</vscode-table-header-cell>
<vscode-table-header-cell>Value</vscode-table-header-cell>
<vscode-table-header-cell>DEL</vscode-table-header-cell>
</vscode-table-header>
<vscode-table-body id="table-header" slot="body">
</vscode-table-body>
</vscode-table>
<br>
<vscode-button id="button-add-header" icon="add" style="align-self: flex-end;">Add</vscode-button>
<div style="display: flex; flex-direction: column; gap: 0.5rem">
<div id="container-url">
<vscode-single-select id="select-method" placeholder="Method" combobox>
<vscode-option>HEAD</vscode-option>
<vscode-option>GET</vscode-option>
<vscode-option>POST</vscode-option>
<vscode-option>PUT</vscode-option>
<vscode-option>DELETE</vscode-option>
<vscode-option>PATCH</vscode-option>
<vscode-option>TRACE</vscode-option>
<vscode-option>CONNECT</vscode-option>
<vscode-option>OPTIONS</vscode-option>
<vscode-option>SEARCH</vscode-option>
</vscode-single-select>
<vscode-textfield id="input-url" placeholder="URL"></vscode-textfield>
<spacer></spacer>
<vscode-button id="button-run" icon="run">Run</vscode-button>
</div>
</vscode-collapsible>


<vscode-divider></vscode-divider>
<vscode-checkbox id="bust-cache" label="Bust cache (using query string)"></vscode-checkbox>
</div>

<vscode-collapsible title="Body" open>
<div style="display: flex; flex-direction: column; gap: 0.5rem; margin: 0.5rem;">
<div id="body-errors" hidden></div>
<vscode-textarea id="input-body" placeholder="Request Body" monospace style="width: 100%;" rows="12"></vscode-textarea>
</div>
</vscode-collapsible>
</div>
<br>

<div id="container-options">
<vscode-collapsible title="Variables">
<p>
Every text input accepts variables in the following formats (quotes are mandatory).<br>
Variables are substituted at runtime.
<br><br>
<vscode-table>
<vscode-table-body slot="body">
<vscode-table-row>
<vscode-table-cell><code>{{file "relative/path.file"}}</code></vscode-table-cell>
<vscode-table-cell>Read an entire local file as string, path relative to workspace</vscode-table-cell>
</vscode-table-row>
<vscode-table-row>
<vscode-table-cell><code>{{env "variable"}}</code></vscode-table-cell>
<vscode-table-cell>Replace with a system environment variable</vscode-table-cell>
</vscode-table-row>
<vscode-table-row>
<vscode-table-cell><code>{{.env "relative/path.file" "variable"}}</code></vscode-table-cell>
<vscode-table-cell>Read "variable" from .env file, path relative to workspace</vscode-table-cell>
</vscode-table-row>
</vscode-table-body>
</vscode-table>
<br>
You can also nest them: <code>{{file "{{.env "settings.env" "file"}}"}}</code>
</p>
</vscode-collapsible>

<vscode-divider></vscode-divider>

<vscode-collapsible title="Auth" open>
<p>
You can auto-construct auth headers using the following variables (quotes are mandatory).<br>
Patterns fitting the variables outlined above will still be substituted (quotes are still mandatory).<br>
Variables are substituted at runtime.
</p>
<ul>
<li><code>{{auth basic "username" "password"}}</code></li>
<li><code>{{auth bearer "token"}}</code></li>
</ul>
<p>
Example: <code>{{auth basic "{{env "systemuser"}}" "{{.env ".env" "API_PW"}}"}}</code>
</p>
<br>
<div style="display: flex; flex-direction: row; gap: 0.5rem; margin-left: 0.5rem; align-items: center;">
<span style="flex-grow: 0; flex-shrink: 0;">Authorization:</span>
<vscode-textfield id="input-auth" placeholder="Value" style="flex: 1; margin: 0.5rem;"></vscode-textfield>
</div>
</vscode-collapsible>

<vscode-divider></vscode-divider>

<vscode-collapsible title="Headers" open>
<div style="display: flex; flex-direction: column; margin: 0.5rem; gap: 0.5rem;">
<vscode-table>
<vscode-table-header slot="header">
<vscode-table-header-cell>Header</vscode-table-header-cell>
<vscode-table-header-cell>Value</vscode-table-header-cell>
<vscode-table-header-cell>DEL</vscode-table-header-cell>
</vscode-table-header>
<vscode-table-body id="table-header" slot="body">
</vscode-table-body>
</vscode-table>
<br>
<vscode-button id="button-add-header" icon="add" style="align-self: flex-end;">Add</vscode-button>
</div>
</vscode-collapsible>


<vscode-divider></vscode-divider>

<vscode-collapsible title="Body" open>
<div style="display: flex; flex-direction: column; gap: 0.5rem; margin: 0.5rem;">
<div id="body-errors" hidden></div>
<vscode-textarea id="input-body" placeholder="Request Body" monospace style="width: 100%;" rows="12"></vscode-textarea>
</div>
</vscode-collapsible>
</div>
</vscode-tab-panel>


Expand Down Expand Up @@ -229,9 +232,12 @@ <h3 id="title-sub"></h3>
button_run.onclick = () => vscode.postMessage({channel: 'run', value: data});
const input_auth = document.getElementById('input-auth');
input_auth.onchange = (e) => update('auth', e.target.value);
const check_bustCache = document.getElementById('bust-cache');
check_bustCache.checked =
check_bustCache.onchange = (e) => update('bustCache', e.target.checked);

const table_header = document.getElementById('table-header');
const button_add_header = document.getElementById('button-add-header');

const addHeaderRow = (newIndex, row) => {
const newRow = document.createElement('vscode-table-row');
const cellHeader = document.createElement('vscode-table-cell');
Expand Down Expand Up @@ -312,6 +318,7 @@ <h3 id="title-sub"></h3>
title.innerHTML = data.label;
select_method.value = data.method ?? 'GET';
input_url.value = data.url ?? '';
check_bustCache.checked = data.bustCache;
input_auth.value = data.auth ?? '';
table_header.replaceChildren();
if (data.headers.length > 0) {
Expand Down
11 changes: 10 additions & 1 deletion src/CallRun.html
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,16 @@ <h3 id="title-sub"></h3>


try {
const response = await fetch(data.url, {
const createCachebuster = (url) => {
let ret = '';
if (url.includes('?')) {
ret = `${url}&${Date.now().toString().substring(7)}`;
} else ret = `${url}?${Date.now().toString().substring(7)}`;
title_sub.innerHTML = `${data.method}&nbsp;&nbsp;&nbsp;${ret}`;
return ret;
}
const response = await fetch(
data.bustCache ? createCachebuster(data.url) : data.url, {
method: data.method,
headers: headers,
body: data.body ? data.body : undefined
Expand Down
1 change: 1 addition & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export function activate(context: vscode.ExtensionContext): void {
}));

context.subscriptions.push(vscode.commands.registerCommand('restless-http-rest-client.refresh', () => treeProvider.refreshFromFile()));

context.subscriptions.push(vscode.commands.registerCommand('restless-http-rest-client.openTemporary', () => {
const openCall = (call: RESTCall_Temporary): void => call.edit();
if (tempCall) {
Expand Down

0 comments on commit beb2431

Please sign in to comment.