简体   繁体   English

Angular10 - XHR 加载失败:POST - 浏览器阻止 HTTP 请求同名域

[英]Angular10 - XHR failed loading: POST - Browser blocks HTTP Request to domain of identical name

I have a webpage consisting of a Django REST API and an Angular 10 Frontend SPA.我有一个网页,其中包含一个 Django REST API 和一个 ZC31C335EF37283C451B18BA0DA1 前端 1DE1ZDD3。 Generally I can send GET-, POST-, PUT- and DELETE-XHR Requests to my backend without issue, I only have a single API Endpoint where categorically my SPA's requests are cancelled, somehow.通常,我可以毫无问题地将 GET-、POST-、PUT- 和 DELETE-XHR 请求发送到我的后端,我只有一个 API 端点,我的 SPA 请求以某种方式被明确地取消了。 The issue occurs on both Chrome and Firefox and seems browser independant.该问题出现在 Chrome 和 Firefox 上,并且似乎与浏览器无关。 The error message I receive in google chrome is:我在谷歌浏览器中收到的错误消息是:

zone-evergreen.js:2845 XHR failed loading: POST "https://www.aldrune.com/wiki1/api/timestamp/". zone-evergreen.js:2845 XHR 加载失败:发布“https://www.aldrune.com/wiki1/api/timestamp/”。

This is the information we have about that:这是我们掌握的相关信息:

  1. The HTTP Request is being cancelled after it is constructed by either the browser or the SPA (Below information from the chrome network tab) HTTP 请求在由浏览器或 SPA 构造后被取消(以下信息来自 chrome 网络选项卡) 在此处输入图像描述 在此处输入图像描述

  2. Restarting the HTTP Request in the Network Tab in chrome gives back a correct response from the backend, proving that the HTTP Request object was constructed correctly在 Chrome 的网络选项卡中重新启动 HTTP 请求会从后端返回正确的响应,证明 HTTP 请求 object 构造正确在此处输入图像描述

  3. The backend is working correctly (Based on 2. and that I can send HTTP Requests via postman successfully)后端工作正常(基于 2. 并且我可以通过 postman 成功发送 HTTP 请求)

  4. It can't be CORS related, as both SPA and my Backend are served from the same HTTP Server (Apache2) .它不能与 CORS 相关,因为 SPA 和我的后端都是由同一个 HTTP Server (Apache2)提供的。 Even if that weren't enough, Django is currently configured to allow all origins.即使这还不够,Django 当前配置为允许所有来源。

Other questions with this issue had unintentional page-reloads as their cause, which interrupted the AJAX Request.与此问题有关的其他问题的原因是无意的页面重新加载,这中断了 AJAX 请求。 But nothing in my component should trigger a page reload when the request is created via createTimestamp() .但是当通过createTimestamp()创建请求时,我的组件中的任何内容都不应触发页面重新加载。 The component literally takes the 2 input DOM elements required from the HTML and builds the object that is to be sent itself.该组件从字面上获取 HTML 所需的 2 个输入 DOM 元素,并构建要自行发送的 object。 No form submission involved.不涉及表单提交。

//session-audio.component.html
...
            <!-- Timestamp Create Form -->
            <div [ngClass]="{'d-none': !timestampCreateState, 'row my-1': timestampCreateState}">
                <input type="text" name="time" #timestampTimeInput />
                <input type="text" name="title" #timestampNameInput />
                <div>
                    <i class="icon hover-red fa fa-1-5x fa-times mx-1" (click)="cancelTimestampCreateState()"></i>
                    <i class="icon hover-green fa fa-1-5x fa-check mx-1" (click)="createTimestamp(timestampTimeInput, timestampNameInput)"></i>
                </div>
            </div>
...
//session-audio.component.ts
export class SessionAudioComponent implements OnInit {
...
  createTimestamp(timestampTimeInput: any, timestampNameInput: any){
    this.timestamp_model.time = this.stringToTime(timestampTimeInput.value);
    this.timestamp_model.name = timestampNameInput.value;
    //session_audio is set during initialization of this.timestamp_model

    this.timestampService.createTimestamp(this.timestamp_model).subscribe(timestamp => {
      this.timestamps.unshift(timestamp);
      this.timestampCreateState = false;
    }, error => console.log(error)).unsubscribe();
  }

}

My best guess is that it's something with the component, but what?我最好的猜测是它与组件有关,但是什么?

The error is indeed caused by the request being interrupted, in this case by the observable being unsubscribed from before it can even finish making the request to the backend.该错误确实是由请求被中断引起的,在这种情况下是由于 observable 在它甚至可以完成向后端发出请求之前被取消订阅。 The issue happens in the createTimestamp() function of my componen.问题发生在我的组件的createTimestamp() function 中。 I left out the callback-functions in subscribe to emphasize my point::我在订阅中省略了回调函数以强调我的观点::

 this.timestampService.createTimestamp(this.timestamp_model).subscribe(...).unsubscribe();

The lesson:课程:

Do not unsubscribe from an observable immediately after subscribing to it .不要在订阅后立即取消订阅 observable That will interrupt your call.打断你的电话。

If you want a single use Observable that is unsubscribed from after you get the first value, use the default method that is recommended everywhere: use the rxjs pipe method with the first() operator.如果您想要在获得第一个值后取消订阅的单次使用 Observable,请使用随处推荐的默认方法:将 rxjs pipe方法与first()运算符一起使用。

  createTimestamp(timestampTimeInput: any, timestampNameInput: any){
    this.timestamp_model.time = this.stringToTime(timestampTimeInput.value);
    this.timestamp_model.name = timestampNameInput.value;
    //session_audio is set during initialization of this.timestamp_model

    this.timestampService.createTimestamp(this.timestamp_model).pipe(first()).subscribe(timestamp => {
      this.timestamps.unshift(timestamp);
      this.timestampCreateState = false;
    }, error => console.log(error));
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM