在开发中设置用于从 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) 在一个对话框中设置开始时间、结束时间和持续时间