267

テンプレートファイルを配信するアセットホストが別のドメインにあるクロスオリジンリソースと通信するようにAngularJSをセットアップしようとしています。したがって、Angularが実行するXHRリクエストはクロスドメインである必要があります。これを機能させるためにHTTPリクエスト用に適切なCORSヘッダーをサーバーに追加しましたが、機能していないようです。問題は、ブラウザ(chrome)でHTTPリクエストを検査すると、アセットファイルに送信されるリクエストがOPTIONSリクエスト(GETリクエストである必要があります)であるということです。

これがAngularJSのバグなのか、何かを構成する必要があるのか​​わかりません。私が理解していることから、XHRラッパーはOPTIONS HTTPリクエストを作成できないため、ブラウザはGETリクエストを実行する前に、最初にアセットをダウンロードすることが「許可」されているかどうかを判断しようとしているようです。この場合、アセットホストでもCORSヘッダー(Access-Control-Allow-Origin: http://asset.host。。。 )を設定する必要がありますか?

4

14 に答える 14

228

OPTIONSリクエストは決してAngularJSのバグではありません。これは、クロスオリジンリソースシェアリング標準がブラウザーの動作を義務付ける方法です。次のドキュメントを参照してください:https ://developer.mozilla.org/en-US/docs/HTTP_access_control 、「概要」セクションに次のように記載されています。

クロスオリジンリソースシェアリング標準は、サーバーがWebブラウザーを使用してその情報を読み取ることを許可されているオリジンのセットを記述できるようにする新しいHTTPヘッダーを追加することによって機能します。さらに、ユーザーデータに副作用を引き起こす可能性のあるHTTPリクエストメソッドの場合(特に、GET以外のHTTPメソッドの場合、または特定のMIMEタイプでのPOSTの使用の場合)。この仕様では、ブラウザがリクエストを「プリフライト」し、HTTP OPTIONSリクエストヘッダーを使用してサーバーからサポートされているメソッドを要求し、サーバーから「承認」されると、実際のHTTPリクエストメソッドを使用して実際のリクエストを送信することを義務付けています。サーバーは、「資格情報」(CookieとHTTP認証データを含む)を要求とともに送信する必要があるかどうかをクライアントに通知することもできます。

セットアップはサーバー自体とサポートするHTTP動詞によって異なるため、すべてのWWWサーバーで機能する汎用ソリューションを提供することは非常に困難です。サーバーから送信する必要のある正確なヘッダーの詳細が記載されているこの優れた記事(http://www.html5rocks.com/en/tutorials/cors/ )を確認することをお勧めします。

于 2012-08-24T15:23:56.413 に答える
70

Angular 1.2.0rc1 +の場合、resourceUrlWhitelistを追加する必要があります。

1.2:リリースバージョンでは、escapeForRegexp関数が追加されたため、文字列をエスケープする必要がなくなりました。URLを直接追加できます

'http://sub*.assets.example.com/**' 

サブフォルダには必ず**を追加してください。1.2で動作するjsbinは次のとおりです。http: //jsbin.com/olavok/145/edit


1.2.0rc:まだrcバージョンを使用している場合、Angular1.2.0rc1のソリューションは次のようになります。

.config(['$sceDelegateProvider', function($sceDelegateProvider) {
     $sceDelegateProvider.resourceUrlWhitelist(['self', /^https?:\/\/(cdn\.)?yourdomain.com/]);
 }])

これは、1.2.0rc1で機能するjsbinの例です。http: //jsbin.com/olavok/144/edit


1.2より前:古いバージョン(http://better-inter.net/enabling-cors-in-angular-js/を参照)の場合、構成に次の2行を追加する必要があります。

$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];

1.2より前のバージョンで機能するjsbinの例を次に示します。http: //jsbin.com/olavok/11/edit

于 2013-05-15T16:40:51.857 に答える
62

注:最新バージョンのAngularで動作するかどうかはわかりません。

オリジナル:

OPTIONSリクエストをオーバーライドすることもできます(Chromeでのみテストされています)。

app.config(['$httpProvider', function ($httpProvider) {
  //Reset headers to avoid OPTIONS request (aka preflight)
  $httpProvider.defaults.headers.common = {};
  $httpProvider.defaults.headers.post = {};
  $httpProvider.defaults.headers.put = {};
  $httpProvider.defaults.headers.patch = {};
}]);
于 2013-12-11T10:07:42.710 に答える
34

サービスは、OPTIONS次のようなヘッダーを使用してリクエストに応答する必要があります。

Access-Control-Allow-Origin: [the same origin from the request]
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: [the same ACCESS-CONTROL-REQUEST-HEADERS from request]

ここに良いドキュメントがあります:http ://www.html5rocks.com/en/tutorials/cors/#toc-adding-cors-support-to-the-server

于 2013-04-21T14:51:24.653 に答える
20

同じ文書によると

単純なリクエスト(上記で説明)とは異なり、「プリフライト」リクエストは、実際のリクエストを安全に送信できるかどうかを判断するために、最初にHTTPOPTIONSリクエストヘッダーを他のドメインのリソースに送信します。クロスサイトリクエストは、ユーザーデータに影響を与える可能性があるため、このようにプリフライトされます。特に、次の場合、リクエストはプリフライトされます。

GETまたはPOST以外のメソッドを使用します。また、POSTを使用してapplication / x-www-form-urlencoded、multipart / form-data、text / plain以外のContent-Typeでリクエストデータを送信する場合、たとえば、POSTリクエストがXMLペイロードをサーバーに送信する場合application/xmlまたはtext/xmlを使用すると、リクエストがプリフライトされます。

リクエストにカスタムヘッダーを設定します(たとえば、リクエストはX-PINGOTHERなどのヘッダーを使用します)

元のリクエストがカスタムヘッダーのないGetである場合、ブラウザは現在行っているオプションリクエストを作成しないでください。問題は、Optionsリクエストを強制するヘッダーX-Requested-Withを生成することです。このヘッダーを削除する方法については、 https://github.com/angular/angular.js/pull/1454を参照してください

于 2013-03-09T02:45:37.380 に答える
10

これで私の問題は解決しました:

$http.defaults.headers.post["Content-Type"] = "text/plain";
于 2016-02-25T12:59:46.653 に答える
10

nodeJSサーバーを使用している場合は、このライブラリを使用できます。私にとっては問題なく機能しましたhttps://github.com/expressjs/cors

var express = require('express')
  , cors = require('cors')
  , app = express();

app.use(cors());

そして、あなたがすることができた後npm update

于 2016-10-14T17:11:17.603 に答える
5

これがASP.NETでこの問題を修正した方法です

  • まず、nugetパッケージMicrosoft.AspNet.WebApi.Corsを追加する必要があります

  • 次に、ファイルApp_Start\WebApiConfig.csを変更します

    public static class WebApiConfig    
    {
       public static void Register(HttpConfiguration config)
       {
          config.EnableCors();
    
          ...
       }    
    }
    
  • この属性をコントローラークラスに追加します

    [EnableCors(origins: "*", headers: "*", methods: "*")]
    public class MyController : ApiController
    {  
        [AcceptVerbs("POST")]
        public IHttpActionResult Post([FromBody]YourDataType data)
        {
             ...
             return Ok(result);
        }
    }
    
  • このようにして、jsonをアクションに送信することができました

    $http({
            method: 'POST',
            data: JSON.stringify(data),
            url: 'actionurl',
            headers: {
                'Content-Type': 'application/json; charset=UTF-8'
            }
        }).then(...)
    

参照: ASP.NET WebAPI2でのクロスオリジンリクエストの有効化

于 2016-06-23T14:45:31.720 に答える
2

どういうわけか変更して修正しました

<add name="Access-Control-Allow-Headers" 
     value="Origin, X-Requested-With, Content-Type, Accept, Authorization" 
     />

<add name="Access-Control-Allow-Headers" 
     value="Origin, Content-Type, Accept, Authorization" 
     />
于 2016-03-14T15:21:49.427 に答える
0

pkozlowskiのコメントで完全に説明されています。AngularJS1.2.6とASP.NETWebApiで機能するソリューションがありましたが、AngularJSを1.3.3にアップグレードすると、リクエストが失敗しました。

  • Web Apiサーバーの解決策は、構成メソッドの最初にOPTIONS要求の処理を追加することでした(詳細はこのブログ投稿を参照してください)。

    app.Use(async (context, next) =>
    {
        IOwinRequest req = context.Request;
        IOwinResponse res = context.Response;
        if (req.Path.StartsWithSegments(new PathString("/Token")))
        {
            var origin = req.Headers.Get("Origin");
            if (!string.IsNullOrEmpty(origin))
            {
                res.Headers.Set("Access-Control-Allow-Origin", origin);
            }
            if (req.Method == "OPTIONS")
            {
                res.StatusCode = 200;
                res.Headers.AppendCommaSeparatedValues("Access-Control-Allow-Methods", "GET", "POST");
                res.Headers.AppendCommaSeparatedValues("Access-Control-Allow-Headers", "authorization", "content-type");
                return;
            }
        }
        await next();
    });
    
于 2015-02-27T08:38:57.557 に答える
0

ジャージーをRESTAPIに使用している場合は、次のように実行できます

Webサービスの実装を変更する必要はありません。

ジャージー2.xについて説明します

1)まず、以下に示すようにResponseFilterを追加します

import java.io.IOException;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;

public class CorsResponseFilter implements ContainerResponseFilter {

@Override
public void filter(ContainerRequestContext requestContext,   ContainerResponseContext responseContext)
    throws IOException {
        responseContext.getHeaders().add("Access-Control-Allow-Origin","*");
        responseContext.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");

  }
}

2)次に、web.xmlで、サーブレットサーブレット宣言に以下を追加します。

    <init-param>
        <param-name>jersey.config.server.provider.classnames</param-name>
        <param-value>YOUR PACKAGE.CorsResponseFilter</param-value>
    </init-param>
