mirror of
https://github.com/AustinKelsay/plebdevs.git
synced 2025-06-05 00:32:03 +00:00
Remove getAllUsers endpoint, add checks to image proxy endpoint, setup local in memory cache for rate limitng in dev, added NODE_ENV variable
This commit is contained in:
parent
735ed2b7db
commit
7953bb641f
@ -24,4 +24,18 @@ module.exports = removeImports({
|
||||
}
|
||||
];
|
||||
},
|
||||
env: {
|
||||
KV_URL: process.env.NODE_ENV !== 'production'
|
||||
? process.env.REDIS_URL
|
||||
: process.env.KV_URL,
|
||||
KV_REST_API_URL: process.env.NODE_ENV !== 'production'
|
||||
? process.env.REDIS_URL
|
||||
: process.env.KV_REST_API_URL,
|
||||
KV_REST_API_TOKEN: process.env.NODE_ENV !== 'production'
|
||||
? 'dummy_token'
|
||||
: process.env.KV_REST_API_TOKEN,
|
||||
KV_REST_API_READ_ONLY_TOKEN: process.env.NODE_ENV !== 'production'
|
||||
? 'dummy_token'
|
||||
: process.env.KV_REST_API_READ_ONLY_TOKEN,
|
||||
},
|
||||
});
|
@ -2,13 +2,45 @@ import { NextResponse } from 'next/server';
|
||||
import { Ratelimit } from '@upstash/ratelimit';
|
||||
import { kv } from '@vercel/kv';
|
||||
|
||||
const ratelimit = new Ratelimit({
|
||||
redis: kv,
|
||||
// 5 requests from the same IP in 10 seconds
|
||||
limiter: Ratelimit.slidingWindow(5, '10 s'),
|
||||
analytics: true,
|
||||
timeout: 1000, // 1 second
|
||||
});
|
||||
// In-memory store for development
|
||||
const inMemoryStore = new Map();
|
||||
|
||||
// Simple in-memory rate limiter for development
|
||||
const localRatelimit = {
|
||||
limit: async (key) => {
|
||||
const now = Date.now();
|
||||
const windowMs = 10 * 1000; // 10 seconds
|
||||
const maxRequests = 5;
|
||||
|
||||
const requestLog = inMemoryStore.get(key) || [];
|
||||
const windowStart = now - windowMs;
|
||||
|
||||
const recentRequests = requestLog.filter(timestamp => timestamp > windowStart);
|
||||
const isRateLimited = recentRequests.length >= maxRequests;
|
||||
|
||||
if (!isRateLimited) {
|
||||
recentRequests.push(now);
|
||||
inMemoryStore.set(key, recentRequests);
|
||||
}
|
||||
|
||||
return {
|
||||
success: !isRateLimited,
|
||||
limit: maxRequests,
|
||||
remaining: Math.max(0, maxRequests - recentRequests.length),
|
||||
reset: windowStart + windowMs,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
// Use local rate limiter for development, Upstash for production
|
||||
const ratelimit = process.env.NODE_ENV === 'production'
|
||||
? new Ratelimit({
|
||||
redis: kv,
|
||||
limiter: Ratelimit.slidingWindow(10, '10 s'),
|
||||
analytics: true,
|
||||
timeout: 1000,
|
||||
})
|
||||
: localRatelimit;
|
||||
|
||||
// Define which routes you want to rate limit
|
||||
export const config = {
|
||||
@ -17,7 +49,7 @@ export const config = {
|
||||
|
||||
export default async function middleware(request) {
|
||||
const ip = request.ip ?? '127.0.0.1';
|
||||
const { success, pending, limit, reset, remaining } = await ratelimit.limit(
|
||||
const { success, limit, remaining, reset } = await ratelimit.limit(
|
||||
`ratelimit_middleware_${ip}`
|
||||
);
|
||||
|
||||
@ -25,10 +57,15 @@ export default async function middleware(request) {
|
||||
return new NextResponse('Too Many Requests', {
|
||||
status: 429,
|
||||
headers: {
|
||||
'Retry-After': reset.toString(),
|
||||
'Retry-After': Math.ceil((reset - Date.now()) / 1000).toString(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return NextResponse.next();
|
||||
const response = NextResponse.next();
|
||||
response.headers.set('X-RateLimit-Limit', limit.toString());
|
||||
response.headers.set('X-RateLimit-Remaining', remaining.toString());
|
||||
response.headers.set('X-RateLimit-Reset', reset.toString());
|
||||
|
||||
return response;
|
||||
}
|
@ -1,11 +1,25 @@
|
||||
import axios from 'axios';
|
||||
import { URL } from 'url';
|
||||
|
||||
export default async function handler(req, res) {
|
||||
const { imageUrl } = req.query;
|
||||
|
||||
// Validate the imageUrl query parameter
|
||||
if (!imageUrl) {
|
||||
return res.status(400).json({ error: 'Missing imageUrl query parameter' });
|
||||
if (!imageUrl || typeof imageUrl !== 'string') {
|
||||
return res.status(400).json({ error: 'Invalid or missing imageUrl query parameter' });
|
||||
}
|
||||
|
||||
// Validate the URL
|
||||
let parsedUrl;
|
||||
try {
|
||||
parsedUrl = new URL(imageUrl);
|
||||
} catch (error) {
|
||||
return res.status(400).json({ error: 'Invalid URL' });
|
||||
}
|
||||
|
||||
// Only allow http and https protocols
|
||||
if (!['http:', 'https:'].includes(parsedUrl.protocol)) {
|
||||
return res.status(403).json({ error: 'Invalid protocol' });
|
||||
}
|
||||
|
||||
try {
|
||||
@ -13,9 +27,9 @@ export default async function handler(req, res) {
|
||||
method: 'GET',
|
||||
url: imageUrl,
|
||||
responseType: 'arraybuffer',
|
||||
timeout: 8000, // Set a timeout to prevent long-running requests
|
||||
// limit the size of the response to 100MB
|
||||
maxContentLength: 100 * 1024 * 1024,
|
||||
timeout: 5000, // Reduced timeout to 5 seconds
|
||||
maxContentLength: 10 * 1024 * 1024, // Reduced max content length to 10MB
|
||||
// ... rest of the axios config
|
||||
});
|
||||
|
||||
// Validate content type
|
||||
@ -34,6 +48,6 @@ export default async function handler(req, res) {
|
||||
res.send(response.data);
|
||||
} catch (error) {
|
||||
console.error('Image proxy error:', error);
|
||||
res.status(500).json({ error: 'Failed to fetch image' });
|
||||
res.status(error.response?.status || 500).json({ error: 'Failed to fetch image' });
|
||||
}
|
||||
}
|
||||
|
@ -3,20 +3,8 @@ import { getServerSession } from "next-auth/next"
|
||||
import { authOptions } from "@/pages/api/auth/[...nextauth].js"
|
||||
|
||||
export default async function handler(req, res) {
|
||||
if (req.method === 'GET') {
|
||||
try {
|
||||
const session = await getServerSession(req, res, authOptions)
|
||||
|
||||
if (!session) {
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
|
||||
const users = await getAllUsers();
|
||||
res.status(200).json(users);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
} else if (req.method === 'POST') {
|
||||
// const session = await getServerSession(req, res, authOptions);
|
||||
if (req.method === 'POST') {
|
||||
try {
|
||||
const user = await createUser(req.body);
|
||||
res.status(201).json(user);
|
||||
|
Loading…
x
Reference in New Issue
Block a user