it-swarm.com.de

AngularJS führt eine HTTP-Anforderung von OPTIONS für eine Ursprungsquelle aus

Ich versuche, AngularJS so einzurichten, dass es mit einer Cross-Origin-Ressource kommuniziert, bei der sich der Asset-Host, der meine Vorlagendateien bereitstellt, auf einer anderen Domäne befindet. Daher muss die XHR-Anforderung, die Winkel ausführt, domänenübergreifend sein. Ich habe meinem Server den entsprechenden CORS-Header für die HTTP-Anforderung hinzugefügt, damit dies funktioniert, aber es scheint nicht zu funktionieren. Das Problem ist, dass, wenn ich die HTTP-Anforderungen in meinem Browser (Chrome) prüfe, die an die Asset-Datei gesendete Anforderung eine OPTIONS-Anforderung ist (es sollte eine GET-Anforderung sein).

Ich bin nicht sicher, ob dies ein Fehler in AngularJS ist oder ob ich etwas konfigurieren muss. Soweit ich weiß, kann der XHR-Wrapper keine HTTP-Anfrage von OPTIONS machen. Es sieht also so aus, als würde der Browser herausfinden, ob "erlaubt" ist, das Asset zuerst herunterzuladen, bevor es die GET-Anfrage ausführt. Wenn dies der Fall ist, muss ich den CORS-Header (Access-Control-Allow-Origin: http://asset.Host .. .) Auch mit dem Asset-Host festlegen?

253
matsko

Die OPTIONS-Anfrage ist keinesfalls ein AngularJS-Fehler, so dass der Cross-Origin Resource Sharing-Standard Browser dazu verhält, sich zu verhalten. Bitte beachten Sie dieses Dokument: https://developer.mozilla.org/en-US/docs/HTTP_access_control , wobei im Abschnitt "Übersicht" Folgendes angegeben ist:

Der Cross-Origin-Standard für die gemeinsame Nutzung von Ressourcen funktioniert durch Hinzufügen von neuem HTTP Kopfzeilen, die es Servern ermöglichen, die Ursprungsmenge zu beschreiben, die .__ ist. diese Informationen mit einem Webbrowser lesen dürfen. Zusätzlich, für HTTP-Anforderungsmethoden, die Nebenwirkungen auf Benutzerdaten verursachen können (in insbesondere; für andere HTTP-Methoden als GET oder für die Verwendung von POST mit bestimmten MIME-Typen). Die Spezifikation verlangt, dass Browser "Preflight" der Anforderung, um unterstützte Methoden vom Server abzurufen mit einem HTTP-OPTIONS-Anforderungsheader und dann bei "Genehmigung" von Der Server sendet die tatsächliche Anforderung mit der tatsächlichen HTTP-Anforderung Methode. Server können Clients auch darüber informieren, ob "Berechtigungsnachweise" (einschließlich Cookies und HTTP-Authentifizierungsdaten) sollten mit .__ gesendet werden. Anfragen.

Es ist sehr schwierig, eine generische Lösung bereitzustellen, die für alle WWW-Server geeignet ist, da das Setup von Server zu Server und von den zu verwendenden HTTP-Verben abhängt. Ich möchte Sie dazu ermutigen, über diesen hervorragenden Artikel ( http://www.html5rocks.com/de/tutorials/cors/ ) zu lesen, der viel mehr Details zu den genauen Kopfzeilen enthält, die von einem Server gesendet werden müssen.

220

Für Angular 1.2.0rc1 + müssen Sie eine resourceUrlWhitelist hinzufügen.

1.2: Release-Version Sie haben eine escapeForRegexp-Funktion hinzugefügt, damit Sie die Zeichenfolgen nicht mehr übergehen müssen. Sie können die URL einfach direkt hinzufügen 

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

stellen Sie sicher, dass Sie ** für Unterordner hinzufügen. Hier ist ein Arbeitsjsbin für 1.2: http://jsbin.com/olavok/145/edit


1.2.0rc: Wenn Sie sich noch in einer RC-Version befinden, sieht die Lösung Angular 1.2.0rc1 folgendermaßen aus:

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

Hier ist ein Beispiel für jsbin, wo es für 1.2.0rc1 funktioniert: http://jsbin.com/olavok/144/edit


Pre 1.2: Bei älteren Versionen (ref http://better-inter.net/enabling-cors-in-angular-js/ ) müssen Sie der Konfiguration die folgenden 2 Zeilen hinzufügen:

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

Hier ist ein Beispiel von jsbin, in dem es für Versionen vor 1.2 funktioniert: http://jsbin.com/olavok/11/edit

67
JStark

HINWEIS: Nicht sicher, ob es mit der neuesten Version von Angular funktioniert.

ORIGINAL:

Es ist auch möglich, die Anfrage OPTIONS zu überschreiben (wurde nur in Chrome getestet):

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 = {};
}]);
61
user2899845