于 2015-05-26T06:29:25.870 に答える
0

私はこの問題を修正しようとするのをあきらめました。

私のIISweb.configには関連する" Access-Control-Allow-Methods"が含まれており、Angularコードに構成設定を追加することを試みましたが、ChromeにクロスドメインJSON Webサービスを呼び出させようとして数時間燃焼した後、惨めに諦めました。

最後に、ダムASP.NetハンドラーWebページを追加し、それを取得てJSON Webサービスを呼び出し、結果を返しました。2分で稼働しました。

これが私が使用したコードです:

public class LoadJSONData : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "text/plain";

        string URL = "......";

        using (var client = new HttpClient())
        {
            // New code:
            client.BaseAddress = new Uri(URL);
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            client.DefaultRequestHeaders.Add("Authorization", "Basic AUTHORIZATION_STRING");

            HttpResponseMessage response = client.GetAsync(URL).Result;
            if (response.IsSuccessStatusCode)
            {
                var content = response.Content.ReadAsStringAsync().Result;
                context.Response.Write("Success: " + content);
            }
            else
            {
                context.Response.Write(response.StatusCode + " : Message - " + response.ReasonPhrase);
            }
        }
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

そして私のAngularコントローラーでは...

$http.get("/Handlers/LoadJSONData.ashx")
   .success(function (data) {
      ....
   });

