Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 23 additions & 17 deletions bun-koyeb/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@

[Koyeb](https://www.koyeb.com?ref=unkey) is a developer-friendly serverless platform to deploy apps globally. Koyeb offers a fully managed environment to deploy any apps in seconds without managing any infrastructure. Koyeb supports any programming languages, frameworks, and tools to build your apps.

This example shows how to build an API using bun, secure it with unkey, and deploy it globally on Koyeb.

This example shows how to build an API using Bun, secure it with Unkey, and deploy it globally on Koyeb.

## Requirements

Expand All @@ -28,41 +27,48 @@ bun run dev
## Test

```bash
curl http://localhost:8000 -H "Authorization: Bearer <KEY>"
curl -X POST http://localhost:8000 -H "Authorization: Bearer <KEY>"
```


## Deploy on Koyeb

[![Deploy to Koyeb](https://www.koyeb.com/static/images/deploy/button.svg)](https://app.koyeb.com/deploy?type=git&name=bun-unkey&service_type=web&ports=8000;http;/&env[UNKEY_ROOT_KEY]=&repository=github.com/unkeyed/unkey&branch=main&workdir=examples/bun-koyeb&builder=buildpack)

[![Deploy to Koyeb](https://www.koyeb.com/static/images/deploy/button.svg)](https://app.koyeb.com/deploy?type=git&name=bun-unkey&service_type=web&ports=8000;http;/&env[UNKEY_ROOT_KEY]=<root_key>&env[UNKEY_API_ID]=<api_id>&repository=github.com/unkeyed/unkey&branch=main&workdir=examples/bun-koyeb&builder=dockerfile)

Replace the environment variable placeholders with real values from your Unkey [dashboard](https://app.unkey.com).
Replace the `UNKEY_ROOT_KEY` environment variable with your actual root key from your Unkey [dashboard](https://app.unkey.com).

Then hit the `Deploy` button.
Koyeb will deploy your app in your selected regions and provide a unique URL to access it, or you can configure your own custom domain.

Koyeb will deploy your app in your selected regions and provide a unique URL to access it, or you can configure your own custom domain.

Now that your app is deployed, you can test it:

```sh-session
curl -XPOST https://<YOUR_APP_NAME>-<YOUR_KOYEB_ORG>.koyeb.app -H "Authorization: Bearer <UNKEY_API_KEY>"
```bash
curl -X POST https://<YOUR_APP_NAME>-<YOUR_KOYEB_ORG>.koyeb.app -H "Authorization: Bearer <UNKEY_API_KEY>"
```

It should return a `200` status code and at least the following response, depending on your key settings:
It should return a `200` status code with the Unkey verification response:

```json
{
"valid": true
"meta": {
"requestId": "req_123"
},
"data": {
"valid": true,
"code": "VALID",
"keyId": "key_123",
"name": "my-api-key"
}
}
```


### Manual configuration:

1. Create a [new project](https://app.koyeb.com/apps/new) on Koyeb.
2. Under the advanced section, add your `UNKEY_ROOT_KEY` and `UNKEY_API_ID` environment variables. You can find those in the [Unkey dashboard](https://app.unkey.com).
3. Click on the `Deploy` button

1. In the [Koyeb control panel](https://app.koyeb.com), click **Create Web Service**.
2. Select **GitHub** as the deployment method.
3. Choose your repository and branch.
4. Under **Environment variables**, add your `UNKEY_ROOT_KEY`. You can find this in the [Unkey dashboard](https://app.unkey.com).
5. Click the **Deploy** button.

## References

Expand Down
7 changes: 5 additions & 2 deletions bun-koyeb/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
"version": "1.0.0",
"description": "Deploy a bun API secured by Unkey to Koyeb",
"scripts": {
"dev": "bun run ./index.ts"
"dev": "bun run ./server.ts"
},
"author": "Andreas Thomas",
"license": "ISC",
"dependencies": {
"@unkey/api": "^0.22.1"
"@unkey/api": "^2.0.0"
},
"devDependencies": {
"@types/bun": "^1.2.19"
}
}
37 changes: 23 additions & 14 deletions bun-koyeb/server.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
import { verifyKey } from "@unkey/api";
import { Unkey } from "@unkey/api";

const port = process.env.PORT || 8000;
const UNKEY_ROOT_KEY = process.env.UNKEY_ROOT_KEY || "";

console.log(`Launching Bun HTTP server on port: ${port}, url: http://0.0.0.0:${port} 🚀`);
if (!UNKEY_ROOT_KEY) {
console.error("UNKEY_ROOT_KEY environment variable is required");
process.exit(1);
}

const unkey = new Unkey({ rootKey: UNKEY_ROOT_KEY });

console.log(
`Launching Bun HTTP server on port: ${port}, url: http://0.0.0.0:${port} 🚀`,
);

Bun.serve({
async fetch(req) {
Expand All @@ -11,19 +21,18 @@ Bun.serve({
return new Response("Unauthorized", { status: 401 });
}

const { result, error } = await verifyKey(key);
if (error) {
// This may happen on network errors
// We already retry the request 5 times, but if it still fails, we return an error
console.error(error);
return Response.json("Internal Server Error", { status: 500 });
}
try {
const response = await unkey.keys.verifyKey({ key });

if (!result.valid) {
return new Response("Unauthorized", { status: 401 });
}
if (!response.data.valid) {
return new Response("Unauthorized", { status: 401 });
}

return Response.json(result);
return Response.json(response);
} catch (error) {
console.error("Key verification error:", error);
return new Response("Internal Server Error", { status: 500 });
}
},
port: 8000,
port,
});
29 changes: 29 additions & 0 deletions bun-koyeb/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"compilerOptions": {
// Environment setup & latest features
"lib": ["ESNext"],
"target": "ESNext",
"module": "Preserve",
"moduleDetection": "force",
"jsx": "react-jsx",
"allowJs": true,

// Bundler mode
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,

// Best practices
"strict": true,
"skipLibCheck": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,

// Some stricter flags (disabled by default)
"noUnusedLocals": false,
"noUnusedParameters": false,
"noPropertyAccessFromIndexSignature": false
}
}
7 changes: 5 additions & 2 deletions bun-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
"version": "1.0.0",
"description": "Bun server with unkey.dev",
"scripts": {
"dev": "bun run ./index.ts"
"dev": "bun run ./server.ts"
},
"author": "Andreas Thomas",
"license": "ISC",
"dependencies": {
"@unkey/api": "^0.22.1"
"@unkey/api": "^2.0.0"
},
"devDependencies": {
"@types/bun": "^1.2.19"
}
}
37 changes: 23 additions & 14 deletions bun-server/server.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
import { verifyKey } from "@unkey/api";
import { Unkey } from "@unkey/api";

const port = process.env.PORT || 8000;
const UNKEY_ROOT_KEY = process.env.UNKEY_ROOT_KEY || "";

console.log(`Launching Bun HTTP server on port: ${port}, url: http://0.0.0.0:${port} 🚀`);
if (!UNKEY_ROOT_KEY) {
console.error("UNKEY_ROOT_KEY environment variable is required");
process.exit(1);
}

const unkey = new Unkey({ rootKey: UNKEY_ROOT_KEY });

console.log(
`Launching Bun HTTP server on port: ${port}, url: http://0.0.0.0:${port} 🚀`,
);

Bun.serve({
async fetch(req) {
Expand All @@ -11,19 +21,18 @@ Bun.serve({
return new Response("Unauthorized", { status: 401 });
}

const { result, error } = await verifyKey(key);
if (error) {
// This may happen on network errors
// We already retry the request 5 times, but if it still fails, we return an error
console.error(error);
return Response.json("Internal Server Error", { status: 500 });
}
try {
const response = await unkey.keys.verifyKey({ key });

if (!result.valid) {
return new Response("Unauthorized", { status: 401 });
}
if (!response.data.valid) {
return new Response("Unauthorized", { status: 401 });
}

return Response.json(result);
return Response.json(response);
} catch (error) {
console.error("Key verification error:", error);
return new Response("Internal Server Error", { status: 500 });
}
},
port: 8000,
port,
});
29 changes: 29 additions & 0 deletions bun-server/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"compilerOptions": {
// Environment setup & latest features
"lib": ["ESNext"],
"target": "ESNext",
"module": "Preserve",
"moduleDetection": "force",
"jsx": "react-jsx",
"allowJs": true,

// Bundler mode
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,

// Best practices
"strict": true,
"skipLibCheck": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,

// Some stricter flags (disabled by default)
"noUnusedLocals": false,
"noUnusedParameters": false,
"noPropertyAccessFromIndexSignature": false
}
}
4 changes: 2 additions & 2 deletions cloudflare/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
"devDependencies": {
"@cloudflare/workers-types": "^4.20231016.0",
"typescript": "^5.0.4",
"wrangler": "^3.14.0"
"wrangler": "^3.114.12"
},
"dependencies": {
"@unkey/api": "^0.22.1",
"@unkey/api": "^2.0.0",
"deploy": "^1.0.3",
"pnpm": "^8.9.2",
"run": "^1.4.0"
Expand Down
40 changes: 28 additions & 12 deletions cloudflare/src/worker.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,41 @@
import { verifyKey } from "@unkey/api";
import { Unkey } from "@unkey/api";

export default {
async fetch(request: Request): Promise<Response> {
async fetch(request: Request, env: Env): Promise<Response> {
const UNKEY_ROOT_KEY = env.UNKEY_ROOT_KEY;

if (!UNKEY_ROOT_KEY) {
return new Response("Server configuration error", { status: 500 });
}

const unkey = new Unkey({ rootKey: UNKEY_ROOT_KEY });

// Grab the key from the authorization header
const authHeader = request.headers.get("Authorization");
if (!authHeader) {
return new Response("Unauthorized (No key)", { status: 401 });
}

const key = authHeader.replace("Bearer ", "");

const { result, error } = await verifyKey(key);
if (error) {
console.error(error.message);
try {
const response = await unkey.keys.verifyKey({ key });

if (!response.data.valid) {
return new Response("Unauthorized", { status: 401 });
}

// proceed to handle the request
// since this is a demo, we just return the result
return Response.json(response.data);
} catch (error) {
console.error("Key verification error:", error);
return new Response("Internal Server Error", { status: 500 });
}
if (!result.valid) {
return new Response("Unauthorized", { status: 401 });
}

// proceed to handle the request
// since this is a demo, we just return the result
return Response.json(result);
},
};

// Type definition for the environment
interface Env {
UNKEY_ROOT_KEY: string;
}
4 changes: 4 additions & 0 deletions cloudflare/wrangler.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
name = "cloudflare2"
main = "src/worker.ts"
compatibility_date = "2023-10-17"


[vars]
UNKEY_ROOT_KEY = "<YOUR_UNKEY_ROOT_KEY_HERE>"
4 changes: 3 additions & 1 deletion deno-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ A simple deno server with unkey.

## Run

`deno add npm:@unkey/api@latest`

```bash
deno run --allow-net --allow-env server.ts
deno run server.ts
```

## Test
Expand Down
Loading