Ihr Dienst muss eine OPTIONS-Anforderung mit den folgenden Kopfzeilen beantworten:

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]

Hier ist ein gutes Dokument: http://www.html5rocks.com/de/tutorials/cors/#toc-adding-cors-support-to-the-server

34
user2304582

Das gleiche Dokument sagt 

Im Gegensatz zu einfachen Anforderungen (oben beschrieben) senden "Preflight" -Anforderungen zunächst einen HTTP OPTIONS-Anforderungsheader an die Ressource in der anderen Domäne, um festzustellen, ob die tatsächliche Anforderung sicher gesendet werden kann. Standortübergreifende Anforderungen werden so geprüft, da sie Auswirkungen auf die Benutzerdaten haben können. Insbesondere ist eine Anfrage vorab geprüft, wenn:

Es verwendet andere Methoden als GET oder POST. Wenn POST zum Senden von Anfragedaten mit einem anderen Inhaltstyp als application/x-www-form-urlencoded, mehrteiligen/Formulardaten oder Text/plain verwendet wird, z. Wenn die Anforderung POST eine XML-Nutzlast mithilfe von application/xml oder text/xml an den Server sendet, wird die Anforderung als Preflight-Anforderung bezeichnet.

In der Anfrage werden benutzerdefinierte Header festgelegt (z. B. verwendet die Anfrage einen Header wie X-PINGOTHER).

Wenn die ursprüngliche Anforderung Get ohne benutzerdefinierte Kopfzeilen lautet, sollte der Browser keine Optionsanfrage machen, die jetzt ausgeführt wird. Das Problem ist, dass es einen Header X-Requested-With generiert, der die Optionsanforderung erzwingt. Unter https://github.com/angular/angular.js/pull/1454 erfahren Sie, wie Sie diesen Header entfernen

20
Grum Ketema

Dies hat mein Problem behoben:

$http.defaults.headers.post["Content-Type"] = "text/plain";
10
Cem Arguvanlı

Wenn Sie einen nodeJS-Server verwenden, können Sie diese Bibliothek verwenden. Es hat für mich gut funktioniert https://github.com/expressjs/cors

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

app.use(cors());

und nachdem Sie einen npm update machen können.

10
Zakaria.dem

So habe ich dieses Problem in ASP.NET behoben

  • Zuerst sollten Sie das Nuget-Paket Microsoft.AspNet.WebApi.Cors hinzufügen. 

  • Ändern Sie dann die Datei App_Start\WebApiConfig.cs 

    public static class WebApiConfig    
    {
       public static void Register(HttpConfiguration config)
       {
          config.EnableCors();
    
          ...
       }    
    }
    
  • Fügen Sie dieses Attribut Ihrer Controller-Klasse hinzu

    [EnableCors(origins: "*", headers: "*", methods: "*")]
    public class MyController : ApiController
    {  
        [AcceptVerbs("POST")]
        public IHttpActionResult Post([FromBody]YourDataType data)
        {
             ...
             return Ok(result);
        }
    }
    
  • Ich konnte auf diese Weise Json zur Aktion schicken

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

