ionic2+angular-in-memory-web-api(内置内存服务器)+跨域问题
2017-11-10 17:05
453 查看
随着angularJS内置服务器官网的一条更新,我想很多前端的工程师在本地进行调试时均出现了大问题。关于17-10-5号的改动我也纠结了许久,随着对于前端以及IONIC框架的学习,经验总结如下:
之前一直没有查询官方文档,对着AngularJS教程的HTTP服务部分代码直接复制粘贴。发现不论怎么操作,返回结果都为空。官方给出的原因在于返回的data数据不再压缩在data属性之中而是直接作为主体部分返回。那么意味着我们需要对源代码进行如下修改:
//gethero_service.ts @Injectable() export class HeroService { //private headers = new Headers({'Content-Type': 'application/json'}); private heroesUrl = 'http://localhost:810/api/heroes'; // URL to web api constructor(private http: Http) { } getHeroes(): Observable<Hero[]> { console.log(this.http.get(this.heroesUrl)); this.http.get(this.heroesUrl).subscribe((res:Response) =>{console.log(res.json())}); return this.http.get(this.heroesUrl) .map(this.extractData) .catch(this.handleError); } create(name: string): Observable<Hero> { let headers = new Headers({ 'Content-Type': 'application/json' }); let options = new RequestOptions({ headers: headers }); return this.http.post(this.heroesUrl, { name }, options) .map(this.extractData) .catch(this.handleError); } private extractData(res: Response) { let body = res.json(); return body || { }; //主要修改的就是这一部分,之前return的是body.data由于合并之后,直接返回,所以不再需要调用内部属性;其余部分保持和官网一致。 } private handleError (error: Response | any) { // In a real world app, you might use a remote logging infrastructure let errMsg: string; if (error instanceof Response) { const body = error.json() || ''; const err = body.error || JSON.stringify(body); errMsg = `${error.status} - ${error.statusText || ''} ${err}`; } else { errMsg = error.message ? error.message : error.toString(); } console.error(errMsg); return Observable.throw(errMsg); } }
在浏览器测试正常:
观察者设计模式
在各种服务实现过程中,用到的最重要的一个设计模式就是观察者设计模式。public interface Subject{ public void registerObserver (Observer o); public void removeObserver (Observer o); public void notifyObservers(); } public interface Observer{ public void update (float temp,float humidity,float pressure); } public interface DisplayElements{ public void display(); }
public class WeatherData implements Subject{ private ArrayList observers; private float temp; private float humidity; private float pressure; public WeatherData(){ observers = new ArrayList(); } public void registerObserver(Observer o){ this.observers.add(o); } public void removeObserver (Observer o){ int i = this.observers.indexof(o); this.observers.remove(i); } public void notifyObservers(){ for(int i=0,i<this.observers.size();i++){ Observer observer =(Observer)observers.get(i); observer.update(float temp,float humidity,float pressure); } public void changes(){ this.notifyObservers(); } }
public class CurrentConditionsDisplay implements Observer,DisplayElements{ private float temp; private float humidity; private float pressure; private Subject weatherdata; public CurrentConditionsDisplay(Subject weatherdata){ this.weatherdata = weatherdata; weatherdata.registerObserver(this);//最重要的一部分 } public void update(float temp,float humidity,float pressure){ this.temp=temp; this.humidity=humidity; this.pressure=pressure; display(); } public void dispaly(){ //(略) } }
修改之后官方测试用例在本地运行正常。这里需要补充官网对于Http各种服务两种写法的区别:
1、observable:可观察对象;是一个事件流。可以利用数组操作符对它进行处理,支持:请求——取消——新请求。
这里的结构有一条编程的黄金法则:总是把数据访问工作委托给一个支持性服务类。Angular会把一个HeroService注入到组件的构造函数中,该组件将调用此服务来获取和保存数据。这个组件不会直接和 Angular 的 Http 客户端打交道! 它既不知道也不关心我们如何获取数据,这些都被委托给了HeroService去做。getHeroes()确实可以返回 HTTP 响应对象,但这不是最佳实践。 数据服务的重点在于,对消费者隐藏与服务器交互的细节。 调用HeroService的组件希望得到英雄数组。 它并不关心我们如何得到它们。 它也不在乎这些数据从哪里来。 毫无疑问,它也不希望直接和一个响应对象打交道。
在service.ts中HTTP 的 GET 方法被推迟执行。调用http.get仍然没有发送请求!这是因为可观察对象是 冷的, 调用subscribe()后,这个请求才会被发出。(Angular 的http服务把客户端/服务器通讯的工作委托给了一个叫做XHRBackend的辅助服务。)
getHeroes(): Observable<Hero[]> { return this.http.get(this.heroesUrl) .map(this.extractData) .catch(this.handleError); } getHeroes() { this.heroService.getHeroes() .subscribe( heroes => this.heroes = heroes, error => this.errorMessage = <any>error); }
2、promise:
遵循承诺的then(this.extractData).catch(this.handleError)模式。它是可观察对象的末端。我们不能在它上面调用map()函数或再次调用subscribe()函数。 Subscription对象的设计目的是不同的,这从它的主方法unsubscribe就能看出来。//service.ts getHeroes (): Promise<Hero[]> { return this.http.get(this.heroesUrl) .toPromise() .then(this.extractData) .catch(this.handleError); } //html.ts getHeroes() { this.heroService.getHeroes() .then( heroes => this.heroes = heroes, error => this.errorMessage = <any>error); }
请求头 (headers)
我们通过Content-Type头{‘Content-Type’: ‘application/json’}告诉服务器,body 是 JSON 格式的。接下来,使用headers对象来配置options对象。 options对象是RequestOptions的新实例,该类允许你在实例化请求时指定某些设置。这样, Headers 是 RequestOptions 中的一员。
跨域请求
出于安全的考虑,网络浏览器会阻止调用与当前页面不“同源”的远端服务器的XHR(http实际调用的get/post请求函数)。 所谓源就是 URI 的协议 (scheme)、主机名 (host) 和端口号 (port) 这几部分的组合。 这被称为同源策略。跨域请求的两类服务器:
现代的CORS API和一个传统的JSONP搜索 API(只允许调用get方法)
//1. 等用户停止输入 //2. 当搜索关键字变化了才搜索 //3. 对付乱序响应体 this.items = this.searchTermStream .debounceTime(300) .distinctUntilChanged() .switchMap((term: string) => this.wikipediaService.search(term));
跨站请求伪造攻击
在一个跨站请求伪造攻击(CSRF 或 XSRF)中,攻击者欺骗用户访问一个不同的网页,它带有恶意代码,秘密向你的应用程序服务器发送恶意请求。客户端和服务器必须合作来抵挡这种攻击。 Angular 的http客户端自动使用它默认的CookieXSRFStrategy来完成客户端的任务。cookie(服务器生成,保存在客户端)
Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。
因为HTTP请求采用的是Ajax技术,其调用的核心代码模块为XMLHttpRequest();在请求头中,如果需要记录下client的cookie信息,需要在请求头中做如下修改:
let headers = new Headers({ 'Content-Type': 'application/json' }); let options = new RequestOptions({ headers: headers,withCredentials:true});//注意这里带了一个类似cookie的东西。 return this.http.post(this.heroesUrl,JSON.stringify({user_id:id,user_password:password}), options) .map(this.extractData) .catch(this.handleError);
withCredentials:true该属性是告诉浏览器,1、允许创建来自不同域的cookie信息;2、每次的跨域请求都允许带上该cookie信息。
IONIC2在浏览器中部署因为涉及到HTTP协议,故涉及到跨域问题,但当应用部署到手机上时,便采用file协议。故不存在跨域问题。本文解决跨域问题的思路是采用代理服务器,需要修改ionic.config.json文件的代理配置如下:
{ "name": "MenuDemo", "app_id": "", "type": "ionic-angular", "integrations": { "cordova": { } }, "proxies": [{ "path": "/services", "proxyUrl": "http://192.168.4.184:8080/DomainRIS/services" }] }
运行应用,上图中可见代理地址启动。跨域问题得到解决。
相关文章推荐
- angular-in-memory-web-api
- angular官网教程第7个HTTP,找不到angular-in-memory-web-api
- Cannot find module “angular-in-memory-web-api”
- 【ng2】Cannot find module 'angular-in-memory-web-api'
- Cannot find module 'angular-in-memory-web-api'
- 关于Angular2.0 in-memory-web-api的GET http://localhost:3000/traceur 404 (Not Found)等错误的解决方法之一
- .Net WebAPI解决跨域问题
- c# WebApi之解决跨域问题:Cors
- InMemoryWebApiModule
- wordpress内存不足问题“Fatal error:out of memoryin etc...”
- 本地web访问远程服务器后端引发的跨域问题
- 关于VS2005内置web服务器和IIS的区别问题(讨论,收集)
- 用nginx解决webstorm内置server调用本地api的跨域问题
- tonardo做web服务器播放大视频内存泄露问题的解决
- web api post/put空值问题以及和angular的冲突的解决
- tonardo做web服务器播放大视频内存泄露问题的解决
- nginx服务器通过配置来解决API的跨域问题
- ABP .Net Core API和Angular前端APP独立部署跨域问题(No Access-Control-Allow-Origin)
- 本地地图api传到服务器上不显示,解决跨域问题
- ionic $http 无法正常访问外部web服务器的问题