ASP.NET/React.JS - 使用 React-email 时无法获取 API/CORS

问题描述 投票:0回答:1

我有一个 React 应用程序在端口 44411 运行,react-email 在端口 3000 运行。

我看过一个关于如何设置反应电子邮件和重新发送的 YouTube 视频,但它立即不起作用。因此,经过多次摆弄后,我让它通过邮递员接收我的 API 请求,所以下一步是让它通过网站工作。我启用了 CORS(这也导致邮递员请求不再工作),并尝试通过网站发送它(从 44411 发送的 API 请求尝试在 3000 处获取),这会触发此错误:

Access to fetch at 'http://localhost:3000/api/email' from origin 'https://localhost:44411' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
ContactForm.js:30 
        
        
POST http://localhost:3000/api/email net::ERR_FAILED
handleSubmit @ ContactForm.js:30
callCallback @ react-dom.development.js:3706
invokeGuardedCallbackDev @ react-dom.development.js:3750
invokeGuardedCallback @ react-dom.development.js:3807
invokeGuardedCallbackAndCatchFirstError @ react-dom.development.js:3821
executeDispatch @ react-dom.development.js:7964
processDispatchQueueItemsInOrder @ react-dom.development.js:7990
processDispatchQueue @ react-dom.development.js:8001
dispatchEventsForPlugins @ react-dom.development.js:8010
(anonymous) @ react-dom.development.js:8170
batchedUpdates$1 @ react-dom.development.js:22559
batchedUpdates @ react-dom.development.js:3554
dispatchEventForPluginEventSystem @ react-dom.development.js:8169
dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay @ react-dom.development.js:5676
dispatchEvent @ react-dom.development.js:5670
dispatchDiscreteEvent @ react-dom.development.js:5647
Show 15 more frames
Show less
ContactForm.js:55 Error during fetch: TypeError: Failed to fetch
    at handleSubmit (ContactForm.js:30:1)
    at HTMLUnknownElement.callCallback (react-dom.development.js:3706:1)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:3750:1)
    at invokeGuardedCallback (react-dom.development.js:3807:1)
    at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:3821:1)
    at executeDispatch (react-dom.development.js:7964:1)
    at processDispatchQueueItemsInOrder (react-dom.development.js:7990:1)
    at processDispatchQueue (react-dom.development.js:8001:1)
    at dispatchEventsForPlugins (react-dom.development.js:8010:1)
    at react-dom.development.js:8170:1

