node.js - 网络请求因本机博览会而失败
问题描述
我正在尝试在 react native expo 中编写应用程序的登录名。代码或多或少已完成,但每次我测试它时,我都会收到错误通知:
Network request failed
at node_modules\whatwg-fetch\dist\fetch.umd.js:535:17 in setTimeout$argument_0
at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:130:14 in _callTimer
at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:383:16 in callTimers
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:416:4 in __callFunction
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:109:6 in __guard$argument_0
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:364:10 in __guard
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:108:4 in callFunctionReturnFlushedQueue
我试图而不是获取本地主机来获取我的电脑的 IP,以便我正在测试的智能手机可以向他请求。我在有和没有 VPN 和防火墙的情况下都做到了。
我的前端代码是:
import React, { useState } from 'react';
import { View, Text, StyleSheet, TouchableOpacity, TextInput, Platform } from 'react-native';
const API_URL = Platform.OS === 'ios' ? 'http://192.168.178.73:3000' : 'http://10.0.2.2:3000';
const AuthScreen = () => {
const [email, setEmail] = useState('');
const [name, setName] = useState('');
const [password, setPassword] = useState('');
const [isError, setIsError] = useState(false);
const [message, setMessage] = useState('');
const [isLogin, setIsLogin] = useState(true);
const onChangeHandler = () => {
setIsLogin(!isLogin);
setMessage('');
};
const onLoggedIn = token => {
fetch(`${API_URL}/private`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
},
})
.then(async res => {
try {
const jsonRes = await res.json();
if (res.status === 200) {
setMessage(jsonRes.message);
}
} catch (err) {
console.log(err);
};
})
.catch(err => {
console.log(err);
});
}
const onSubmitHandler = () => {
const payload = {
email,
name,
password,
};
fetch(`${API_URL}/${isLogin ? 'login' : 'signup'}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
})
.then(async res => {
try {
const jsonRes = await res.json();
if (res.status !== 200) {
setIsError(true);
setMessage(jsonRes.message);
} else {
onLoggedIn(jsonRes.token);
setIsError(false);
setMessage(jsonRes.message);
}
} catch (err) {
console.log(err);
};
})
.catch(err => {
console.log(err);
});
};
const getMessage = () => {
const status = isError ? `Error: ` : `Success: `;
return status + message;
}
return (
<View style={styles.card}>
<Text style={styles.heading}>{isLogin ? 'Plugin to your Account' : 'Signup'}</Text>
<View style={styles.form}>
<View style={styles.inputs}>
<TextInput style={styles.input} placeholder="Email" autoCapitalize="none" onChangeText={setEmail}></TextInput>
{!isLogin && <TextInput style={styles.input} placeholder="Name" onChangeText={setName}></TextInput>}
<TextInput secureTextEntry={true} style={styles.input} placeholder="Password" onChangeText={setPassword}></TextInput>
<Text style={[styles.message, { color: isError ? 'red' : 'green' }]}>{message ? getMessage() : null}</Text>
<TouchableOpacity style={styles.button} onPress={onSubmitHandler}>
<Text style={styles.buttonText}>Done</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.buttonAlt} onPress={onChangeHandler}>
<Text style={styles.buttonAltText}>{isLogin ? 'Sign Up' : 'Log In'}</Text>
</TouchableOpacity>
</View>
</View>
</View>
);
};
const styles = StyleSheet.create({
back: {
flex: 1,
width: '100%',
alignItems: 'center',
backgroundColor: '#8a2be2'
},
card: {
flex: 1,
backgroundColor: 'rgba(255, 255, 255, 0.4)',
width: '80%',
marginTop: '40%',
borderRadius: 20,
maxHeight: 380,
paddingBottom: '30%',
},
heading: {
fontSize: 30,
fontWeight: 'bold',
marginLeft: '10%',
marginTop: '5%',
marginBottom: '30%',
color: 'black',
},
form: {
flex: 1,
justifyContent: 'space-between',
paddingBottom: '5%',
},
inputs: {
width: '100%',
flex: 1,
alignItems: 'center',
justifyContent: 'center',
paddingTop: '10%',
},
input: {
width: '80%',
borderBottomWidth: 1,
borderBottomColor: 'black',
paddingTop: 10,
fontSize: 16,
minHeight: 40,
},
button: {
width: '80%',
backgroundColor: 'black',
height: 40,
borderRadius: 50,
justifyContent: 'center',
alignItems: 'center',
marginVertical: 5,
},
buttonText: {
color: 'white',
fontSize: 16,
fontWeight: '400'
},
buttonAlt: {
width: '80%',
borderWidth: 1,
height: 40,
borderRadius: 50,
borderColor: 'black',
justifyContent: 'center',
alignItems: 'center',
marginVertical: 5,
},
buttonAltText: {
color: 'black',
fontSize: 16,
fontWeight: '400',
},
message: {
fontSize: 16,
marginVertical: '5%',
},
});
export default AuthScreen;
我的后端是:
用于身份验证:
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';
import User from '_components/atoms/user.js';
const signup = (req, res, next) => {
// checks if email already exists
User.findOne({
where: {
email: req.body.email,
}
})
.then(dbUser => {
if (dbUser) {
return res.status(409).json({ message: "email already exists" });
} else if (req.body.email && req.body.password) {
// password hash
bcrypt.hash(req.body.password, 12, (err, passwordHash) => {
if (err) {
return res.status(500).json({ message: "couldnt hash the password" });
} else if (passwordHash) {
return User.create(({
email: req.body.email,
name: req.body.name,
password: passwordHash,
}))
.then(() => {
res.status(200).json({ message: "user created" });
})
.catch(err => {
console.log(err);
res.status(502).json({ message: "error while creating the user" });
});
};
});
} else if (!req.body.password) {
return res.status(400).json({ message: "password not provided" });
} else if (!req.body.email) {
return res.status(400).json({ message: "email not provided" });
};
})
.catch(err => {
console.log('error', err);
});
};
const login = (req, res, next) => {
// checks if email exists
User.findOne({
where: {
email: req.body.email,
}
})
.then(dbUser => {
if (!dbUser) {
return res.status(404).json({ message: "user not found" });
} else {
// password hash
bcrypt.compare(req.body.password, dbUser.password, (err, compareRes) => {
if (err) { // error while comparing
res.status(502).json({ message: "error while checking user password" });
} else if (compareRes) { // password match
const token = jwt.sign({ email: req.body.email }, 'secret', { expiresIn: '1h' });
res.status(200).json({ message: "user logged in", "token": token });
} else { // password doesnt match
res.status(401).json({ message: "invalid credentials" });
};
});
};
})
.catch(err => {
console.log('error', err);
});
};
const isAuth = (req, res, next) => {
const authHeader = req.get("Authorization");
if (!authHeader) {
return res.status(401).json({ message: 'not authenticated' });
};
const token = authHeader.split(' ')[1];
let decodedToken;
try {
decodedToken = jwt.verify(token, 'secret');
} catch (err) {
return res.status(500).json({ message: err.message || 'could not decode the token' });
};
if (!decodedToken) {
res.status(401).json({ message: 'unauthorized' });
} else {
res.status(200).json({ message: 'here is your resource' });
};
};
export { signup, login, isAuth };
用于连接到 mysql:
import { Sequelize } from 'sequelize';
const sequelize = new Sequelize('logindb', 'root', 'Ben@1312', {
dialect: 'mysql',
host: 'localhost',
});
export default sequelize;
和
import express from 'express';
import sequelize from '_utils/database.js';
import router from '_utils/routes.js';
const app = express();
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use((_, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
next();
});
app.use(router);
sequelize.sync();
app.listen(3000);
感谢您的帮助真诚的 Deftsu
解决方案
推荐阅读
- python - 如何为 tkinter 创建语言按钮?
- autodesk-forge - 可以在 Tableau 仪表板中嵌入 forge Viewer 吗?
- r - 如何创建两列计算两个条件的总数
- r - 在 R 中反向计算 t 统计量
- excel - 通过 SUMPRODUCT 和 SUMIFS 粘贴负值的 SUM
- javascript - 聊天 php 脚本到 codeigniter 4
- c++ - 31==错误:AddressSanitizer:负大小参数:(大小=-4))
- firebase - 为什么 FCM 的 onLaunch 方法被多次调用
- airflow - 有没有办法将气流中的两个任务联系在一起 w/r/t 重试?
- bash - 如何在 sed 命令中包含 1 个或多个空格