处理登录错误消息时出错:http://localhost:3000/auth/login net::ERR_ABORTED 405(方法不允许>)

JS3*_*JS3 5 javascript typescript reactjs next.js supabase

我有这个/app/auth/login/route.ts

import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs'
import { cookies } from 'next/headers'
import { NextResponse } from 'next/server'

export async function POST(request: Request) {
  const requestUrl = new URL(request.url)
  const formData = await request.formData()
  const email = String(formData.get('email'))
  const password = String(formData.get('password'))
  const cookieStore = cookies()
  const supabase = createRouteHandlerClient({ cookies: () => cookieStore })

  await supabase.auth.signInWithPassword({
    email,
    password,
  })

  return NextResponse.redirect(requestUrl.origin, {
    status: 301,
  })
}
Run Code Online (Sandbox Code Playgroud)

以及/app/login/page.tsx上的页面

import Link from "next/link";

export default function LoginPage() {
  return (
    <>
      <form action="/auth/login" method="post">
      <label htmlFor="email">Email</label>
      <input name="email" />
      <label htmlFor="password">Password</label>
      <input type="password" name="password" />
      <button>Sign In</button>
    </form>

    <Link href="/reset-password">Reset Password</Link>
    </>
  )
}
Run Code Online (Sandbox Code Playgroud)

这些是我从文档中获得的代码。但是,我无法实现显示他们已成功登录的位置以及错误处理。

我遵循了下面的答案,但是,我收到了此错误:

POST http://localhost:3000/auth/login net::ERR_ABORTED 405(方法不允许)

路由.ts

import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs';
import { NextApiRequest, NextApiResponse } from 'next'; // Correct import for NextApiRequest and NextApiResponse
import { cookies } from 'next/headers';
import { NextResponse } from 'next/server'; // Correct import for NextResponse

export async function handler(
  req: NextApiRequest, // Correct the parameter list
  res: NextApiResponse // Correct the parameter list
) {
  const jsonBody = await req.body.json(); // Change 'request' to 'req'
  const email = jsonBody.email;
  const password = jsonBody.password;
  const cookieStore = cookies();
  const supabase = createRouteHandlerClient({ cookies: () => cookieStore });

  try {
    const { error } = await supabase.auth.signInWithPassword({
      email,
      password,
    });

    if (error) {
      return res.status(401).json({ message: 'Login failed. Please check your credentials.' });
    }
    return res.status(200).json({ message: 'Login successful' });
  } catch (error) {
    console.error('An error occurred:', error);
    return res.status(500).json({ message: 'An unexpected error occurred' });
  }
}
Run Code Online (Sandbox Code Playgroud)

api/登录/page.tsx

'use client'

import { useRouter } from 'next/navigation';
import { useState } from 'react';

export default function LoginPage() {
  const router = useRouter();
  const [error, setError] = useState<string>('');
  const [email, setEmail] = useState<string>('');
  const [password, setPassword] = useState<string>('');

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setError('');
  
    try {
      const response = await fetch('/auth/login', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ email, password }),
      });
  
      if (response.status === 200) {
        router.push('/');
      } else {
        if (response.headers.get('content-type')?.includes('application/json')) {
          // Check if the response contains JSON data.
          const result = await response.json();
          setError(result.message);
        } else {
          // Handle non-JSON responses (e.g., empty responses).
          setError('An unexpected error occurred.');
        }
      }
    } catch (error) {
      console.log(error, "error on the login page.tsx")
      console.error('An error occurred:', error);
      setError('An unexpected error occurred.');
    }
  }; 

  return (
    <>
      <form onSubmit={handleSubmit}>
        <label htmlFor="email">Email</label>
        <input
          type="email"
          name="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
        />
        <label htmlFor="password">Password</label>
        <input
          type="password"
          name="password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
        />
        <button type="submit">Sign In</button>
      </form>

      {error && <p>{error}</p>}
    </>
  );
}
Run Code Online (Sandbox Code Playgroud)

Von*_*onC 1

我看到您确实在 Next.js 中为端点实现了一个路由处理程序/auth/login,但在您的第一个代码片段中,您定义了一个名为 的函数POST。在第二个片段中,您已将此函数重命名为handler. 在两个代码片段中对此函数使用相同的名称会更清楚。
由于您收到 405,我认为服务器配置或路由处理程序未正确设置以处理对此端点的 POST 请求。

首先,确保路由处理程序的文件名与您尝试处理的 URL 路径匹配。例如,如果您的路由处理程序位于名为 的文件中route.ts,请确保它位于pages/api/auth/login/route.ts您的项目目录中。
将路由处理程序函数导出为路由处理程序文件中的默认导出。