Reference:Aktivieren von Cross-Origin-Anforderungen in ASP.NET Web API 2

4
asfez

Irgendwie habe ich es durch einen Wechsel behoben 

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

zu 

<add name="Access-Control-Allow-Headers" 
     value="Origin, Content-Type, Accept, Authorization" 
     />
2
Ved Prakash

Wenn Sie Jersey für REST - APIs verwenden, können Sie Folgendes tun 

Sie müssen Ihre Webservices-Implementierung nicht ändern.

Ich werde es für Jersey 2.x erklären 

1) Fügen Sie zunächst einen ResponseFilter hinzu, wie unten gezeigt 

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) dann in der web.xml, fügen Sie in der Jersey-Servlet-Deklaration das Folgende hinzu 

    <init-param>
        <param-name>jersey.config.server.provider.classnames</param-name>
        <param-value>YOUR PACKAGE.CorsResponseFilter</param-value>
    </init-param>
0
nondescript

Etwas spät zur Party,

Wenn Sie Angular 7 (oder 5/6/7) und PHP als API verwenden und dieser Fehler weiterhin angezeigt wird, fügen Sie dem Endpunkt (PHP-API) die folgenden Header-Optionen hinzu.

 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");

Hinweis : Was benötigt wird, ist Access-Control-Allow-Methods. Ich füge hier jedoch noch zwei weitere Access-Control-Allow-Origin und Access-Control-Allow-Headers ein, einfach weil Sie alle Einstellungen richtig vornehmen müssen, damit Angular App richtig mit Ihrer API kommuniziert.

Hoffe das hilft jemandem.

Prost.

0
Anjana Silva

Ich habe es aufgegeben, dieses Problem zu beheben.

Meine IIS web.config enthielt das relevante "Access-Control-Allow-Methods". Ich experimentierte mit dem Hinzufügen von Konfigurationseinstellungen zu meinem Angular-Code, aber nachdem ich einige Stunden gebrannt hatte, dass ich versucht habe, mit Chrome einen domänenübergreifenden JSON-Webdienst aufzurufen, habe ich dies gegeben kläglich auf.

Am Ende fügte ich eine dumme ASP.Net-Handler-Webseite hinzu, bekam that , um meinen JSON-Webdienst aufzurufen, und gab die Ergebnisse zurück. Es war in 2 Minuten einsatzbereit.

Hier ist der Code, den ich verwendet habe:

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;
        }
    }
}

Und in meinem Angular Controller ...

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

Ich bin sicher, es gibt eine einfachere/allgemeinere Art, dies zu tun, aber das Leben ist zu kurz ... 

Das hat für mich funktioniert, und ich kann jetzt mit der normalen Arbeit fortfahren !!

0
Mike Gledhill

In pkozlowskis Kommentar perfekt beschrieben. Ich hatte eine funktionierende Lösung mit AngularJS 1.2.6 und ASP.NET Web Api, aber als ich AngularJS auf 1.3.3 aufgerüstet hatte, schlugen Anforderungen fehl.

  • Die Lösung für den Web Api-Server bestand darin, die OPTIONS-Anforderungen am Anfang der Konfigurationsmethode zu behandeln (weitere Informationen in diesem Blogbeitrag ):

    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();
    });
    
0
Jiří Kavulák

Bei einem IIS MVC 5/Angular-CLI-Projekt (Ja, ich bin mir sehr wohl bewusst, dass Ihr Problem mit Angular JS besteht) mit API habe ich Folgendes getan:

web.config unter <system.webServer>-Knoten

    <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();
  }
}

Dies sollte Ihre Probleme sowohl für MVC als auch für WebAPI beheben, ohne dass Sie alle anderen Schritte ausführen müssen. Anschließend habe ich im Angular CLI-Projekt einen HttpInterceptor erstellt, der automatisch die entsprechenden Headerinformationen hinzufügte. Hoffe, das hilft jemandem in einer ähnlichen Situation.

0
Damon Drake