postgresql Heroku上的Typescript应用程序和API- CORS失败,NS_ERROR_DOM_BAD_URI

cx6n0qe3  于 2024-01-07  发布在  PostgreSQL
关注(0)|答案(1)|浏览(138)

我一直在寻找一个解决这个问题的方法,现在已经很累了。这是我在heroku上的设置:

申请

  • 使用Heroku提供的typescript运行应用程序。为了登录并与我的API连接,此代码用于我的布局屏幕:

LoginScreen.js

import useMutation from "../../../../core/hooks/useMutation";
import logo from "../../../../img/logo.svg";
import { useAuthContext } from "../AuthProvider";
import useForm from "../../../../core/hooks/useForm";
import * as yup from "yup";
import Label from "../../../Design/Form/Label";
import Input from "../../../Design/Form/Input";
import "../login/styles/auth.css";
import errorHandler from "../../../../core/helpers/errorHandler";

// validation schema
const schema = yup.object().shape({
  email: yup.string().email().required(),
  password: yup.string().required(),
});

const defaultData = {
  email: "",
  password: "",
};

const LoginScreen = () => {
  const { login } = useAuthContext();
  const { isLoading, error, mutate } = useMutation();
  const { values, errors, handleChange, handleSubmit } = useForm(schema, {
    ...defaultData,
  });

  // handle submit
  const handleData = (values) => {
    mutate(`${process.env.REACT_APP_API_URL}/login`, {
      method: "POST",
      data: values,
      onSuccess: (data) => {
        login(data);
      },
    });
  };

  return (
    <div id="auth">
      <div id="auth-login">
        <img src={logo} alt="logo" />
        <h2>Aanmelden:</h2>
        <form
          className="auth-form"
          onSubmit={handleSubmit(handleData)}
          noValidate
        >
          {error && <div className="error">{errorHandler(error)}</div>}
          <div className="form-item">
            <Label htmlFor="email" className="auth-label">
              Gebruikersnaam of e-mail:
            </Label>
            <Input
              type="email"
              name="email"
              className="auth-input"
              onChange={handleChange}
              value={values.email}
              error={errors.email}
              disabled={isLoading}
            />
          </div>
          <div className="form-item">
            <Label htmlFor="password" className="auth-label">
              Wachtwoord:
            </Label>
            <Input
              className="auth-input"
              type="password"
              name="password"
              onChange={handleChange}
              value={values.password}
              error={errors.password}
              disabled={isLoading}
            />
          </div>
          <button>Inloggen</button>
        </form>
      </div>
    </div>
  );
};

export default LoginScreen;

字符串

  • 使用API进行身份验证需要执行以下代码:

useAuthApi.js

import { useCallback } from "react";
import { useAuthContext } from "../../components/App/Auth/AuthProvider";
import ApiError from "../error/ApiError";
import AppError from "../error/AppError";
import { handleErrors } from "../helpers/api";

const useAuthApi = () => {
  const { auth, logout } = useAuthContext();

  const authFetch = useCallback(
    (url, config = {}) => {
      // add authorization header
      if (auth && auth.token) {
        config.headers = {
          ...(config.headers || {}),
          Authorization: `Bearer ${auth.token}`,
        };
      }

      return fetch(url, config)
        .then(handleErrors)
        .catch((error) => {
          if (error instanceof ApiError) {
            if (error.isUnauthorized()) {
              logout();
            }
            throw error;
          } else {
            throw new AppError(error);
          }
        });
    },
    [logout, auth]
  );

  return {
    authFetch,
  };
};

export default useAuthApi;

  • 在heroku上我使用相同的变量,但是我把它们放在我的配置变量中

.env

REACT_APP_URL=http://localhost
REACT_APP_API_URL=http://localhost:3002


我用Heroku给我的正确URL更改了localhost。

API

  • 在端口3002上运行我的类型脚本API。我对这个端口有疑问,因为如果我在Heroku中部署,我会得到以下输出:App has started on http://localhost:54400

index.ts

import "dotenv/config";

import * as express from "express";
import { AppDataSource } from "./database/DatabaseSource";
import { registerErrorHandler, registerMiddleware } from "./middleware";
import { registerRoutes } from "./routes";

// initialize database
AppDataSource.initialize()
  .then(async () => {
    const app = express();

    // middleware
    registerMiddleware(app);

    // routes
    registerRoutes(app);

    // error handler
    registerErrorHandler(app);

    // start express server
    app.listen(process.env.PORT || 3002);

    if (process.env.ENV === "production") {
      console.log(`App has started on http://localhost:${process.env.PORT}`);
    }
  })
  .catch((error) => {
    console.log(error);
  });

