我一直在寻找一个解决这个问题的方法,现在已经很累了。这是我在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变化的事情,但到目前为止还没有运气。
1条答案
按热度按时间wbrvyc0a1#
我同样的错误是第二个postgres进程仍然在后台。
查看这些选项:
我在这里找到的。