Express API 适用于 curl 但不适用于浏览器
Express API works with curl but not in browser
我按照本教程 https://www.positronx.io/angular-8-mean-stack-tutorial-build-crud-angular-material/ 创建了一个 MEAN 应用程序
我的快递 API 通过 curl 工作,数据成功填充 mongo 数据库。我的 angular 前端也可以在使用 nginx 作为服务器的实时浏览器中工作。我还可以 proxy_pass 使用 express 直接为 angular 静态文件提供服务。
当我尝试从浏览器 POST 将数据输入表单时,我收到一条错误消息 ERR_CONNECTION_REFUSED。我已经坚持了几天,不知道如何解决这个问题。我怀疑问题出在我的 nginx 文件或 /sites-available/default 文件上,因为 curl 在命令行中有效。
我的关键文件是:
/etc/nginx/sites-available/default:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
app.js(快递):
let express = require('express'),
path = require('path'),
mongoose = require('mongoose'),
cors = require('cors'),
bodyParser = require('body-parser'),
dataBaseConfig = require('./database/db');
// Connecting mongoDB
mongoose.Promise = global.Promise;
mongoose.connect(dataBaseConfig.db, {
useNewUrlParser: true,
useFindAndModify: false
}).then(() => {
console.log('Database connected sucessfully ')
},
error => {
console.log('Could not connected to database : ' + error)
}
);
// Set up express js port
const studentRoute = require('./routes/student.route');
const app = express();
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(bodyParser.json());
app.use(cors());
// Setting up static directory
app.use(express.static('../dist/meanstack'));
// RESTful API root
app.use('/api', studentRoute);
// PORT
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log('Connected to port ' + port);
})
// Find 404 and hand over to error handler
app.use((req, res, next) => {
next(createError(404));
});
// Index Route
app.get('/', (req, res) => {
res.send('invaild endpoint');
});
app.get('*', (req, res) => {
res.sendFile('../dist/meanstack/index.html');
});
//error handler
app.use(function (err, req, res, next) {
console.error(err.message);
if (!err.statusCode) err.statusCode = 500;
res.status(err.statusCode).send(err.message);
});
以及连接后端和前端的angular api.service文件:
import { Injectable } from '@angular/core';
import { Student } from './student';
import { Observable, throwError } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class ApiService {
endpoint: string = 'http://localhost:3000/api';
headers = new HttpHeaders().set('Content-Type', 'application/json');
constructor(private http: HttpClient) { }
// Add student
AddStudent(data: Student): Observable<any> {
let API_URL = `${this.endpoint}/add-student`;
return this.http.post(API_URL, data)
.pipe(
catchError(this.errorMgmt)
)
}
// Get all students
GetStudents() {
return this.http.get(`${this.endpoint}`);
}
// Get student
GetStudent(id): Observable<any> {
let API_URL = `${this.endpoint}/read-student/${id}`;
return this.http.get(API_URL, { headers: this.headers })
.pipe(
map((res: Response) => {
return res || {}
}),
catchError(this.errorMgmt)
)
}
// Update student
UpdateStudent(id, data): Observable<any> {
let API_URL = `${this.endpoint}/update-student/${id}`;
return this.http.put(API_URL, data, { headers: this.headers })
.pipe(
catchError(this.errorMgmt)
)
}
// Delete student
DeleteStudent(id): Observable<any> {
var API_URL = `${this.endpoint}/delete-student/${id}`;
return this.http.delete(API_URL)
.pipe(
catchError(this.errorMgmt)
)
}
// Error handling
errorMgmt(error: HttpErrorResponse) {
let errorMessage = '';
if (error.error instanceof ErrorEvent) {
// Get client-side error
errorMessage = error.error.message;
} else {
// Get server-side error
errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
}
console.log(errorMessage);
return throwError(errorMessage);
}
}
我正在添加./routes/student.route.js
const express = require('express');
const app = express();
const studentRoute = express.Router();
// Student model
let Student = require('../database/model/Student');
// Add Student
studentRoute.route('/add-student').post((req, res, next) => {
Student.create(req.body, (error, data) => {
if (error) {
return next(error)
} else {
res.json(data)
}
})
});
// Get all student
studentRoute.route('/').get((req, res) => {
Student.find((error, data) => {
if (error) {
return next(error)
} else {
res.json(data)
}
})
})
// Get single student
studentRoute.route('/read-student/:id').get((req, res) => {
Student.findById(req.params.id, (error, data) => {
if (error) {
return next(error)
} else {
res.json(data)
}
})
})
// Update student
studentRoute.route('/update-student/:id').put((req, res, next) => {
Student.findByIdAndUpdate(req.params.id, {
$set: req.body
}, (error, data) => {
if (error) {
return next(error);
console.log(error)
} else {
res.json(data)
console.log('Student successfully updated!')
}
})
})
// Delete student
studentRoute.route('/delete-student/:id').delete((req, res, next) => {
Student.findByIdAndRemove(req.params.id, (error, data) => {
if (error) {
return next(error);
} else {
res.status(200).json({
msg: data
})
}
})
})
module.exports = studentRoute;
我欢迎任何提示,因为这是我能够让我的第一个 MEAN 应用程序教程上线之前的最后一步。如果您需要任何说明,请告诉我。谢谢。
编辑 1:我添加了 ./routes/student.route.js 文件。阅读更多内容后,我想知道这个问题是否与 cors 相关。
编辑 2:我从终端添加了 curl 输出的屏幕截图
编辑 3:我已经按照这里 https://enable-cors.org/server_nginx.html 的描述尝试了 nginx cors 有和没有 proxy_pass 来表达,但也没有解决这个问题
这个问题现在已经解决了。问题出在 angular
中的 api.service 文件
endpoint: string = 'http://localhost:3000/api';
这里localhost:3000要换成域名
endpoint: string = 'http://www.example.com/api';
就我而言,我是 运行 本地 3000 端口的快速服务器,能够通过 curl 而不是浏览器从“/”端点获得响应。然后我注意到该路由在 chrome 浏览器中运行良好。我必须清除边缘浏览器数据,它起作用了
我的快递 API 通过 curl 工作,数据成功填充 mongo 数据库。我的 angular 前端也可以在使用 nginx 作为服务器的实时浏览器中工作。我还可以 proxy_pass 使用 express 直接为 angular 静态文件提供服务。
当我尝试从浏览器 POST 将数据输入表单时,我收到一条错误消息 ERR_CONNECTION_REFUSED。我已经坚持了几天,不知道如何解决这个问题。我怀疑问题出在我的 nginx 文件或 /sites-available/default 文件上,因为 curl 在命令行中有效。
我的关键文件是:
/etc/nginx/sites-available/default:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
app.js(快递):
let express = require('express'),
path = require('path'),
mongoose = require('mongoose'),
cors = require('cors'),
bodyParser = require('body-parser'),
dataBaseConfig = require('./database/db');
// Connecting mongoDB
mongoose.Promise = global.Promise;
mongoose.connect(dataBaseConfig.db, {
useNewUrlParser: true,
useFindAndModify: false
}).then(() => {
console.log('Database connected sucessfully ')
},
error => {
console.log('Could not connected to database : ' + error)
}
);
// Set up express js port
const studentRoute = require('./routes/student.route');
const app = express();
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(bodyParser.json());
app.use(cors());
// Setting up static directory
app.use(express.static('../dist/meanstack'));
// RESTful API root
app.use('/api', studentRoute);
// PORT
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log('Connected to port ' + port);
})
// Find 404 and hand over to error handler
app.use((req, res, next) => {
next(createError(404));
});
// Index Route
app.get('/', (req, res) => {
res.send('invaild endpoint');
});
app.get('*', (req, res) => {
res.sendFile('../dist/meanstack/index.html');
});
//error handler
app.use(function (err, req, res, next) {
console.error(err.message);
if (!err.statusCode) err.statusCode = 500;
res.status(err.statusCode).send(err.message);
});
以及连接后端和前端的angular api.service文件:
import { Injectable } from '@angular/core';
import { Student } from './student';
import { Observable, throwError } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class ApiService {
endpoint: string = 'http://localhost:3000/api';
headers = new HttpHeaders().set('Content-Type', 'application/json');
constructor(private http: HttpClient) { }
// Add student
AddStudent(data: Student): Observable<any> {
let API_URL = `${this.endpoint}/add-student`;
return this.http.post(API_URL, data)
.pipe(
catchError(this.errorMgmt)
)
}
// Get all students
GetStudents() {
return this.http.get(`${this.endpoint}`);
}
// Get student
GetStudent(id): Observable<any> {
let API_URL = `${this.endpoint}/read-student/${id}`;
return this.http.get(API_URL, { headers: this.headers })
.pipe(
map((res: Response) => {
return res || {}
}),
catchError(this.errorMgmt)
)
}
// Update student
UpdateStudent(id, data): Observable<any> {
let API_URL = `${this.endpoint}/update-student/${id}`;
return this.http.put(API_URL, data, { headers: this.headers })
.pipe(
catchError(this.errorMgmt)
)
}
// Delete student
DeleteStudent(id): Observable<any> {
var API_URL = `${this.endpoint}/delete-student/${id}`;
return this.http.delete(API_URL)
.pipe(
catchError(this.errorMgmt)
)
}
// Error handling
errorMgmt(error: HttpErrorResponse) {
let errorMessage = '';
if (error.error instanceof ErrorEvent) {
// Get client-side error
errorMessage = error.error.message;
} else {
// Get server-side error
errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
}
console.log(errorMessage);
return throwError(errorMessage);
}
}
我正在添加./routes/student.route.js
const express = require('express');
const app = express();
const studentRoute = express.Router();
// Student model
let Student = require('../database/model/Student');
// Add Student
studentRoute.route('/add-student').post((req, res, next) => {
Student.create(req.body, (error, data) => {
if (error) {
return next(error)
} else {
res.json(data)
}
})
});
// Get all student
studentRoute.route('/').get((req, res) => {
Student.find((error, data) => {
if (error) {
return next(error)
} else {
res.json(data)
}
})
})
// Get single student
studentRoute.route('/read-student/:id').get((req, res) => {
Student.findById(req.params.id, (error, data) => {
if (error) {
return next(error)
} else {
res.json(data)
}
})
})
// Update student
studentRoute.route('/update-student/:id').put((req, res, next) => {
Student.findByIdAndUpdate(req.params.id, {
$set: req.body
}, (error, data) => {
if (error) {
return next(error);
console.log(error)
} else {
res.json(data)
console.log('Student successfully updated!')
}
})
})
// Delete student
studentRoute.route('/delete-student/:id').delete((req, res, next) => {
Student.findByIdAndRemove(req.params.id, (error, data) => {
if (error) {
return next(error);
} else {
res.status(200).json({
msg: data
})
}
})
})
module.exports = studentRoute;
我欢迎任何提示,因为这是我能够让我的第一个 MEAN 应用程序教程上线之前的最后一步。如果您需要任何说明,请告诉我。谢谢。
编辑 1:我添加了 ./routes/student.route.js 文件。阅读更多内容后,我想知道这个问题是否与 cors 相关。
编辑 2:我从终端添加了 curl 输出的屏幕截图
编辑 3:我已经按照这里 https://enable-cors.org/server_nginx.html 的描述尝试了 nginx cors 有和没有 proxy_pass 来表达,但也没有解决这个问题
这个问题现在已经解决了。问题出在 angular
中的 api.service 文件 endpoint: string = 'http://localhost:3000/api';
这里localhost:3000要换成域名
endpoint: string = 'http://www.example.com/api';
就我而言,我是 运行 本地 3000 端口的快速服务器,能够通过 curl 而不是浏览器从“/”端点获得响应。然后我注意到该路由在 chrome 浏览器中运行良好。我必须清除边缘浏览器数据,它起作用了