Angular 返回 OPTIONS 的结果,而不是调用的方法

Posted

技术标签:

【中文标题】Angular 返回 OPTIONS 的结果,而不是调用的方法【英文标题】:Angular returns result of OPTIONS and not the method called 【发布时间】:2018-05-28 21:24:09 【问题描述】:

我有一些 Angular 4 应用程序,并期待一个奇怪的错误。 有一个服务,myService。它有一个请求方法,用于应用程序的其他部分。

(部分视图)

import  Injectable, Inject  from '@angular/core';
import  Http, RequestOptions, Headers, Response  from '@angular/http';
import  Observable  from 'rxjs';
import  SweetAlertService  from 'ng2-sweetalert2';
import  TranslateService  from '@ngx-translate/core';
import  Toast, ToastsManager  from 'ng2-toastr/ng2-toastr';

@Injectable()
export class myService 

    constructor(
        @Inject(SweetAlertService) swal: SweetAlertService,
        private http: Http,
        public toaster: ToastsManager
    ) 
        this._swal = swal;
    

    public absTop(el) 
        return el.offsetParent ? el.offsetTop + this.absTop(el.offsetParent) : el.offsetTop;
    

    public post(path: string, requestData?: any, settings?: any) 
        !settings && (settings = );
        settings.method = 'post';
        return this.request.call(this, path, requestData, settings);
    

    public get(path: string, requestData?: any, settings?: any) 
        !settings && (settings = );
        settings.method = 'get';
        return this.request.call(this, path, requestData, settings);
    

    public request(path: string, requestData?: any, settings?: any): Observable<Response> 
        settings = settings || ;
        var supErr = settings.suppressError;

        let headers = new Headers();
        headers.append('Content-Type', 'application/json');
        let options = new RequestOptions( headers: headers )

        let prefix: string = window['requestUrlPrefix'] || '';

        if (!window['countLoadings']) 
            window['countLoadings'] = 1;
         else 
            ++window['countLoadings'];
        

        if (document.body.className.indexOf("load-mask") < 0) 
            document.body.className += " load-mask";
        

        var toid = setTimeout(function() 
            if (window['countLoadings'] > 0) 
                if (document.body.className.indexOf("load-spinner") < 0) 
                    document.body.className += " load-spinner";
                
            
        , 400);

        let method = settings && settings.method ? settings.method : 'post';
        let obs = this.http[method](prefix + path, JSON.stringify(requestData), options).share();

        if (settings.timeout) 
            obs = obs.timeout(settings.timeout);
        

        let onErr = (err) => 
            let resp = '';

            let status = err.status ? err.status : err.name;

            if (supErr === true || supErr == status || (Object.prototype.toString.call(supErr) === '[object Array]' && supErr.indexOf(status) >= 0)) 
                // supress the error message
             else 
                this.swal(
                    text: 'The is an error!<br>' + resp,
                    type: 'error'
                );
            
            fin();
        ;

        let fin = () => 
            setTimeout(() => 
                if (--window['countLoadings'] === 0) 
                    document.body.className = document.body.className.replace(/\bload-mask\b/, '').replace(/\bload-spinner\b/, '');
                    clearTimeout(toid);
                
            , 1);
        ;

        obs.subscribe(
            fin,
            onErr
        );

        return obs;
    

后端部分是绝对正确的。返回所有必需的标头。 CORS 始终设置为原点(在开发模式下),因此没有任何问题。

问题部分在这里:

...cut...
export class AppComponent implements OnInit 

constructor(
    public settings: SettingsService,
    public myService: myService,
...cut...
        myService.post('/someEndpoint', null, 
            timeout: 10000,
            suppressError: [412, 403]
        ).subscribe((ret) => 

            console.log(ret);
...cut...

console.log(ret) 始终显示浏览器完成的预检请求的结果(正文)。如果我禁用 CORS(例如在 Safari 中),它可以正常工作,因为返回了正确的数据。但是启用 CORS(因为它在 prod 中)后,订阅部分中会出现错误的数据。

附加信息(示例):

该应用程序在app.somedomain.com 下可用 api 在api.somedomain.com 下可用

这里有什么问题? (我不知道 Angular :D)

更新

我尝试简单地添加一个方法来进行 api 调用。它看起来像这样:

public test(): Observable<Response> 

        let headers = new Headers();
        headers.append('Content-Type', 'application/json');
        let options = new RequestOptions( headers: headers )

        return this.http
            .post('http://api.somedomain.com/someEndpoint', '' ,options)
            .map(response => 
                console.log(response)
                return response
            )
            .catch(this.handleError);

而且我仍然从浏览器的 OPTION 调用中得到响应...

我在某些组件中这样调用方法:

this.test = this.myService.test();

【问题讨论】:

什么是jfs? myService taht 的实例包装了 http 服务?看起来你是直接调用请求,这不应该这样做,因为你没有设置方法 抱歉,更新了代码。应该怎么称呼? 这个服务不是你写的吗?您需要为您正在尝试执行的操作调用正确的 http 请求类型,例如 get、put、post、delete...请求实际上应该是仅由服务内部使用的私有方法 这不是我的代码,但我必须修复它...如我所见,post 被称为默认方法类型 (this.http[method])。即使在 AppComponent 中改成post 也没有变化 它没有正确完成,这整件事绝对是一团糟。不知道你从哪里弄来的,但我的建议是把它扔掉,永远不要再使用给你这个的人的代码 【参考方案1】:

答案似乎很简单……

options.withCredentials = true 丢失...(在请求中)

【讨论】:

以上是关于Angular 返回 OPTIONS 的结果,而不是调用的方法的主要内容,如果未能解决你的问题,请参考以下文章

Angular:HTTP GET 请求 - OPTIONS 405(不允许的方法)

如何在 React 中正确地进行 GET 调用,返回一个 observable(类似于 Angular 中的方法而不使用 Promise)?

来自2个不同Web服务的Angular Populate mat-optgroup / mat-options

有时 PHAsset fetchAssetsWithLocalIdentifiers:options 方法返回一个空的提取结果

如何从另一个组件返回到另一个组件而不以角度重新加载组件?

为啥查询的数据在结果集中返回而不是在数组中?