-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #104 from upstash/dx-784-enrich-examples
Dx 784 enrich examples
- Loading branch information
Showing
18 changed files
with
384 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
|
||
## Deno Examples | ||
|
||
This directory has two deno examples. | ||
|
||
| File | Description | | ||
| --------------- | ----------- | | ||
| `deprecated.ts` | Deno app with the `serve` method which was deprecated with Deno version `0.107.0`. | | ||
| `main.ts` | Up-to-date Deno app with the `Deno.serve` method | | ||
|
||
To run the apps locally, simply set the environment variables `UPSTASH_REDIS_REST_URL` and `UPSTASH_REDIS_REST_TOKEN` and run: | ||
|
||
``` | ||
deno run --allow-net --allow-env main.ts | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { serve } from "https://deno.land/[email protected]/http/server.ts"; | ||
import { Ratelimit } from "https://cdn.skypack.dev/@upstash/ratelimit@latest"; | ||
import { Redis } from "https://esm.sh/@upstash/redis"; | ||
|
||
const server = serve({ port: 8000 }); | ||
|
||
// Create a new ratelimiter, allowing 10 requests per 10 seconds | ||
const ratelimit = new Ratelimit({ | ||
redis: Redis.fromEnv(), | ||
limiter: Ratelimit.slidingWindow(10, "10s"), | ||
analytics: true, | ||
prefix: "@upstash/ratelimit", | ||
}); | ||
|
||
console.log("Server running..."); | ||
|
||
for await (const req of server) { | ||
|
||
if (req.url !== "/") { | ||
continue | ||
} | ||
|
||
// Use a constant string to limit all requests with a single ratelimit | ||
// You can also use a userID, apiKey, or IP address for individual limits. | ||
const identifier = "api"; | ||
|
||
const { success, remaining } = await ratelimit.limit(identifier); | ||
if (!success) { | ||
req.respond({ status: 429, body: "Too Many Requests" }); | ||
continue; | ||
} | ||
|
||
// Perform your expensive calculation here | ||
const body = `Here you go! (Remaining" ${remaining})`; | ||
req.respond({ body }); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { Ratelimit } from "https://cdn.skypack.dev/@upstash/ratelimit@latest"; | ||
import { Redis } from "https://esm.sh/@upstash/redis"; | ||
|
||
// Create a new ratelimiter, allowing 10 requests per 10 seconds | ||
const ratelimit = new Ratelimit({ | ||
redis: Redis.fromEnv(), | ||
limiter: Ratelimit.slidingWindow(10, "10s"), | ||
analytics: true, | ||
prefix: "@upstash/ratelimit", | ||
}); | ||
|
||
async function requestHandler(request: Request): Promise<Response> { | ||
|
||
// Use a constant string to limit all requests with a single ratelimit | ||
// You can also use a userID, apiKey, or IP address for individual limits. | ||
const identifier = "api"; | ||
|
||
const { success, remaining } = await ratelimit.limit(identifier); | ||
if (!success) { | ||
return new Response("Too Many Requests", { status: 429 }); | ||
} | ||
|
||
// Perform your expensive calculation here | ||
const body = `Here you go! (Remaining" ${remaining})`; | ||
return new Response(body, { status: 200 }); | ||
} | ||
|
||
Deno.serve(requestHandler, { port: 8000 }); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"extends": "next/core-web-vitals" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.js | ||
.yarn/install-state.gz | ||
|
||
# testing | ||
/coverage | ||
|
||
# next.js | ||
/.next/ | ||
/out/ | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
*.pem | ||
|
||
# debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# local env files | ||
.env*.local | ||
|
||
# vercel | ||
.vercel | ||
|
||
# typescript | ||
*.tsbuildinfo | ||
next-env.d.ts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# Rate Limiting a Vercel Edge API | ||
|
||
In this example, we define an API using Vercel Edge and utilize | ||
rate limiting to protect it. | ||
|
||
The api is defined in [the route.ts file](https://github.com/upstash/ratelimit/blob/main/examples/vercel-edge/app/api/route.ts) as follows: | ||
|
||
```ts | ||
export const runtime = 'edge'; | ||
|
||
export const dynamic = 'force-dynamic'; | ||
|
||
import { Ratelimit } from "@upstash/ratelimit"; | ||
import { Redis } from "@upstash/redis"; | ||
|
||
// Create a new ratelimiter | ||
const ratelimit = new Ratelimit({ | ||
redis: Redis.fromEnv(), | ||
limiter: Ratelimit.slidingWindow(10, "10 s"), | ||
prefix: "@upstash/ratelimit", | ||
}); | ||
|
||
export async function GET(request: Request) { | ||
|
||
const identifier = "api"; | ||
const { success, limit, remaining } = await ratelimit.limit(identifier); | ||
const response = { | ||
success: success, | ||
limit: limit, | ||
remaining: remaining | ||
} | ||
|
||
if (!success) { | ||
return new Response(JSON.stringify(response), { status: 429 }); | ||
} | ||
return new Response(JSON.stringify(response)); | ||
} | ||
``` | ||
|
||
It runs on Vercel Edge and upon request, it returns the result of the rate limit call. This response is then shown on the home page. | ||
|
||
# Run Locally | ||
|
||
To run the example in your local environment, create a Upstash Redis and set the `UPSTASH_REDIS_REST_URL` and `UPSTASH_REDIS_REST_TOKEN` environment variables. Then run | ||
|
||
``` | ||
npm run dev | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
export const runtime = 'edge'; | ||
|
||
export const dynamic = 'force-dynamic'; | ||
|
||
import { Ratelimit } from "@upstash/ratelimit"; | ||
import { Redis } from "@upstash/redis"; | ||
|
||
// Create a new ratelimiter | ||
const ratelimit = new Ratelimit({ | ||
redis: Redis.fromEnv(), | ||
limiter: Ratelimit.slidingWindow(10, "10 s"), | ||
prefix: "@upstash/ratelimit", | ||
}); | ||
|
||
export async function GET(request: Request) { | ||
|
||
const identifier = "api"; | ||
const { success, limit, remaining } = await ratelimit.limit(identifier); | ||
const response = { | ||
success: success, | ||
limit: limit, | ||
remaining: remaining | ||
} | ||
|
||
if (!success) { | ||
return new Response(JSON.stringify(response), { status: 429 }); | ||
} | ||
return new Response(JSON.stringify(response)); | ||
} |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
@tailwind base; | ||
@tailwind components; | ||
@tailwind utilities; | ||
|
||
:root { | ||
--foreground-rgb: 0, 0, 0; | ||
--background-start-rgb: 249,250,250; | ||
--background-end-rgb: 236,238,238; | ||
} | ||
|
||
@media (prefers-color-scheme: dark) { | ||
:root { | ||
--foreground-rgb: 255, 255, 255; | ||
--background-start-rgb: 0, 0, 0; | ||
--background-end-rgb: 0, 0, 0; | ||
} | ||
} | ||
|
||
body { | ||
color: rgb(var(--foreground-rgb)); | ||
background: linear-gradient( | ||
to bottom, | ||
transparent, | ||
rgb(var(--background-end-rgb)) | ||
) | ||
rgb(var(--background-start-rgb)); | ||
} | ||
|
||
@layer utilities { | ||
.text-balance { | ||
text-wrap: balance; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import type { Metadata } from "next"; | ||
import { Inter } from "next/font/google"; | ||
import "./globals.css"; | ||
|
||
const inter = Inter({ subsets: ["latin"] }); | ||
|
||
export const metadata: Metadata = { | ||
title: "Create Next App", | ||
description: "Generated by create next app", | ||
}; | ||
|
||
export default function RootLayout({ | ||
children, | ||
}: Readonly<{ | ||
children: React.ReactNode; | ||
}>) { | ||
return ( | ||
<html lang="en"> | ||
<body className={inter.className}>{children}</body> | ||
</html> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
"use client"; | ||
import React, { useState } from "react"; | ||
|
||
export default function Home() { | ||
const [status, setStatus] = useState({ | ||
success: true, | ||
limit: 10, | ||
remaining: 10 | ||
}); | ||
|
||
const handleClick = async () => { | ||
try { | ||
const response = await fetch(`/api`); | ||
const data = await response.text(); | ||
setStatus(JSON.parse(data)); | ||
} catch (error) { | ||
console.error("Error fetching data:", error); | ||
setStatus({ | ||
success: false, | ||
limit: -1, | ||
remaining: -1 | ||
}); | ||
} | ||
}; | ||
|
||
return ( | ||
<div className="flex flex-col items-center justify-center min-h-screen"> | ||
<div className="absolute top-1/3 text-center"> | ||
<p className="text-lg">This app is an example of rate limiting an API on Vercel Edge.</p> | ||
<p className="text-lg">Click the button below to call the API and get the rate limit status.</p> | ||
</div> | ||
<div className="absolute top-1/2 grid grid-cols-3 gap-8 justify-center transform -translate-y-1/2"> | ||
{Object.entries(status).map(([key, value]) => ( | ||
<div key={key} className="text-center"> | ||
<div className="font-semibold">{key}</div> | ||
<div>{JSON.stringify(value)}</div> | ||
</div> | ||
))} | ||
</div> | ||
<div className="absolute bottom-1/3"> | ||
<button onClick={handleClick} className="bg-[#dee2e3] hover:bg-[#9aa6a9] transition border-black text-[#5a6769] font-semibold py-2 px-4 rounded-lg"> | ||
Test Rate Limit | ||
</button> | ||
</div> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
/** @type {import('next').NextConfig} */ | ||
const nextConfig = {}; | ||
|
||
export default nextConfig; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
{ | ||
"name": "vercel-edge", | ||
"version": "0.1.0", | ||
"private": true, | ||
"scripts": { | ||
"dev": "next dev", | ||
"build": "next build", | ||
"start": "next start", | ||
"lint": "next lint" | ||
}, | ||
"dependencies": { | ||
"@upstash/ratelimit": "^1.1.3", | ||
"next": "14.2.3", | ||
"react": "^18", | ||
"react-dom": "^18" | ||
}, | ||
"devDependencies": { | ||
"@types/node": "^20", | ||
"@types/react": "^18", | ||
"@types/react-dom": "^18", | ||
"eslint": "^8", | ||
"eslint-config-next": "14.2.3", | ||
"postcss": "^8", | ||
"tailwindcss": "^3.4.1", | ||
"typescript": "^5" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/** @type {import('postcss-load-config').Config} */ | ||
const config = { | ||
plugins: { | ||
tailwindcss: {}, | ||
}, | ||
}; | ||
|
||
export default config; |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import type { Config } from "tailwindcss"; | ||
|
||
const config: Config = { | ||
content: [ | ||
"./pages/**/*.{js,ts,jsx,tsx,mdx}", | ||
"./components/**/*.{js,ts,jsx,tsx,mdx}", | ||
"./app/**/*.{js,ts,jsx,tsx,mdx}", | ||
], | ||
theme: { | ||
extend: { | ||
backgroundImage: { | ||
"gradient-radial": "radial-gradient(var(--tw-gradient-stops))", | ||
"gradient-conic": | ||
"conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", | ||
}, | ||
}, | ||
}, | ||
plugins: [], | ||
}; | ||
export default config; |
Oops, something went wrong.