仅在 Chrome 中且仅在服务器上获取对 Web API 的 CORS 请求的 404

Posted

技术标签:

【中文标题】仅在 Chrome 中且仅在服务器上获取对 Web API 的 CORS 请求的 404【英文标题】:Getting 404 for CORS request to Web API only in Chrome and only on server 【发布时间】:2018-06-24 07:10:41 【问题描述】:

我正在尝试将数据从网站发布到具有相同域名但端口号不同的同一服务器上的 Web API 端点。它适用于本地和我们的测试服务器上的 IE11,但 Chrome 仅适用于本地。在测试服务器上,我收到 404 错误。据我所知,它符合“简单”请求,但是 404 错误显示 HTTP 方法是“OPTIONS”,因此它必须发出预检请求并失败。

zone.js:2933 OPTIONS http://example.com:8001/api/search/quickSearch?v=1.35.2664 404 (Not Found)
scheduleTask @ zone.js:2933
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.scheduleTask @ zone.js:411
onScheduleTask @ zone.js:301
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.scheduleTask @ zone.js:405
webpackJsonp.../../../../zone.js/dist/zone.js.Zone.scheduleTask @ zone.js:236
webpackJsonp.../../../../zone.js/dist/zone.js.Zone.scheduleMacroTask @ zone.js:259
(anonymous) @ zone.js:2966
proto.(anonymous function) @ zone.js:1366
(anonymous) @ angular.js:12587
sendReq @ angular.js:12332
serverRequest @ angular.js:12084
processQueue @ angular.js:16832
(anonymous) @ angular.js:16876
$digest @ angular.js:17971
(anonymous) @ static.js:1502
schedulerFn @ core.js:4351
webpackJsonp.../../../../rxjs/_esm5/Subscriber.js.SafeSubscriber.__tryOrUnsub @ Subscriber.js:240
webpackJsonp.../../../../rxjs/_esm5/Subscriber.js.SafeSubscriber.next @ Subscriber.js:187
webpackJsonp.../../../../rxjs/_esm5/Subscriber.js.Subscriber._next @ Subscriber.js:128
webpackJsonp.../../../../rxjs/_esm5/Subscriber.js.Subscriber.next @ Subscriber.js:92
webpackJsonp.../../../../rxjs/_esm5/Subject.js.Subject.next @ Subject.js:56
webpackJsonp.../../../core/esm5/core.js.EventEmitter.emit @ core.js:4319
checkStable @ core.js:4718
onLeave @ core.js:4797
onInvokeTask @ core.js:4747
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:424
webpackJsonp.../../../../zone.js/dist/zone.js.Zone.runTask @ zone.js:192
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneTask.invokeTask @ zone.js:499
ZoneTask.invoke @ zone.js:488
timer @ zone.js:2040
setTimeout (async)
scheduleTask @ zone.js:2056
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.scheduleTask @ zone.js:411
onScheduleTask @ zone.js:301
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.scheduleTask @ zone.js:405
webpackJsonp.../../../../zone.js/dist/zone.js.Zone.scheduleTask @ zone.js:236
webpackJsonp.../../../../zone.js/dist/zone.js.Zone.scheduleMacroTask @ zone.js:259
(anonymous) @ zone.js:2072
proto.(anonymous function) @ zone.js:1366
setTimeout @ lodash.js:6663
timerExpired @ lodash.js:10388
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:425
onInvokeTask @ core.js:4744
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:424
webpackJsonp.../../../../zone.js/dist/zone.js.Zone.runTask @ zone.js:192
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneTask.invokeTask @ zone.js:499
ZoneTask.invoke @ zone.js:488
timer @ zone.js:2040
setTimeout (async)
scheduleTask @ zone.js:2056
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.scheduleTask @ zone.js:411
onScheduleTask @ zone.js:301
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.scheduleTask @ zone.js:405
webpackJsonp.../../../../zone.js/dist/zone.js.Zone.scheduleTask @ zone.js:236
webpackJsonp.../../../../zone.js/dist/zone.js.Zone.scheduleMacroTask @ zone.js:259
(anonymous) @ zone.js:2072
proto.(anonymous function) @ zone.js:1366
setTimeout @ lodash.js:6663
leadingEdge @ lodash.js:10358
debounced @ lodash.js:10425
fn @ VM445:4
$eval @ angular.js:18161
(anonymous) @ angular.js:25998
(anonymous) @ angular.js:28813
forEach @ angular.js:403
$$writeModelToScope @ angular.js:28811
writeToModelIfNeeded @ angular.js:28804
(anonymous) @ angular.js:28798
validationDone @ angular.js:28723
processAsyncValidators @ angular.js:28706
$$runValidators @ angular.js:28650
$$parseAndValidate @ angular.js:28791
$commitViewValue @ angular.js:28757
(anonymous) @ angular.js:28898
$eval @ angular.js:18161
$apply @ angular.js:18261
$$debounceViewValueCommit @ angular.js:28897
$setViewValue @ angular.js:28875
listener @ angular.js:24822
dispatch @ jquery.js:4737
elemData.handle @ jquery.js:4549
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:425
onInvokeTask @ core.js:4744
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:424
webpackJsonp.../../../../zone.js/dist/zone.js.Zone.runTask @ zone.js:192
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneTask.invokeTask @ zone.js:499
invokeTask @ zone.js:1540
globalZoneAwareCallback @ zone.js:1566
(index):1 Failed to load http://example.com:8001/api/search/quickSearch?v=1.35.2664: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://example.com' is therefore not allowed access. The response had HTTP status code 404.

