Angular 4入门教程系列:13:跨域问题解决方法
跨域问题是web开发碰到的非常常见的问题之一,解决方法也有很多,这篇文章将会整理一下最简单的两种典型解决方法,nginx的反向代理和angular-cli自带的代理配置方式。
模拟后端
首先我们使用express+node来模拟一个提供数据的后端服务。
安装express
[root@angular proj]# npm install express
npm WARN proj@1.0.0 No repository field.
+ express@4.16.2
added 46 packages in 17.212s
[root@angular proj]#
模拟后端
模拟一个最简单的功能,用户通过api/heroes的URI能够取到heroes的信息,具体代码如下:
[root@angular proj]# cat dist/backsrv.js
const express = require("express");
const app = express();
let heroes = [
{ id: 0, name: 'Zero' },
{ id: 11, name: 'Mr. Nice' },
{ id: 12, name: 'Narco' },
{ id: 13, name: 'Bombasto' },
{ id: 14, name: 'Celeritas' },
{ id: 15, name: 'Magneta' },
{ id: 16, name: 'RubberMan' },
{ id: 17, name: 'Dynama' },
{ id: 18, name: 'Dr IQ' },
{ id: 19, name: 'Magma' },
{ id: 20, name: 'Tornado' }
];
app.get("/api/heroes",(req,res)=>{
res.json(heroes);
});
app.listen(8080,"192.168.163.151",()=>console.log("Service has been started at the port 8080..."))
[root@angular proj]#
启动服务
使用node启动模拟后端服务
[aaa@qq.com proj]# node dist/backsrv.js
Service has been started at the port 8080...
通过页面访问,结果如下:
前端设定
继续使用第8篇文章的HelloAngular的工程,在其根目录创建Angular-cli的代理设定文件,具体内容如下:
/workspace/HelloAngular # cat proxy.conf.json
{
"/api/": {
"target": "http://192.168.163.151:8080/",
"secure": false
}
}
/workspace/HelloAngular #
你会发现这个跟nginx的反响代理设定非常相似,其实其所做的就是将匹配http://192.168.163.151:8080/api/的内容发到http://192.168.163.151:4200/api/,但是写法略有不同,详细可以参看https://webpack.github.io/docs/webpack-dev-server.html#proxy
启动前端
ng serve -H 0.0.0.0 –proxy-config proxy.conf.json –open
因为此为在容器中启动所以有-H 0.0.0.0,不在容器中根据情况启动时不使用此选项即可
/workspace/HelloAngular # ng serve -H 0.0.0.0 --proxy-config proxy.conf.json --open
** NG Live Development Server is listening on 0.0.0.0:4200, open your browser on http://localhost:4200/ **
...
chunk {vendor} vendor.bundle.js, vendor.bundle.js.map (vendor) 3.07 MB [initial] [rendered]
webpack: Compiled successfully.
确认结果
确认proxy.conf.json已经正常起到作用,可以进行跨域访问
这样angular-cli自带的方式就简单验证完毕了,接下来看一下nginx怎样设定。
nginx反向代理
事前准备
依然让express的后端服务继续运行
[aaa@qq.com proj]# node dist/backsrv.js
Service has been started at the port 8080...
ng build
使用ng build进行构建,生成dist对象目录
/workspace/HelloAngular # ng build --prod --aot
Date: 2017-11-12T21:03:34.949Z
Hash: 01ac9865708afa91122f
Time: 73829ms
chunk {0} polyfills.14173651b8ae6311a4b5.bundle.js (polyfills) 61.4 kB {4} [initial] [rendered]
chunk {1} main.9b501447634295d191b6.bundle.js (main) 18.1 kB {3} [initial] [rendered]
chunk {2} styles.d41d8cd98f00b204e980.bundle.css (styles) 0 bytes {4} [initial] [rendered]
chunk {3} vendor.d9514c5d6ae413b22be2.bundle.js (vendor) 425 kB [initial] [rendered]
chunk {4} inline.86bf4b1ff0e2bd46ee26.bundle.js (inline) 1.45 kB [entry] [rendered]
/workspace/HelloAngular #
给后面的nginx做个tar包
/workspace/HelloAngular # tar cvpf dist.tar dist
dist/
dist/polyfills.14173651b8ae6311a4b5.bundle.js
dist/main.9b501447634295d191b6.bundle.js
dist/vendor.d9514c5d6ae413b22be2.bundle.js
dist/inline.86bf4b1ff0e2bd46ee26.bundle.js
dist/styles.d41d8cd98f00b204e980.bundle.css
dist/favicon.ico
dist/index.html
dist/3rdpartylicenses.txt
/workspace/HelloAngular #
从镜像中拷贝出tar文件,然后展开
[aaa@qq.com tmp]# docker cp festive_johnson:/workspace/HelloAngular/dist.tar .
[aaa@qq.com tmp]# tar xvf dist.tar
dist/
dist/polyfills.14173651b8ae6311a4b5.bundle.js
dist/main.9b501447634295d191b6.bundle.js
dist/vendor.d9514c5d6ae413b22be2.bundle.js
dist/inline.86bf4b1ff0e2bd46ee26.bundle.js
dist/styles.d41d8cd98f00b204e980.bundle.css
dist/favicon.ico
dist/index.html
dist/3rdpartylicenses.txt
[aaa@qq.com proj]#
下载nginx镜像
只要有nginx即可,不是使用容器方式的可以直接跳过跟容器相关的步骤
[aaa@qq.com ~]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
bc95e04b23c0: Pull complete
a21d9ee25fc3: Pull complete
9bda7d5afd39: Pull complete
Digest: sha256:9fca103a62af6db7f188ac3376c60927db41f88b8d2354bf02d2290a672dc425
Status: Downloaded newer image for nginx:latest
[aaa@qq.com ~]#
启动nginx
[aaa@qq.com proj]# [aaa@qq.com proj]# docker run -it -p 4200:80 -v /tmp/dist:/usr/share/nginx/html –name=nginx nginx
结果确认
可以确认目前通过8080和4200都能正常访问
而通过4200/api/heroes则提示404,因为此时还没有设定nginx的反向代理
nginx设定
我们进到容器中,通过设定如下文件便可进行反向代理的设定
[aaa@qq.com dist]# docker exec -it nginx sh
# cd /etc/nginx/conf.d
# ls
default.conf
#
我们所需要做的事情就是把这个文件中添加如下一段设定即可,跟angular-cli的proxy.conf.json是不是非常类似,因为proxy都是工作原理都是相近的,至少在外面设定的时候所需要的信息都是一样的。
location /api/ {
proxy_pass http://192.168.163.151:8080/api/;
proxy_redirect default;
}
发现nginx里面没有vi,可以把设定文件挂出来进行修改,由于只是演示,直接使用cat+EOF吧
修改前
# cat default.conf
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
#
修改
使用如下方式进行执行
cat <<EOF >default.conf
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /api/ {
proxy_pass http://192.168.163.151:8080/api/;
proxy_redirect default;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
EOF
修改后
# cat default.conf
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /api/ {
proxy_pass http://192.168.163.151:8080/api/;
proxy_redirect default;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
#
重启nginx镜像
ctrl + c中断当前的nginx镜像,然后重新启动即可
[root@angular proj]# docker start nginx
nginx
[root@angular proj]#
结果确认
确认已经能够进行跨域的访问了
总结
这篇文章总结了angular解决跨域的两种常见方式,并结合express和实际的例子进行了验证。
上一篇: Grafana监控腾讯cdb物理资源信息
下一篇: nginx学习