在开发中设置用于从 Angular 向 NodeJS 发送 API 请求的服务器端口

Posted

技术标签:

【中文标题】在开发中设置用于从 Angular 向 NodeJS 发送 API 请求的服务器端口【英文标题】:Set the server port for sending API requests from Angular to NodeJS in development 【发布时间】:2019-03-30 23:11:00 【问题描述】:

我有这个 MEAN Stack 应用程序,对于我使用 Angular 6 的前端,我创建了用户 root 和后端登录系统,我已经使用 Postman 对其进行了测试,它可以按预期工作。但是当我使用表单时,我总是在下面得到这个错误:

我知道问题是将端口从4200 更改为3000,但还没有找到正确的解决方案。

这是我的服务:

import  Injectable  from '@angular/core';
import  HttpClient  from '@angular/common/http';
import  map  from 'rxjs/operators';

@Injectable()
export class UserService 

  constructor(
    private _httpClient: HttpClient
  )  


  public auth(user) 
    return this._httpClient.post('users/login', user).pipe(map((resp: any) => resp.json()));
  


这是我使用该服务的地方:

import  Component, OnInit  from '@angular/core';
import  Router  from '@angular/router';
import  UserService  from '../../services/user.service';



@Component(
  selector: 'app-side-menu',
  templateUrl: './side-menu.component.html',
  styleUrls: ['./side-menu.component.scss']
)
export class SideMenuComponent implements OnInit 

  public positionsList: Array<any> = [];
  public selectedOption: string;
  public feedbackMessage: string;

  public email: string;
  public password: string;

  public formNotValid: boolean;

  constructor(
    private _userService: UserService,
    private _router: Router
  )  

  

  ngOnInit() 
  

  public sendLoginForm() 
    if(!this.email || !this.password)
      this.formNotValid = true;
      this.feedbackMessage = "Both fields are required to login!";
      return false;
    

    const user = 
      email: this.email,
      password: this.password
    

    this._userService.auth(user).subscribe(resp => 
      if(!resp.success)
        this.feedbackMessage = resp.message;
        return false;
      
    );
  

  public getSelectedOption(option) 
    this.selectedOption = "as " + option;
  



任何想法都会受到赞赏。

【问题讨论】:

您在哪个端口上运行您的 Angular 应用程序?输入 ng serve 后端口说明了什么? 对于节点我使用 3000 端口和 4200 用于 Angular 应用程序,我知道它应该是端口,因为在邮递员上我使用了这个:localhost:3000/users/login 并且它正在工作,对于 Angular 我使用这个@ 987654329@。但在控制台上显示:POST http://localhost:4200/users/login 404 (Not Found) 是的,使用代理设置ng serve - 请参阅我的答案。 这是因为您没有在服务中指定任何主机和端口,因此 Angular 应用程序将当前运行的主机视为您的默认主机,即 localhost:4200。使用这个:return this._httpClient.post('localhost:3000/users/login', user).pipe(map((resp: any) => resp.json())); 它给了我:Failed to load localhost:3000/users/login: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https. 【参考方案1】:

您必须在 Angular ng serve 中设置代理才能将请求转发到您的 API。修改package.json运行ng serve带参数:

"scripts": 
   .....
   "start": "ng serve --proxy-config proxy.config.json",
   .....

并创建proxy.config.json 将请求转发到您的后端,例如,假设您的后端在同一台机器和端口 3000 上运行:


  "/api/*": 
   "target": "http://localhost:3000",
   "secure": false
  ,
  "/__/*": 
    "target": "http://localhost:3100",
    "secure": false
  

我相信这也可以在 angular.json 中进行配置,但从未探索过该选项。

编辑:这是在angular.json (docs) 中设置的方法:

打开angular.json,找到密钥"serve";然后在下面的"options" 中设置"proxyConfig" 键中代理配置文件的路径:

"serve": 
  "builder": "@angular-devkit/build-angular:dev-server",
  "configurations": 
     "production": 
        ...
     ,
     "development": 
        ...
     
  ,
  "defaultConfiguration": "development",
  "options": 
     "proxyConfig": "proxy.config.json"
  

【讨论】:

【参考方案2】:

您可以像这样在通话中使用完整的 URL

this._httpClient.post(window.location.protocol + '//' + window.location.hostname + ':3000/' + 'users/login', user)

理想情况下,您应该让微服务在反向代理后面,并根据 URI 路径路由您的请求

【讨论】:

这在生产环境中不起作用,除非服务器也在生产环境中的端口 3000 上运行。 即使在开发模式下Failed to load http://localhost:3000/users/login: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access. @PeS 是的。我建议在开发过程中将其作为一种解决方法,但理想情况下,应在生产中使用反向代理来处理此类情况。顺便说一句,您的答案对开发来说更好。 :) @NajmEddineZAGA 您必须在运行在端口 3000 的服务器上启用 CORS。如果它是 express 服务器,请使用 npm install cors 安装 cors 模块,然后将其添加为像 app.use(cors()) 这样的中间件。更多信息请参考this。 这个错误已经不存在了,我想它可能有效。我必须解决另一个响应问题,如果解决了,我会通知您【参考方案3】:

您可以尝试将 api 调用的 url 放入变量中,然后将其附加到带有特定路由的 http 动词 url 中。

import  Injectable  from '@angular/core';
import  HttpClient  from '@angular/common/http';
import  map  from 'rxjs/operators';

@Injectable()
export class UserService 
url='http://localhost:3000/'
  constructor(
    private _httpClient: HttpClient
  )  


  public auth(user) 
    return this._httpClient.post(this.url+'users/login', user).pipe(map((resp: any) => resp.json()));
  


【讨论】:

Failed to load http://localhost:3000/users/login: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access. 在你的节点文件中添加 cors 插件。 cors 允许跨源请求响应。 在您的节点应用程序中,您必须允许来自 __http://localhost:4200 来源的请求。 @Apar Adhikari 提供的解决方案应该没问题。【参考方案4】:

如果您使用不同的环境,您可以在环境文件中设置它们

例如,您的evironment.dev.ts 看起来像这样

export const environment = 
  production: false,
  API_REST_URL: 'https://yourDomainName', // can be http://localhost as well
  API_REST_PORT: 3000
;

在你的服务中你会像这样使用它

import  environment  from '/path/to/environment';

@Injectable()
export class MyService
  apiPort = environment['API_REST_PORT'];
  apiUrl = environment['API_REST_URL'];

  constructor(private http: HttpClient) 
  

  apiCall(): Observable<any> 
    return this.http.get(`$this.apiUrl:$this.apiPort/endpoint/path`)
      .pipe(map(data => 
        return data;
      ));
  

要在dev 环境中为您的应用提供服务,您可以将命令添加到package.json 中的scripts object

 "scripts": 
    ...
    "start-dev": "ng serve --configuration=dev",
    "build:dev": "ng build --configuration=dev",
    ...
  ,

【讨论】:

以上是关于在开发中设置用于从 Angular 向 NodeJS 发送 API 请求的服务器端口的主要内容,如果未能解决你的问题,请参考以下文章

angular 5 stepper selectedIndex 不适用于订阅中设置的变量

如何使用 Ionic (Angular) 在一个对话框中设置开始时间、结束时间和持续时间

如何在 Angular 2 Http Observable 请求中设置间隔

在 Angular 模板中设置类值

为啥要在 Angular 中设置依赖提供者?

在 Angular/Material 中设置 mat-form-field 输入样式