web-dev-qa-db-fra.com

CORS activé, mais la réponse pour le contrôle en amont a un code d'état HTTP non valide 404 lors de l'envoi de JSON

J'ai fait une recherche approfondie mais je ne trouve pas de solution à ce problème dans mon cas particulier.

Les appels de service entre domaines utilisant Fiddler (POST) s'exécutent correctement et les données sont reçues. Cependant, via le navigateur (Chrome), je reçois le message "Le contrôle en amont a un code d'état HTTP non valide 404".

J'ai une application Web API et j'ai installé CORS et je suis assuré que le fichier web.config contient les informations suivantes:

<system.webServer>
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Headers" value="Content-Type" />
        <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
      </customHeaders>
    </httpProtocol>
</system.webServer>

Voici l'appel Ajax: 

var secretKey = 'difusod7899sdfiertwe08wepifdfsodifyosey',
    url = 'http://api.intrinsic.co.uk/api/v1/PTS/ActiveDrivers?api_key=098werolllfWnCbPGAuIXVOJidDHRfYcgxImMlxTXopuekXrSOqOWzEAIdeNTWGPQPpyHxgVGsFysGFKPzq';

  jQuery.ajax ({
      url: url,
      type: "POST",
      data: JSON.stringify({ secretKey: secretKey}),
      dataType: "json",
      contentType: "application/json; charset=utf-8",
      success: function(data){
          var content = "<table class=\"container\"><thead><tr><th>Driver Number</th><th>Timestamp</th><th>VRN</th><th>Latitude</th><th>Longitude</th><th>Track Link</th></tr></thead><tbody>";
          $.each(data.ActiveDrivers.DriverLocationStatus, function (index, element) {
              content += "<tr><td>" + element.DriverNumber + "</td>";
              content += "<td>" + dateFormat(element.Timestamp, "d/m/yy") + " " + dateFormat(element.Timestamp, "h:MM TT") + "</td>";
              content += "<td>" + element.VRN + "</td>";
              content += "<td>" + element.CurrentLatitude + "</td>";
              content += "<td>" + element.CurrentLongitude + "</td>";
              content += "<td><a href=\"https://www.google.co.uk/maps/place//@" + element.CurrentLatitude + "," + element.CurrentLongitude + ",15z/\" target='_blank'>Track &raquo;</a></td></tr>";
          });
          content += "</tbody></table>";
          $( "#result" ).html( content );
      }
  });

Évidemment, fonctionne parfaitement sur le même domaine et, comme mentionné, fonctionne avec Fiddler.

Je suis certain que c'est la vérification OPTIONS avant le contrôle du navigateur qui échoue pour le type de contenu "application/json", mais je ne sais pas comment le résoudre.

Il manque quelque chose dans le fichier web.config que je devrais ajouter?

J'ai essayé de supprimer "type de contenu" sans aucun effet.

J'avais espéré cet article résoudrait le problème (cela semblait prometteur) mais la même erreur est rencontrée:

XMLHttpRequest cannot load [URL]. Response for preflight has invalid HTTP status code 404
21
ChrisCurrie

Merci, mais obtenir l'erreur 405, après les changements de configuration ci-dessus.

Enfin, cela fonctionne après avoir ajouté le code ci-dessous dans le fichier Web api Global.asax.

protected void Application_BeginRequest(Object sender, EventArgs e)
    {
        //HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
        if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
        {
            HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache");
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
            HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
            HttpContext.Current.Response.End();
        }
    }
37
Hussain

J'ai finalement obtenu que cela fonctionne.

Cet article " WebAPI avec CORS - IIS intercepte des OPTIONS verbe " a éclairé ma pensée. Une image montrait où, dans IIS, le mappage du gestionnaire OPTIONS apparaît et pourquoi, dans le fichier web.config, nous devions le supprimer pour nous assurer que IIS ne l'intercepte pas.

Lorsque j'ai jeté un coup d'œil à IIS, ce gestionnaire n'était PAS présent. J'ai ensuite jeté un coup d'œil à l'article lié ' Je ne peux pas définir l'ordre de HttpHandler à l'aide de Web.Config à moins qu'une balise «clear» n'existe ' et j'ai constaté que, dans cet article, après avoir supprimé le gestionnaire OPTION, il était alors explicitement ajouté dans le web.config.

Comme je ne pouvais pas voir le gestionnaire OPTION dans IIS, je l’ai aussi ajouté au fichier web.config et tout a soudainement fonctionné. Il est apparu que cette addition est ce qui était nécessaire.

La section finale des gestionnaires web.config se présente comme suit (notez que j'ai décidé de conserver la "suppression" initiale au cas où cela poserait des problèmes si je migrais ultérieurement vers un autre serveur Web).

<system.webServer>
    <handlers>
      <remove name="WebDAV"/>
      <remove name="OPTIONSVerbHandler"/>
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
      <add name="OPTIONSVerbHandler" path="*" verb="OPTIONS" modules="ProtocolSupportModule" requireAccess="None" responseBufferLimit="4194304" />
    </handlers>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Headers" value="Content-Type" />
        <add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS" />
      </customHeaders>
    </httpProtocol>
</system.webServer>
15
ChrisCurrie

Cela a fonctionné pour moi.

Dans Global.asax

protected void Application_BeginRequest(Object sender, EventArgs e)
{
    //HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
    if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
    {
        HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
        HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
        HttpContext.Current.Response.End();
    }
}

Dans Web.config

    <httpProtocol>
        <customHeaders>

    <add name="Access-Control-Allow-Origin" value="*"/>
    <add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE,OPTIONS"/>
    <add name="Access-Control-Allow-Headers" value="Content-Type"/>
        </customHeaders>
    </httpProtocol>

reconstruire et hop.

11
Darren Street

J'ai une configuration similaire qui affichait 404 erreurs et 500 erreurs alors que j'essayais de faire fonctionner CORS sur mon service Web. Mon correctif utilisait essentiellement la solution de Hussain, mais en le nettoyant, j'ai remarqué qu'une seule ligne de réponse était nécessaire et que je pouvais conserver les gestionnaires Web originaux dans le fichier web.config. gestionnaires de réponse dans le code.

En gros, mon correctif inclut ce ONE FIXE MAJEUR dans mon gestionnaire ApplicationOnBeginRequest:

    private void ApplicationOnBeginRequest( object sender, EventArgs eventArgs )
        {
...
            if ( context.Request.HttpMethod == "OPTIONS" )
                response.End();
        }

et ces gestionnaires dans mon web.config:

<system.webServer>
    <!--Other handlers/modules ...-->
    <httpProtocol>
        <customHeaders>
            <clear />
            <add name="Access-Control-Allow-Origin" value="*" />
            <add name="Access-Control-Allow-Credentials" value="true" />
            <add name="Access-Control-Allow-Headers" value="Content-Type,Accept" />
            <add name="Access-Control-Allow-Methods" value="GET,POST,PUT,DELETE,OPTIONS" />
        </customHeaders>
    </httpProtocol>
   </system.webServer>

Désolé de ne pouvoir envoyer cette note en tant que commentaire sur la réponse de Hussain.

2
InquisitionX

Pour asp core, utilisez ce code dans Startup.cs dans la procédure de configuration. J'ai utilisé pour la version 2.0 mais je pense que cela devrait fonctionner avec les anciens aussi

app.UseCors(builder => {
                builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();
            });
0
valentasm

Cela m'a aidé aussi, j'avais déjà configuré CORS dans web.config

protected void Application_BeginRequest(Object sender, EventArgs e)
{
    //HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
    if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
    {
        HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
        HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
        HttpContext.Current.Response.End();
    }
}