当我启用 CORS 并通过邮递员发送请求时,我的电子邮件控制台中开始出现这些错误

 ⨯ TypeError: res.setHeader is not a function
    at applyHeaders (webpack-internal:///(rsc)/./node_modules/cors/lib/index.js:149:25)
    at applyHeaders (webpack-internal:///(rsc)/./node_modules/cors/lib/index.js:145:21)
    at applyHeaders (webpack-internal:///(rsc)/./node_modules/cors/lib/index.js:145:21)
    at cors (webpack-internal:///(rsc)/./node_modules/cors/lib/index.js:179:13)
    at eval (webpack-internal:///(rsc)/./node_modules/cors/lib/index.js:213:33)
    at originCallback (webpack-internal:///(rsc)/./node_modules/cors/lib/index.js:204:29)
    at eval (webpack-internal:///(rsc)/./node_modules/cors/lib/index.js:208:25)
    at optionsCallback (webpack-internal:///(rsc)/./node_modules/cors/lib/index.js:190:17)
    at corsMiddleware (webpack-internal:///(rsc)/./node_modules/cors/lib/index.js:194:13)
    at POST (webpack-internal:///(rsc)/./src/app/api/email/route.ts:25:5)
    at C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\compiled\next-server\app-route.runtime.dev.js:6:63257
    at C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\server\lib\trace\tracer.js:133:36
    at NoopContextManager.with (C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\compiled\@opentelemetry\api\index.js:1:7062)
    at ContextAPI.with (C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\compiled\@opentelemetry\api\index.js:1:518)
    at NoopTracer.startActiveSpan (C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\compiled\@opentelemetry\api\index.js:1:18093)
    at ProxyTracer.startActiveSpan (C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\compiled\@opentelemetry\api\index.js:1:18854)
    at C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\server\lib\trace\tracer.js:122:103
    at NoopContextManager.with (C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\compiled\@opentelemetry\api\index.js:1:7062)
    at ContextAPI.with (C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\compiled\@opentelemetry\api\index.js:1:518)
    at NextTracerImpl.trace (C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\server\lib\trace\tracer.js:122:28)
    at C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\compiled\next-server\app-route.runtime.dev.js:6:56774
    at AsyncLocalStorage.run (node:async_hooks:346:14)
    at Object.wrap (C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\compiled\next-server\app-route.runtime.dev.js:6:37057)
    at C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\compiled\next-server\app-route.runtime.dev.js:6:54547
    at AsyncLocalStorage.run (node:async_hooks:346:14)
    at Object.wrap (C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\compiled\next-server\app-route.runtime.dev.js:6:36306)
    at C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\compiled\next-server\app-route.runtime.dev.js:6:54509
    at AsyncLocalStorage.run (node:async_hooks:346:14)
    at eH.execute (C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\compiled\next-server\app-route.runtime.dev.js:6:53902)
    at eH.handle (C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\compiled\next-server\app-route.runtime.dev.js:6:64515)
    at doRender (C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\server\base-server.js:1330:60)
    at cacheEntry.responseCache.get.routeKind (C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\server\base-server.js:1552:34)
    at ResponseCache.get (C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\server\response-cache\index.js:49:26)
    at DevServer.renderToResponseWithComponentsImpl (C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\server\base-server.js:1460:53)
    at C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\server\base-server.js:990:121
    at NextTracerImpl.trace (C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\server\lib\trace\tracer.js:104:20)
    at DevServer.renderToResponseWithComponents (C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\server\base-server.js:990:41)
    at DevServer.renderPageComponent (C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\server\base-server.js:1843:35)
    at async DevServer.renderToResponseImpl (C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\server\base-server.js:1881:32)
    at async DevServer.pipeImpl (C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\server\base-server.js:909:25)
    at async NextNodeServer.handleCatchallRenderRequest (C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\server\next-server.js:266:17)
    at async DevServer.handleRequestImpl (C:\Users\renek\source\ReactNet\ReactNet\ClientApp\.react-email\node_modules\next\dist\server\base-server.js:805:17)

这是我的route.ts,位于ReactNet\ReactNet\ClientApp.react-email\src pp pi mail

import { NextApiRequest, NextApiResponse } from 'next';
import Cors from 'cors';
import { Resend } from 'resend';
import Email from '../../../../emails/ContactEmail';
import AdminEmail from '../../../../emails/Email';

// Create CORS middleware
const corsMiddleware = Cors({
    origin: 'http://localhost:44411', // Update this with your React app's URL
    methods: ['POST'],
});

const resend = new Resend(process.env.RESEND_API_KEY || "re_NpBHN9AX_4CzMejYZTq5YoZatkKikik2t");

// Export a function for the POST method
export async function POST(req: NextApiRequest, res: NextApiResponse) {
    // Apply the CORS middleware
    corsMiddleware(req, res, async () => {
        try {
            const { name, message, email, phone, workType } = req.body;

            await resend.emails.send({
                from: '[email protected]',
                to: email,
                subject: 'TedSite.nl - Bevestiging Contact Aanvraag',
                react: Email({
                    name,
                }),
            });

            await resend.emails.send({
                from: '[email protected]',
                to: "[email protected]",
                subject: 'TedSite.nl - Contact Aanvraag',
                react: AdminEmail({
                    name,
                    message,
                    email,
                    phone,
                    workType,
                }),
            });

            res.status(200).json({
                status: 'Ok',
            });
        } catch (e: unknown) {
            if (e instanceof Error) {
                console.log(`Failed to send email: ${e.message}`);
            }

            res.status(500).json({
                error: 'Internal server error.',
            });
        }
    });
}

这是我的handleSubmit 函数

    // Event handler for form submission
    const handleSubmit = async (e) => {
        e.preventDefault();

        const { name, email, phone, workType, message } = formData;
        console.log('Submitting data:', { name, email, phone, workType, message });

        try {
            const response = await fetch('http://localhost:3000/api/email', {
                method: 'POST',
                mode: "cors",  // Change the mode to CORS
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    name,
                    email,
                    phone,
                    workType,
                    message,
                }),
            });

            if (!response.ok) {
                // Handle non-successful response status
                console.error(`HTTP error! Status: ${response.status}`);
                // You can throw an error or handle it in another way
            } else {
                // Success
                const data = await response.json();
                console.log('Server response:', data);
                // Handle success if needed
            }
        } catch (error) {
            console.error('Error during fetch:', error);
            // Handle errors that occur during the fetch itself
        }
    };

我希望有人知道如何帮助我。

提前致谢!

鲍比

reactjs .net typescript next.js cors
1个回答
0
投票

经过三天的反复摆弄,我了解到:

  • 您必须在 next.config.js 中设置标头
  async headers() {
    return [
        {
            // matching all API routes
            source: "/api/:path*",
            headers: [
                { key: "Access-Control-Allow-Credentials", value: "true" },
                { key: "Access-Control-Allow-Origin", value: "https://localhost:44411" }, // replace this your actual origin
                { key: "Access-Control-Allow-Methods", value: "GET,DELETE,PATCH,POST,PUT" },
                { key: "Access-Control-Allow-Headers", value: "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version" },
            ]
        }
    ]
  },
  • 出于某种未知的原因,您应该将 Content-Type 设置为“application/x-www-form-urlencoded”,即使我们明确创建了一个 JSon 主体。
            const response = await fetch('http://localhost:3000/api/email', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                body: JSON.stringify(formData),
                credentials: 'include',
                mode: 'cors',
            });
  • 您必须为选项请求设置状态 200,并且您需要为客户端和服务器设置标头
    if (request.method === 'OPTIONS') {
        // Handling preflight request
        return NextResponse.json({ status: 200 });
    }

    const res = NextResponse.next()

    // add the CORS headers to the response
    res.headers.append('Access-Control-Allow-Credentials', "true")
    res.headers.append('Access-Control-Allow-Origin', 'https://localhost:44411') // replace this your actual origin
    res.headers.append('Access-Control-Allow-Methods', 'GET,PATCH,POST')
    res.headers.append(
        'Access-Control-Allow-Headers',
        'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version'
    )

我希望这些答案可以帮助将来的人。设置 Content-Type 最终对我起到了作用。

© www.soinside.com 2019 - 2024. All rights reserved.