我在 Nodejs 中编写了一个 API,它有助于使用 Mysql 数据库重置密码。它在 Postman 中工作正常。我在 Expo IOS App 中调用了这个 API。但是我收到网络请求失败错误。下面是Node js程序:
应用程序.js:
var express = require('express');
var path = require('path');
var connection = require('./database.js');
var nodemailer = require('nodemailer');
const bcrypt = require("bcryptjs")
var randtoken = require('rand-token');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var flash = require('express-flash');
var session = require('express-session');
var bodyParser = require('body-parser');
const createError = require('http-errors');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var app = express();
var connection = require('./database.js');
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: false}))
//send email
function sendEmail(email, token) {
var email = email;
var token = token;
var mail = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'c***********@gmail.com', // Your email id
pass: '**********' // Your password
}
});
var mailOptions = {
from: 'poornima@abccompany.com',
to: email,
subject: 'Reset Password Link - ABCCompany.com',
html: '<p>You requested for reset password, kindly use this <a
href="http://localhost:4000/reset-password?token=' + token + '">link</a> to reset
your password</p>'
};
mail.sendMail(mailOptions, function(error, info) {
if (error) {
console.log(1)
} else {
console.log(0)
}
});
}
app.post('/reset-password-email', function(req, res, next) {
var email = req.body.email;
console.log('email from api '+email);
connection.query('SELECT * FROM JTGDB.UserInfo WHERE email ="' + email + '"',
function(err, result) {
if (err) throw err;
var type = ''
var msg = ''
console.log(result[0]);
if (result[0].Email.length > 0) {
var token = randtoken.generate(20);
var sent = sendEmail(email, token);
if (sent != '0') {
var data = {
token: token
}
connection.query('UPDATE JTGDB.UserInfo SET ? WHERE email ="' + email + '"', data,
function(err, result) {
if(err) throw err
})
type = 'success';
msg = 'The reset password link has been sent to your email address';
} else {
type = 'error';
msg = 'Something goes to wrong. Please try again';
}
} else {
console.log('2');
type = 'error';
msg = 'The Email is not registered with us';
}
res.redirect('/');
});
})
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({
secret: '123458cat',
resave: false,
saveUninitialized: true,
cookie: { maxAge: 60000 }
}))
app.use(flash());
app.use('/', usersRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
app.listen(4000, function () {
console.log('Node app is running on port 4000');
});
module.exports = app;
下面是 IOS App ForgetPassword Screen 页面:
ForgetPasswordScreen.js:
import React, { Component, Fragment, useState } from "react";
import { View, Text,SafeAreaView, Image, StyleSheet } from "react-native";
import { Formik } from "formik";
import * as Yup from "yup";
import FormInput from "../../components/UI/FormInput";
import FormButton from "../../components/UI/FormButton";
import ErrorMessage from "../../components/UI/ErrorMessage";
import * as authActions from '../../store/actions/auth';
import {useDispatch} from "react-redux";
import Toast from 'react-native-root-toast';
const validationSchema = Yup.object().shape({
email: Yup.string()
.label("Email")
.email("Enter a valid email")
.required("Please enter a registered email"),
});
const ForgotPasswordScreen = props => {
const [isLoading,setIsLoading] = React.useState(false);
const [error, setError] = React.useState('');
const dispatch = useDispatch();
const handlePasswordReset = async (values, actions) => {
const { email } = values;
console.log('email is '+email);
let action
action = authActions.resetpassword(
email
);
setError(null);
setIsLoading(true);
try{
await dispatch(action);
props.navigation.navigate("Login");
} catch (error) {
actions.setFieldError("general", error.message);
}
};
return (
<SafeAreaView>
<View style={styles.emailiconview}>
<Image source={require('../../assets/reset_email.png')} />
</View>
<View style ={styles.instrview1}>
<Text>
Please enter your registered email address below to
</Text>
</View>
<View style={styles.instrview2}>
<Text>receive password reset instruction</Text>
</View>
<View style={styles.emailinputview}>
<Formik
initialValues={{ email: "" }}
onSubmit={(values, actions) => {
handlePasswordReset(values, actions);
}}
validationSchema={validationSchema}
>
{({
handleChange,
values,
handleSubmit,
errors,
isValid,
touched,
handleBlur,
isSubmitting,
}) => (
<Fragment>
<FormInput
name="email"
value={values.email}
onChangeText={handleChange("email")}
placeholder="Enter email"
autoCapitalize="none"
iconName="ios-mail"
iconColor="blue"
onBlur={handleBlur("email")}
/>
<ErrorMessage errorValue={touched.email && errors.email} />
<View style={styles.buttonContainer}>
<FormButton
buttonType="outline"
onPress={handleSubmit}
title="Send Email"
buttonColor="blue"
disabled={!isValid || isSubmitting}
/>
</View>
<ErrorMessage errorValue={errors.general} />
</Fragment>
)}
</Formik>
</View>
</SafeAreaView>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
marginTop: 150,
},
text: {
color: "#333",
fontSize: 24,
marginLeft: 25,
},
buttonContainer: {
margin: 25,
},
emailiconview:{
justifyContent:'center',
alignItems:'center',
top:"30%"
},
instrview1:{
top:'40%',
justifyContent:'center',
alignSelf:'center'
}, instrview2:{
top:'45%',
justifyContent:'center',
alignSelf:'center'
},
emailinputview:{
top:'50%'
}
});
export default ForgotPasswordScreen;
下面是我获取 API 的商店身份验证:
auth.js:
import Device from '../../model/Device';
import AsyncStorage from '@react-native-async-storage/async-storage'
export const FORGOTPASSWORD = 'FORGOTPASSWORD';
export const resetpassword=(email) =>{
console.log(email);
return async dispatch =>{
const response = await fetch(
'http://my_IPV4_Address:4000/reset-password-email',
{
method: 'POST',
header: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: email
})
}
);
const resData = await response.text();
console.log(resData);
dispatch({type:FORGOTPASSWORD});
};
}
运行此程序后,我在 Expo 中收到以下错误:
网络请求失败
它正在接收电子邮件,但没有点击 api。
email is cpoornima.1987@gmail.com
Email id to API cpoornima.1987@gmail.com
我在 NodeJs 中遇到以下错误:
email from api undefined
undefined
我已经添加了
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
到 Info.plist。我只是在检查附加到 Expo App 的 IOS 模拟器。如何度过这个难关?