// pages/api/auth/login/route.ts
export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  // rest of your code
}
Run Code Online (Sandbox Code Playgroud)

另外,请确保您的路由处理程序正确处理 POST 请求。您可以使用该req.method属性检查传入请求的 HTTP 方法并做出相应响应。

if (req.method === 'POST') {
  // Handle POST requests
  // rest of your code for handling POST requests
} else {
  // Respond with a 405 Method Not Allowed if the request is not a POST request
  res.status(405).send('Method Not Allowed');
}
Run Code Online (Sandbox Code Playgroud)

我假设您使用的是 NextJS 13.4+

根据这些建议,代码将是:

路由处理程序 ( route.ts):

// pages/api/auth/login/route.ts

import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs';
import { cookies } from 'next/headers';
import { NextResponse } from 'next/server';

export async function POST(request: Request) {
  // Parse JSON body from the request
  const jsonBody = await request.json();
  const { email, password } = jsonBody;

  const cookieStore = cookies();
  const supabase = createRouteHandlerClient({ cookies: () => cookieStore });

  try {
    const { error } = await supabase.auth.signInWithPassword({
      email,
      password,
    });

    if (error) {
      // Return a JSON response with a 401 status code for unauthorized
      return NextResponse.json({ message: 'Login failed. Please check your credentials.' }, { status: 401 });
    }
    // Return a JSON response indicating success
    return NextResponse.json({ message: 'Login successful' });
  } catch (error) {
    console.error('An error occurred:', error);
    // Return a JSON response with a 500 status code for server error
    return NextResponse.json({ message: 'An unexpected error occurred' }, { status: 500 });
  }
}
Run Code Online (Sandbox Code Playgroud)

登录页面 ( page.tsx):

// pages/app/login/page.tsx

import { useRouter } from 'next/router';
import { useState } from 'react';

export default function LoginPage() {
  const router = useRouter();
  const [error, setError] = useState<string>('');
  const [email, setEmail] = useState<string>('');
  const [password, setPassword] = useState<string>('');

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setError('');

    try {
      const response = await fetch('/api/auth/login/route', {  // Corrected the URL to match the route handler file location
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ email, password }),
      });

      if (response.status === 200) {
        router.push('/');
      } else {
        if (response.headers.get('content-type')?.includes('application/json')) {
          const result = await response.json();
          setError(result.message);
        } else {
          setError('An unexpected error occurred.');
        }
      }
    } catch (error) {
      console.error('An error occurred:', error);
      setError('An unexpected error occurred.');
    }
  }; 

  return (
    <>
      <form onSubmit={handleSubmit}>
        <label htmlFor="email">Email</label>
        <input
          type="email"
          name="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
        />
        <label htmlFor="password">Password</label>
        <input
          type="password"
          name="password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
        />
        <button type="submit">Sign In</button>
      </form>

      {error && <p>{error}</p>}
    </>
  );
}
Run Code Online (Sandbox Code Playgroud)

在路由处理程序 ( route.ts) 中,我添加了一个检查以确保请求方法是使用 POST 的if (req.method !== 'POST')。
在登录页面 ( page.tsx) 中,我修复了函数中的 URLfetch以匹配路由处理程序文件 ( ) 的位置/api/auth/login/route。

全部流程:

 +-----------------------+   User Input   +------------------------+
 |                       | -------------> |                        |
 | Client:               |   (email,      | Server:                |
 | pages/app/login/      |   password)    | pages/api/auth/login/  |
 | page.tsx              |                | route.ts               |
 |                       |                |                        |
 | 1. Render Login Page  |                |                        |
 |                       |                |                        |
 | 2. User submits       |                |                        |
 |    form               |                |                        |
 |                       |                |                        |
 | 3. handleSubmit       |   POST Req.    | 4. POST function       |
 |    triggers fetch     | -------------> |    executes:           |
 |    request to server  |                |                        |
 |                       |                |    - Parse request     |
 |                       |                |    - Authenticate      |
 |                       |                |      via Supabase      |
 |                       |                |    - Prepare response  |
 |                       |                |                        |
 +-----------------------+   Response    +------------------------+
                          <-------------   
    (success/error msg)  |                | (success/error msg)
                         |                |
 +-----------------------+                |
 |                       |                |
 | Client:               |                |
 | pages/app/login/      |                |
 | page.tsx              |                |
 |                       |                |
 | 5. Process response:  |                |
 |    - Success: Redirect|                |
 |      to homepage      |                |
 |    - Failure: Display |                |
 |      error message    |                |
 |                       |                |
 +-----------------------+                |
Run Code Online (Sandbox Code Playgroud)