关于Angular2 + node接口调试的解决方案,主要可以从以下几个方面入手:
1. 安装Body-parser模块和CORS模块
在Node端,我们需要通过这两个模块来对请求和响应进行处理,解决跨域问题。在项目根目录下使用npm安装这两个模块:
npm install body-parser cors --save
在Node端的app.js文件中使用以下代码完成引入、配置:
const express = require('express');
const cors = require('cors');
const bodyparser = require('body-parser');
const app = express();
app.use(cors());
app.use(bodyparser.json());
2. 设置代理
在大部分情况下,前端和后端是分离的,存在跨域问题。解决跨域问题的办法有很多,其中较为简单有效的方案是设置代理。在Angular2中,需要到proxy.conf.json文件中进行配置。
示例:
假设后端接口地址是http://localhost:3000/api/users,我们在proxy.conf.json中配置代理:
{
"/api/*": {
"target": "http://localhost:3000",
"secure": false,
"changeOrigin": true
}
}
3. 在服务端和客户端分别设置环境变量
为了避免因为前后端环境变量设置不一致导致的调试问题,我们需要在服务端和客户端分别设置环境变量。在服务端的app.js文件中加入以下代码:
process.env.NODE_ENV = 'development';
在客户端的environment.ts文件中加入以下代码:
export const environment = {
production: false,
API_URL: 'http://localhost:4200/api'
};
示例1:调用Node API中存储在MongoDB中的数据
具体步骤如下:
- 安装mongoose
npm install mongoose --save
- 在mongoose.js文件中编写代码连接MongoDB数据库
const mongoose = require('mongoose');
const MONGODB_URI = 'mongodb://localhost/myapp_test';
mongoose.connect(MONGODB_URI, {
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true
}, err => {
if (err) {
console.log(err);
} else {
console.log('MongoDB Connected');
}
});
- 新建model并建立与数据库的映射
const UserSchema = new mongoose.Schema({
name: String,
email: String,
password: String
});
const User = mongoose.model('User', UserSchema);
module.exports = User;
- 在routes目录下,新建users.js文件,实现查询用户信息的API接口
const express = require('express');
const router = express.Router();
const User = require('../models/User');
router.get('/:id', (req, res) => {
User.findById(req.params.id)
.then(user => {
if (!user) {
return res.status(404).send();
}
res.send(user);
})
.catch(err => {
res.status(500).send(err);
});
});
module.exports = router;
- 在app.js中注册/users路由
const usersRouter = require('./routes/users');
app.use('/api/users', usersRouter);
- 在前端调用users接口
在前端的users.component.ts文件中,编写以下代码调用API:
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { environment } from '../../environments/environment';
@Component({
selector: 'app-users',
templateUrl: './users.component.html',
styleUrls: ['./users.component.scss']
})
export class UsersComponent implements OnInit {
user: any;
constructor(private http: HttpClient) { }
ngOnInit(): void {
this.http.get(`${environment.API_URL}/users/5f1d6b356f25f237b3e0366c`)
.subscribe(data => {
console.log(data);
this.user = data;
});
}
}
这里假设我们要查询的用户ID是5f1d6b356f25f237b3e0366c,我们并没有手动设置CORS,也没有手动设置请求头部,而是使用了通过proxy.conf.json配置的代理。
示例2:使用Passport验证用户登录
以下以username/password方式的验证为例。
- 安装passport相关模块
npm install passport passport-local passport-jwt jsonwebtoken bcryptjs --save
- 在passport.js文件中编写代码
const passport = require('passport');
const localStrategy = require('passport-local').Strategy;
const jwtStrategy = require('passport-jwt').Strategy;
const extractJwt = require('passport-jwt').ExtractJwt;
const bcrypt = require('bcryptjs');
const User = require('../models/User');
// 验证username/password
passport.use(new localStrategy({
usernameField: 'email'
}, (email, password, done) => {
User.findOne({
email: email
})
.then(user => {
if (!user) {
return done(null, false, {
message: 'Incorrect email.'
});
}
bcrypt.compare(password, user.password)
.then(isMatch => {
if (isMatch) {
return done(null, user);
} else {
return done(null, false, {
message: 'Incorrect password.'
});
}
});
})
.catch(err => {
console.log(err);
});
}));
// 验证token
passport.use(new jwtStrategy({
jwtFromRequest: extractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: process.env.JWT_SECRET
},
(jwt_payload, done) => {
User.findById(jwt_payload.sub)
.then(user => {
if (user) {
done(null, user);
} else {
done(null, false);
}
})
.catch(err => {
done(err, false);
});
}
));
- 新增/login路由,实现登录接口
在users.js中新增/login路由以实现获取token的功能。
const express = require('express');
const router = express.Router();
const passport = require('passport');
router.post('/login', (req, res, next) => {
passport.authenticate('local', {
session: false
}, (err, user, info) => {
if (err) {
return next(err);
}
if (!user) {
return res.status(400).json({
message: info.message
});
}
req.login(user, {
session: false
}, err => {
if (err) {
return next(err);
}
const payload = {
sub: user.id,
iat: Date.now()
};
const authToken = jwt.sign(payload, process.env.JWT_SECRET);
return res.json({
user: user,
token: authToken
});
});
})(req, res, next);
});
module.exports = router;
这里使用了jwt模块生成token。
- 在前端调用接口
在前端的login.component.ts文件中,编写以下代码调用API:
import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { HttpClient } from '@angular/common/http';
import { Router } from '@angular/router';
import { environment } from '../../environments/environment';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {
form: FormGroup;
constructor(private http: HttpClient, private router: Router) { }
ngOnInit() {
this.form = new FormGroup({
email: new FormControl(''),
password: new FormControl('')
});
}
onSubmit() {
this.http.post(`${environment.API_URL}/users/login`, this.form.value)
.subscribe(data => {
console.log(data);
localStorage.setItem('authToken', data.token);
this.router.navigate(['/']);
}, err => {
console.log(err);
});
}
}
这里假设我们使用了jsonwebtoken模块生成token,此处代码含义是将email和password通过POST方式发送给后端进行验证,返回用户信息以及生成的token,最后将token保存在localStorage中以供后续使用。
以上两个示例可以供你作为参考。当然,实际开发中还有各种问题,需要结合具体的应用场景来进行调整。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:关于Angular2 + node接口调试的解决方案 - Python技术站