Skip to content

Commit

Permalink
feat(http): support custom headers
Browse files Browse the repository at this point in the history
  • Loading branch information
pi0 committed Mar 8, 2023
1 parent fe45e74 commit 4fe7da7
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 25 deletions.
7 changes: 6 additions & 1 deletion docs/content/6.drivers/http.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ const storage = createStorage({

**Options:**

- `base`: Base URL for urls
- `base`: Base URL for urls (**required**)
- `headers`: Custom headers to send on all requests

**Supported HTTP Methods:**

Expand All @@ -24,3 +25,7 @@ const storage = createStorage({
- `setItem`: Maps to http `PUT`. Sends serialized value using body
- `removeItem`: Maps to `DELETE`
- `clear`: Not supported

**Transaction Options:**

- `headers`: Custom headers to be sent on each operation (`getItem`, `setItem`, etc)
68 changes: 47 additions & 21 deletions src/drivers/http.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,50 @@
import { defineDriver } from "./utils";
import { $fetch } from "ofetch";
import { $fetch as _fetch } from "ofetch";
import { joinURL } from "ufo";

export interface HTTPOptions {
base?: string;
base: string;
headers?: Record<string, string>;
}

export default defineDriver((opts: HTTPOptions = {}) => {
export default defineDriver((opts: HTTPOptions) => {
const r = (key: string = "") => joinURL(opts.base!, key.replace(/:/g, "/"));

const rBase = (key: string = "") =>
joinURL(opts.base!, (key || "/").replace(/:/g, "/"), ":");

return {
name: "http",
options: opts,
hasItem(key) {
return $fetch(r(key), { method: "HEAD" })
hasItem(key, topts) {
return _fetch(r(key), {
method: "HEAD",
headers: { ...opts.headers, ...topts.headers },
})
.then(() => true)
.catch(() => false);
},
async getItem(key) {
const value = await $fetch(r(key));
async getItem(key, tops = {}) {
const value = await _fetch(r(key), {
headers: { ...opts.headers, ...tops.headers },
});
return value;
},
async getItemRaw(key) {
const value = await $fetch(r(key), {
async getItemRaw(key, topts) {
const value = await _fetch(r(key), {
headers: {
accept: "application/octet-stream",
...opts.headers,
...topts.headers,
},
});
return value;
},
async getMeta(key) {
const res = await $fetch.raw(r(key), { method: "HEAD" });
async getMeta(key, topts) {
const res = await _fetch.raw(r(key), {
method: "HEAD",
headers: { ...opts.headers, ...topts.headers },
});
let mtime = undefined;
const _lastModified = res.headers.get("last-modified");
if (_lastModified) {
Expand All @@ -43,27 +55,41 @@ export default defineDriver((opts: HTTPOptions = {}) => {
mtime,
};
},
async setItem(key, value) {
await $fetch(r(key), { method: "PUT", body: value });
async setItem(key, value, topts) {
await _fetch(r(key), {
method: "PUT",
body: value,
headers: { ...opts.headers, ...topts.headers },
});
},
async setItemRaw(key, value) {
await $fetch(r(key), {
async setItemRaw(key, value, topts) {
await _fetch(r(key), {
method: "PUT",
body: value,
headers: {
"content-type": "application/octet-stream",
...opts.headers,
...topts.headers,
},
});
},
async removeItem(key) {
await $fetch(r(key), { method: "DELETE" });
async removeItem(key, topts) {
await _fetch(r(key), {
method: "DELETE",
headers: { ...opts.headers, ...topts.headers },
});
},
async getKeys(base) {
const value = await $fetch(rBase(base));
async getKeys(base, topts) {
const value = await _fetch(rBase(base), {
headers: { ...opts.headers, ...topts.headers },
});
return Array.isArray(value) ? value : [];
},
async clear(base) {
await $fetch(rBase(base), { method: "DELETE" });
async clear(base, topts) {
await _fetch(rBase(base), {
method: "DELETE",
headers: { ...opts.headers, ...topts.headers },
});
},
};
});
28 changes: 25 additions & 3 deletions test/drivers/http.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { describe, beforeAll, afterAll } from "vitest";
import { describe, afterAll } from "vitest";
import driver from "../../src/drivers/http";
import { createStorage } from "../../src";
import { createStorageServer } from "../../src/server";
Expand All @@ -7,7 +7,21 @@ import { testDriver } from "./utils";

describe("drivers: http", async () => {
const remoteStorage = createStorage();
const server = createStorageServer(remoteStorage);
const server = createStorageServer(remoteStorage, {
authorize(req) {
if (req.event.node.req.headers["x-global-header"] !== "1") {
// console.log(req.key, req.type, req.event.node.req.headers);
throw new Error("Missing global test header!");
}
if (
req.key === "authorized" &&
req.event.node.req.headers["x-auth-header"] !== "1"
) {
// console.log(req.key, req.type, req.event.node.req.headers);
throw new Error("Missing auth test header!");
}
},
});
const listener = await listen(server.handle, {
port: { random: true },
});
Expand All @@ -17,6 +31,14 @@ describe("drivers: http", async () => {
});

testDriver({
driver: driver({ base: listener!.url }),
driver: driver({
base: listener!.url,
headers: { "x-global-header": "1" },
}),
async additionalTests({ storage }) {
await storage.setItem("authorized", "test", {
headers: { "x-auth-header": "1" },
});
},
});
});

0 comments on commit 4fe7da7

Please sign in to comment.