const closeApp = () => {
  // properly close database
  AppDataSource.destroy();
  // finish Node process
  process.exit();
};

process.on("SIGINT", () => closeApp());
process.on("SIGTERM", () => closeApp());

  • 但是这些设置也是在Heroku本身的配置变量中配置的

.env

PORT=3002
ENV=production
DB_HOST=heroku-database
DB_PORT=5432
DB_USER=heroku-user
DB_PASSWORD=heroku-password
DB_NAME=heroku-name
DATABASE_URL=heroku-url
JWT_SECRET=sometoken
JWT_EXPIRES_IN_HOURS=24
PGSSLMODE=no-verify
PORT=3002
PROCFILE=./Procfile

  • 使用CORS中间件,我已经尝试改变很多次了。现在,这是我的中间件代码:

index.ts

import * as cors from "cors";
import * as bodyParser from "body-parser";
import * as helmet from "helmet";
import { QueryFailedError, TypeORMError } from "typeorm";
import BaseError from "../errors/BaseError";
import { Application, NextFunction, Request, Response, Router } from "express";

const registerMiddleware = (app: Router) => {
  // use CORS middleware
  // add "allow all" cors
  if (process.env.ENV === "PRODUCTION" || process.env.ENV === "production") {
    const corsOptions = {
      origin: '*',
      methods: ['GET','POST','DELETE','UPDATE','PUT','PATCH', 'OPTIONS'],
      optionsSuccessStatus: 200,
      credentials: true,
    };
    // allows CORS online
    app.use(cors(corsOptions));
  } else {
    app.use(cors());
  }
  // JSON is going to be the default format
  app.use(bodyParser.json());
  app.use(
    bodyParser.urlencoded({
      extended: true,
    })
  );
  // blocks the browser from trying to guess the MIME type
  app.use(helmet.noSniff());
  // Hides the X-Powered-By header
  app.use(helmet.hidePoweredBy());
  // Adds a filter to prevent XSS attacks
  app.use(helmet.xssFilter());
};

// Error handler
const registerErrorHandler = (app: Application) => {
  // Default error handler
  app.use(function (
    err: Error,
    req: Request,
    res: Response,
    next: NextFunction
  ) {
    let message: string;
    let statusCode: number;
    let errors = {};

    if (err instanceof QueryFailedError) {
      message = err.driverError.detail;
      statusCode = 400;
    } else if (err instanceof TypeORMError) {
      message = err.message;
      statusCode = 500;
    } else if (err instanceof BaseError) {
      message = err.message;
      statusCode = err.statusCode;
      errors = err.errors;
    } else {
      message = String(err);
      statusCode = 500;
    }
    res.status(statusCode).json({
      message,
      statusCode,
      errors,
    });
  });
};

export { registerMiddleware, registerErrorHandler };

  • 最后创建数据库并设置dbsource。

databaseSource.ts

import "reflect-metadata";
import { DataSource } from "typeorm";
import all different entities

// config for the database
export const AppDataSource = new DataSource({
  type: "postgres",
  host: process.env.DB_HOST,
  port: parseInt(process.env.DB_PORT),
  username: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME,
  synchronize: true,
  logging: false,
  entities: [
    all tables needed
  ],
  migrations: [],
  subscribers: [],
  // ssl:
  //   process.env.ENV === "PRODUCTION"
  //     ? {
  //         rejectUnauthorized: false,
  //       }
  //     : false,
});


我确实把ssl-part放在注解中,因为否则我会得到一个FATAL:no pg_hba.conf entry for host. no encryption错误

错误处理尝试登录时,出现以下错误:

  • 我的代码卡在useAuthApi.js文件上以返回我的获取。我想这是因为与我的postgres(也由heroku托管)的连接失败?通过此获取,浏览器返回CORS失败错误。当使用科塞扩展尝试相同的代码时,没有任何变化。
  • 下一个错误是在POST方法中。我最终得到了一个NS_ERROR_BAD_DOM_URI错误,导致登录失败,没有任何其他错误代码。

如果我同时运行API和APP,本地似乎没有问题.有人能指导我在正确的方向吗?已经尝试了许多关于CORS变化的事情,但到目前为止还没有运气。

wbrvyc0a

wbrvyc0a1#

我同样的错误是第二个postgres进程仍然在后台。
查看这些选项:

  • 选项1:在Windows上停止PostgreSQL服务
  • 选项2(使用WSL):从Windows完全卸载Protgres 12并在WSL上安装postgresql-client(sudo apt install postgresql-client-common postgresql-client libpq-dev)
  • 选项3:更改Docker容器的端口

我在这里找到的。

相关问题