这是启用 CORS 请求的 Global.asax 的样子:

    protected void Application_BeginRequest(object sender, EventArgs e)
    
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", ConfigurationManager.AppSettings["RootUri"].TrimEnd('/'));
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, HEAD, PUT, DELETE, OPTIONS");
        HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "30");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Accept, Accept-CH, Accept-Charset, Accept-Datetime, Accept-Encoding, Accept-Ext, Accept-Features, Accept-Language, Accept-Params, Accept-Ranges, Access-Control-Allow-Credentials, Access-Control-Allow-Headers, Access-Control-Allow-Methods, Access-Control-Allow-Origin, Access-Control-Expose-Headers, Access-Control-Max-Age, Access-Control-Request-Headers, Access-Control-Request-Method, Age, Allow, Alternates, Authentication-Info, Authorization, C-Ext, C-Man, C-Opt, C-PEP, C-PEP-Info, CONNECT, Cache-Control, Compliance, Connection, Content-Base, Content-Disposition, Content-Encoding, Content-ID, Content-Language, Content-Length, Content-Location, Content-MD5, Content-Range, Content-Script-Type, Content-Security-Policy, Content-Style-Type, Content-Transfer-Encoding, Content-Type, Content-Version, Cookie, Cost, DAV, DELETE, DNT, DPR, Date, Default-Style, Delta-Base, Depth, Derived-From, Destination, Differential-ID, Digest, ETag, Expect, Expires, Ext, From, GET, GetProfile, HEAD, HTTP-date, Host, IM, If, If-Match, If-Modified-Since, If-None-Match, If-Range, If-Unmodified-Since, Keep-Alive, Label, Last-Event-ID, Last-Modified, Link, Location, Lock-Token, MIME-Version, Man, Max-Forwards, Media-Range, Message-ID, Meter, Negotiate, Non-Compliance, OPTION, OPTIONS, OWS, Opt, Optional, Ordering-Type, Origin, Overwrite, P3P, PEP, PICS-Label, POST, PUT, Pep-Info, Permanent, Position, Pragma, ProfileObject, Protocol, Protocol-Query, Protocol-Request, Proxy-Authenticate, Proxy-Authentication-Info, Proxy-Authorization, Proxy-Features, Proxy-Instruction, Public, RWS, Range, Referer, Refresh, Resolution-Hint, Resolver-Location, Retry-After, Safe, Sec-Websocket-Extensions, Sec-Websocket-Key, Sec-Websocket-Origin, Sec-Websocket-Protocol, Sec-Websocket-Version, Security-Scheme, Server, Set-Cookie, Set-Cookie2, SetProfile, SoapAction, Status, Status-URI, Strict-Transport-Security, SubOK, Subst, Surrogate-Capability, Surrogate-Control, TCN, TE, TRACE, Timeout, Title, Trailer, Transfer-Encoding, UA-Color, UA-Media, UA-Pixels, UA-Resolution, UA-Windowpixels, URI, Upgrade, User-Agent, Variant-Vary, Vary, Version, Via, Viewport-Width, WWW-Authenticate, Want-Digest, Warning, Width, X-Content-Duration, X-Content-Security-Policy, X-Content-Type-Options, X-CustomHeader, X-DNSPrefetch-Control, X-Forwarded-For, X-Forwarded-Port, X-Forwarded-Proto, X-Frame-Options, X-Modified, X-OTHER, X-PING, X-PINGOTHER, X-Powered-By, X-Requested-With");

        // If a preflight request, end it so we don't fetch data.
        if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
        
            HttpContext.Current.Response.End();
        
    

为什么会出现 404,我该如何解决?

【问题讨论】:

您可能还想包含一个代码 sn-p 显示您的前端 javascript 代码中发起请求的部分。如果它实际上符合一个简单的请求,您的浏览器将不会发送该预检选项。不管怎样,真正的问题似乎是发送请求的服务器配置错误,无法正确响应 404 的 OPTIONS 请求,并且问题中的 Global.asax 代码 sn-p 似乎没有解决该问题. 【参考方案1】:

Chrome 和 Safari 也可能对非 GET 方法(例如 POST)发出预检 OPTIONS 请求。

我不确定ConfigurationManager.AppSettings["RootUri"].TrimEnd('/') 解析为什么 - ACAO 响应标头必须是星号或(您似乎正在尝试这样做)一个 FQDN,包括方案和端口(如果端口不是) t 80 或 443) - 所以在你的情况下,它必须有一个精确的值“http://example.com:8001”。简单地镜像回 Origin 请求标头的值(将具有该值)要简单得多。

您可以发布请求和响应标头吗?

【讨论】:

我有类似的问题,我的应用程序是使用 Angular 7 构建的。我正在对 BPMS 服务器进行 ajax 调用,该服务器在 IE 中运行良好,但在 Chrome 中出现 CORS 错误。但是,当我将 ajax url 复制到 Chrome 浏览器时,我拥有所有数据。有人可以帮忙吗?

以上是关于仅在 Chrome 中且仅在服务器上获取对 Web API 的 CORS 请求的 404的主要内容,如果未能解决你的问题,请参考以下文章

Angular http post 仅在 Chrome 中在服务器上返回 403 错误

获取 ERROR ERROR [object Object] 但仅在 ios 上。在电脑上工作正常

Angular 应用程序仅在 chrome 中出现 CORS 错误

Javascript .Focus 导致 safari 8.1.3 仅在 iPad 上崩溃

仅在 Chrome 上出现 iframe 高度问题

使用带有 Web 平台安装程序 API 的 Powershell 仅在 64 位机器上获取 x86 安装程序