【问题标题】:Angular 5 Http POST request turns to OPTIONS and returns 404Angular 5 Http POST 请求转为 OPTIONS 并返回 404
【发布时间】:2018-10-10 04:02:27
【问题描述】:

使用:

import { HttpClient, HttpHeaders } from '@angular/common/http';

const httpOptions = {
    headers: new HttpHeaders({
        'Content-Type: ['application/json']
        })
    }

@Injectable()
export class MyService {
    constructor (private http: HttpClient) {}
    private myUrl = 'http://localhost:3000/my-service';
    private postBody = 
    `
    [
     { "a": ["complex"],
       "serialized": "data",
       "set": [],
      },{
       "in": "json",
       "format": []
      }
    ]
    `;

    getData(): Observable<ExpectedResponseType> {
        return this.http.post<ExpectedResponseType>(this.myUrl, this.postBody, httpOptions);
    }
}

当我订阅此服务时,浏览器会向 localhost:3000/my-service 发送预检 OPTIONS 请求,该请求返回 404。如果我从请求中删除 httpOptions,它会成功发布我想要但未设置的正文Content-Typeapplication/json,因此服务器返回 500。

如何在 Angular 5 中发送内容类型为 json 的 POST 请求?服务器提供 Postman 的预期结果,但我不确定如何说服 Angular 简单地发送带有我想要的标头的 POST。

【问题讨论】:

    标签: angular http


    【解决方案1】:

    OPTIONS 请求不是 Angular 问题,而是浏览器问题。

    当浏览器发出跨域请求时,它会(对于大多数请求,取决于您请求的内容和使用的方法)首先执行 OPTIONS 请求。

    OPTIONS 请求的目的是检查服务器是否允许您的客户端(浏览器)向它发出请求。这是由服务器 CORS 响应标头确定的。如果 OPTIONS 请求失败,则浏览器知道它是不允许的,因此不会费心发出您想要的实际请求。

    这仅由浏览器强制执行,因此 POSTMAN 可以正常工作。

    请将 CORS 标头添加到您的服务器响应中,并确保您的服务器支持 OPTIONS 请求。

    https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin

    https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

    如果您真的不介意 CORS,请将请求发送到同一个域并让您的网络服务器重写 URL。请注意,您还必须在产品服务器中重复重写逻辑。

    【讨论】:

      【解决方案2】:

      这是由于 CORS 限制(跨域资源共享)而发生的。浏览器不允许请求发送到具有不同主机/端口组合的服务器,除非服务器允许。这是出于安全原因(例如,为了防止 XSRF 攻击)。有几种方法可以解决这个问题:

      • 更新服务器以添加允许来自任何来源或给定来源的 CORS 的标头(如果您想允许其他服务器访问您的 API,这就是您在真实环境中执行此操作的方式)。互联网上有很多关于这方面的资源,这是一个很好的例子:http://restlet.com/company/blog/2016/09/27/how-to-fix-cors-problems/
      • 在您的客户端和服务器之间添加一个代理来解决该问题(根据我的经验,这是偶然的,但像 ionic 这样的一些框架有一个有效的代理)。
      • 有些浏览器比其他浏览器不那么严格,在这种情况下最严格的 chrome 有一个标志,允许您在开发期间绕过 CORS 检查(请谨慎使用,启用此标志时不要访问真实网站,因为它可能使您容易受到 XSRF 攻击)。标志是:--disable-web-security --user-data-dir=SOME_FOLDER

      【讨论】:

      • 即使启用了--disable-web-security,请求仍然转向OPTIONS
      • 您确定您启用了 --disable-web-security 吗?您可能需要关闭所有正在运行的 chrome 浏览器(我宁愿完全终止该进程)并尝试。当我在顶部收到警告“您正在使用不受支持的命令行标志...”时,我知道它已启用。
      • 是的,我得到了标志,但行为是一样的。
      • 标头定义有问题,您可以尝试使用它吗(即使它是 HttpClient afaik 中的默认设置): headers: new HttpHeaders({ 'Content-Type': 'application/json ' }) 此外,您能否尝试重新格式化您的 postBody 以使其采用 javscript 对象格式而不是字符串。例如:private postBody = [ { a: ["complex"], serialized: "data", set: [], },{ in: "json", format: [] } ];错误提示 CORS,但我只是说您的标头中有一个数组,这可能是为什么?
      【解决方案3】:

      我为开发找到的最佳解决方案是使用 Angular 代理。

      const proxy = [
        {
          context: '/api',
          target: 'http://localhost:3000',
          pathRewrite: {'^/api' : ''}
        }
      ];
      module.exports = proxy;
      
      
      ng serve --proxy-config proxy.config.js --open
      

      这会将/api 下同一域上的所有请求重新路由回我的服务器,因此我无需担心配置我的服务器来替换ng serve

      【讨论】:

        猜你喜欢
        • 2017-04-19
        • 2015-07-19
        • 1970-01-01
        • 1970-01-01
        • 2018-08-04
        • 1970-01-01
        • 2012-11-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多