Skip to content

Commit a4bfc44

Browse files
authored
debug login feature (#141)
1 parent 0742da8 commit a4bfc44

File tree

8 files changed

+483
-66
lines changed

8 files changed

+483
-66
lines changed

Diff for: app/api/auth/[...nextauth]/route.ts

+116-22
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { handlers } from "@/app/auth"
22
import { NextResponse } from 'next/server'
33
import { NextRequest } from 'next/server'
4-
import { getProxyConfig } from "@/proxy-config"
4+
import { getProxyConfig, disableProxy } from "@/proxy-config"
55
import { HttpsProxyAgent } from "https-proxy-agent"
66

77
const TIMEOUT_DURATION = 60000;
@@ -12,24 +12,63 @@ interface ExtendedRequestInit extends RequestInit {
1212
timeout?: number;
1313
}
1414

15-
// 定义超时 Promise 的类型
16-
type TimeoutPromise = Promise<never>
17-
1815
export async function GET(request: NextRequest): Promise<Response> {
1916
try {
2017
const { isEnabled, httpsAgent } = getProxyConfig();
18+
const nextauthUrl = process.env.NEXTAUTH_URL || '';
19+
20+
// 检查是否是回调请求
21+
if (request.url.includes('/api/auth/callback')) {
22+
console.log('Callback request detected:', request.url);
23+
24+
// 处理请求
25+
const response = await handlers.GET(request);
26+
27+
// 如果是成功的回调(通常是 302 重定向)
28+
if (response instanceof Response && response.status === 302) {
29+
const location = response.headers.get('location');
30+
31+
// 检查重定向 URL 是否匹配 NEXTAUTH_URL
32+
if (location && (
33+
location === nextauthUrl ||
34+
location.startsWith(nextauthUrl + '/') ||
35+
location === '/' ||
36+
!location.includes('/api/auth')
37+
)) {
38+
console.log('Redirecting to app URL, disabling proxy:', location);
39+
// 在响应发送后禁用代理
40+
setTimeout(() => {
41+
disableProxy();
42+
}, 100);
43+
}
44+
}
45+
46+
return response instanceof Response ? response : NextResponse.json(response);
47+
}
2148

22-
// 只在认证请求时使用代理
49+
// 处理其他认证请求
2350
if (isEnabled && request.url.includes('/api/auth')) {
24-
console.log('originalFetch!!!!!!!!!!:', global.fetch);
51+
console.log('Auth request with proxy:', request.url);
2552
const originalFetch = global.fetch;
53+
2654
global.fetch = async (input: RequestInfo | URL, init?: RequestInit) => {
27-
const extendedInit: ExtendedRequestInit = {
28-
...init,
29-
agent: httpsAgent,
30-
timeout: TIMEOUT_DURATION,
31-
};
32-
return originalFetch(input, extendedInit);
55+
const inputStr = typeof input === 'string' ? input : input.toString();
56+
57+
// 只对 GitHub OAuth 相关 URL 使用代理
58+
if (inputStr.includes('github.com/login/oauth') ||
59+
inputStr.includes('api.github.com/user')) {
60+
61+
console.log('Using proxy for fetch request:', inputStr);
62+
const extendedInit: ExtendedRequestInit = {
63+
...init,
64+
agent: httpsAgent,
65+
timeout: TIMEOUT_DURATION,
66+
};
67+
return originalFetch(input, extendedInit);
68+
} else {
69+
// 其他请求不使用代理
70+
return originalFetch(input, init);
71+
}
3372
};
3473

3574
try {
@@ -40,7 +79,7 @@ export async function GET(request: NextRequest): Promise<Response> {
4079
global.fetch = originalFetch;
4180
}
4281
} else {
43-
// 非认证请求使用普通 fetch
82+
// 非认证请求或代理未启用
4483
const response = await handlers.GET(request);
4584
return response instanceof Response ? response : NextResponse.json(response);
4685
}
@@ -59,17 +98,72 @@ export async function GET(request: NextRequest): Promise<Response> {
5998

6099
export async function POST(request: NextRequest): Promise<Response> {
61100
try {
62-
const { isEnabled } = getProxyConfig();
63-
64-
if (isEnabled) {
65-
// 使用超时机制
66-
const timeoutPromise: TimeoutPromise = new Promise((_, reject) =>
67-
setTimeout(() => reject(new Error('Request timeout')), TIMEOUT_DURATION)
68-
);
69-
const response = await Promise.race([handlers.POST(request), timeoutPromise]);
101+
const { isEnabled, httpsAgent } = getProxyConfig();
102+
const nextauthUrl = process.env.NEXTAUTH_URL || '';
103+
104+
// 检查是否是回调请求
105+
if (request.url.includes('/api/auth/callback')) {
106+
console.log('Callback POST request detected:', request.url);
107+
108+
// 处理请求
109+
const response = await handlers.POST(request);
110+
111+
// 如果是成功的回调(通常是 302 重定向)
112+
if (response instanceof Response && response.status === 302) {
113+
const location = response.headers.get('location');
114+
115+
// 检查重定向 URL 是否匹配 NEXTAUTH_URL
116+
if (location && (
117+
location === nextauthUrl ||
118+
location.startsWith(nextauthUrl + '/') ||
119+
location === '/' ||
120+
!location.includes('/api/auth')
121+
)) {
122+
console.log('POST: Redirecting to app URL, disabling proxy:', location);
123+
// 在响应发送后禁用代理
124+
setTimeout(() => {
125+
disableProxy();
126+
}, 100);
127+
}
128+
}
129+
70130
return response instanceof Response ? response : NextResponse.json(response);
131+
}
132+
133+
// 处理其他认证请求
134+
if (isEnabled && request.url.includes('/api/auth')) {
135+
console.log('Auth POST request with proxy:', request.url);
136+
const originalFetch = global.fetch;
137+
138+
global.fetch = async (input: RequestInfo | URL, init?: RequestInit) => {
139+
const inputStr = typeof input === 'string' ? input : input.toString();
140+
141+
// 只对 GitHub OAuth 相关 URL 使用代理
142+
if (inputStr.includes('github.com/login/oauth') ||
143+
inputStr.includes('api.github.com/user')) {
144+
145+
console.log('Using proxy for POST fetch request:', inputStr);
146+
const extendedInit: ExtendedRequestInit = {
147+
...init,
148+
agent: httpsAgent,
149+
timeout: TIMEOUT_DURATION,
150+
};
151+
return originalFetch(input, extendedInit);
152+
} else {
153+
// 其他请求不使用代理
154+
return originalFetch(input, init);
155+
}
156+
};
157+
158+
try {
159+
const response = await handlers.POST(request);
160+
return response instanceof Response ? response : NextResponse.json(response);
161+
} finally {
162+
// 请求完成后恢复原始的 fetch
163+
global.fetch = originalFetch;
164+
}
71165
} else {
72-
// 不使用超时机制
166+
// 非认证请求或代理未启用
73167
const response = await handlers.POST(request);
74168
return response instanceof Response ? response : NextResponse.json(response);
75169
}

Diff for: app/api/auth/enable-proxy/route.tsx

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { NextResponse } from 'next/server';
2+
import { enableProxy } from "@/proxy-config";
3+
4+
export async function POST() {
5+
try {
6+
const config = enableProxy();
7+
return NextResponse.json({
8+
success: true,
9+
proxyEnabled: config.isEnabled
10+
});
11+
} catch (error) {
12+
return NextResponse.json({
13+
success: false,
14+
error: error instanceof Error ? error.message : 'Unknown error'
15+
}, { status: 500 });
16+
}
17+
}

Diff for: app/api/proxy-image/route.tsx

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { NextRequest, NextResponse } from 'next/server';
2+
import { getProxyConfig } from '@/proxy-config';
3+
4+
export async function GET(request: NextRequest) {
5+
try {
6+
const url = request.nextUrl.searchParams.get('url');
7+
8+
if (!url) {
9+
return new NextResponse('Missing URL parameter', { status: 400 });
10+
}
11+
12+
const { isEnabled, httpsAgent } = getProxyConfig();
13+
14+
const fetchOptions: RequestInit = {};
15+
if (isEnabled && url.includes('githubusercontent.com')) {
16+
// 使用 @ts-expect-error 代替 @ts-ignore
17+
// @ts-expect-error - agent 属性在浏览器端 RequestInit 类型中不存在
18+
fetchOptions.agent = httpsAgent;
19+
}
20+
21+
const response = await fetch(url, fetchOptions);
22+
23+
if (!response.ok) {
24+
return new NextResponse('Failed to fetch image', { status: response.status });
25+
}
26+
27+
const buffer = await response.arrayBuffer();
28+
const headers = new Headers();
29+
headers.set('Content-Type', response.headers.get('Content-Type') || 'image/jpeg');
30+
headers.set('Cache-Control', 'public, max-age=86400');
31+
32+
return new NextResponse(buffer, {
33+
status: 200,
34+
headers
35+
});
36+
} catch (error) {
37+
console.error('Error proxying image:', error);
38+
return new NextResponse('Error fetching image', { status: 500 });
39+
}
40+
}

Diff for: app/auth.ts

+17-12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import NextAuth from "next-auth"
22
import GitHub from "next-auth/providers/github"
3-
// import { getProxyConfig } from "@/proxy-config"
3+
import { setupGlobalFetch } from "@/proxy-config"
4+
5+
// 设置全局 fetch 拦截器(但不启用代理)
6+
setupGlobalFetch();
47

58
// 打印环境变量(开发环境调试用)
69
console.log('Environment Config:', {
@@ -31,32 +34,34 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
3134
debug: true,
3235
callbacks: {
3336
async signIn({ user, account, profile, email, credentials }) {
34-
console.log('Sign in attempt:', { user, account, profile, email, credentials });
35-
37+
console.log('signIn!!!!!!!!!!:', user, account, profile, email, credentials);
38+
console.log('Sign in callback executed');
3639
return true;
3740
},
3841
async redirect({ url, baseUrl }) {
39-
console.log('Redirect:', { url, baseUrl });
42+
43+
console.log('redirect!!!!!!!!!!:', url, baseUrl);
4044
return baseUrl;
4145
},
4246
async session({ session, user, token }) {
43-
console.log('Session:', { session, user, token });
47+
console.log('session!!!!!!!!!!:', session, user, token);
4448
return session;
4549
},
4650
async jwt({ token, user, account, profile }) {
47-
console.log('JWT:', { token, user, account, profile });
51+
console.log('jwt!!!!!!!!!!:', token, user, account, profile);
4852
return token;
4953
}
5054
},
5155
events: {
52-
async signIn(message) { console.log('signIn:', message) },
53-
async signOut(message) { console.log('signOut:', message) },
56+
async signIn(message) {
57+
console.log('signIn event:', message);
58+
},
59+
async signOut(message) {
60+
console.log('signOut:', message);
61+
},
5462
},
5563
pages: {
5664
signIn: '/auth/signin',
5765
error: '/auth/error',
5866
}
59-
})
60-
61-
62-
67+
})

Diff for: components/sign-in.tsx

+42-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { useEffect } from 'react';
44
import { signIn, signOut, useSession } from 'next-auth/react';
5-
import Image from 'next/image';
5+
// import Image from 'next/image';
66
import Link from 'next/link';
77
import { Dropdown } from 'antd';
88
import type { MenuProps } from 'antd';
@@ -32,6 +32,36 @@ export default function SignInButton() {
3232
}
3333
}, [session]); // 依赖于 session
3434

35+
// 处理 GitHub 登录
36+
const handleGitHubSignIn = async () => {
37+
try {
38+
// 先启用代理
39+
await fetch('/api/auth/enable-proxy', {
40+
method: 'POST',
41+
headers: {
42+
'Content-Type': 'application/json',
43+
},
44+
});
45+
46+
console.log('已启用代理用于 GitHub 登录');
47+
48+
// 然后进行 GitHub 登录
49+
await signIn("github");
50+
} catch (error) {
51+
console.error('登录过程中出错:', error);
52+
}
53+
};
54+
55+
// 在组件内部添加一个函数来处理图片 URL
56+
// const getProxiedImageUrl = (imageUrl: string) => {
57+
// if (!imageUrl) return '';
58+
// // 检查是否是 GitHub 头像
59+
// if (imageUrl.includes('githubusercontent.com')) {
60+
// return `/api/proxy-image?url=${encodeURIComponent(imageUrl)}`;
61+
// }
62+
// return imageUrl;
63+
// };
64+
3565
if (status === 'loading') {
3666
return (
3767
<button className="bg-gray-200 text-gray-400 px-4 py-2 rounded-md cursor-not-allowed">
@@ -56,8 +86,17 @@ export default function SignInButton() {
5686
<Dropdown menu={{ items }} placement="bottomRight">
5787
<div className="flex items-center gap-2 cursor-pointer">
5888
<div className="flex items-center gap-2 px-2 py-1 rounded-full bg-gray-100 hover:bg-gray-200 transition-colors duration-200">
59-
{session.user?.image && (
89+
{/* {session.user?.image && (
6090
<Image
91+
src={getProxiedImageUrl(session.user.image)}
92+
alt={session.user.name || 'User avatar'}
93+
width={32}
94+
height={32}
95+
className="rounded-full"
96+
/>
97+
)} */}
98+
{session.user?.image && (
99+
<img
61100
src={session.user.image}
62101
alt={session.user.name || 'User avatar'}
63102
width={32}
@@ -74,10 +113,7 @@ export default function SignInButton() {
74113

75114
return (
76115
<button
77-
onClick={async () => {
78-
79-
await signIn("github")
80-
}}
116+
onClick={handleGitHubSignIn}
81117
className="flex items-center gap-2 px-4 py-2 bg-gray-800 hover:bg-gray-700 text-white rounded-md transition-colors duration-200"
82118
>
83119
<svg

0 commit comments

Comments
 (0)