これを行うためのより簡単で一般的な方法があると確信していますが、人生は短すぎます...

これは私のために働きました、そして私は今通常の仕事をすることに取り掛かることができます!!

于 2015-11-11T12:42:33.493 に答える
0

IIS MVC 5 / Angular CLI(はい、あなたの問題はAngular JSにあることをよく知っています)プロジェクトの場合、APIを使用して次のことを行いました。

<system.webServer>ノードの下のweb.config

    <staticContent>
      <remove fileExtension=".woff2" />
      <mimeMap fileExtension=".woff2" mimeType="font/woff2" />
    </staticContent>
    <httpProtocol>
      <customHeaders>
        <clear />
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Headers" value="Content-Type, atv2" />
        <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS"/>
      </customHeaders>
    </httpProtocol>

global.asax.cs

protected void Application_BeginRequest() {
  if (Request.Headers.AllKeys.Contains("Origin", StringComparer.OrdinalIgnoreCase) && Request.HttpMethod == "OPTIONS") {
    Response.Flush();
    Response.End();
  }
}

これで、他のすべての実行を行うことなく、MVCとWebAPIの両方の問題が修正されるはずです。次に、Angular CLIプロジェクトでHttpInterceptorを作成し、関連するヘッダー情報を自動的に追加しました。これが同様の状況で誰かを助けることを願っています。

于 2018-11-01T20:52:31.217 に答える
0

パーティーに少し遅れて、

APIとしてAngular7(または5/6/7)とPHPを使用しているのにこのエラーが発生する場合は、エンドポイント(PHP API)に次のヘッダーオプションを追加してみてください。

 header("Access-Control-Allow-Origin: *");
 header("Access-Control-Allow-Methods: PUT, GET, POST, PUT, OPTIONS, DELETE, PATCH");
 header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization");

:必要なのは。だけですAccess-Control-Allow-Methods。ただし、 Angular AppがAPIと適切に通信するには、これらすべてを適切に設定する必要があるため、ここに他の2つとAccess-Control-Allow-Originを貼り付けています。Access-Control-Allow-Headers

これが誰かを助けることを願っています。

乾杯。

于 2019-01-24T15:44:52.747 に答える