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 浏览器中运行良好。我必须清除边缘浏览器数据,它起作用了