web-dev-qa-db-fra.com

Activer la CORS à Golang

Bonjour, je mets en œuvre des apis de repos et pour cela, je souhaite autoriser les demandes croisées d’origine.

Ce que je fais actuellement:

Code du serveur virtuel sur AWS:

func (c *UserController) Login(w http.ResponseWriter, r *http.Request, ctx *rack.Context) {
w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin"))
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
...
...
c.render.Json(w,rsp, http.StatusOK)
return
}

Code Ajax sur localhost:

<script>
$( document ).ready(function() {
    console.log( "ready!" );
    $.ajax({
        url: 'http://ip:8080/login',
        crossDomain: true, //set as a cross domain requests
        withCredentials:false,
        type: 'post',
        success: function (data) {
            alert("Data " + data);
        },
    });
});

L'erreur suivante sur la console du navigateur s'affiche: XMLHttpRequest ne peut pas charger http: // ip: 8080/login . Aucun en-tête 'Access-Control-Allow-Origin' n'est présent sur la ressource demandée. Origin ' http: // localhost: 8081 ' n'est donc pas autorisé à accéder. La réponse avait le code d'état HTTP 422.

J'ai essayé d'ajouter des options de contrôle en amont:

func corsRoute(app *app.App) {
allowedHeaders := "Accept, Content-Type, Content-Length, Accept-Encoding, Authorization,X-CSRF-Token"

f := func(w http.ResponseWriter, r *http.Request) {
    if Origin := r.Header.Get("Origin"); Origin != "" {
        w.Header().Set("Access-Control-Allow-Origin", "*")
        w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
        w.Header().Set("Access-Control-Allow-Headers", allowedHeaders)
        w.Header().Set("Access-Control-Expose-Headers", "Authorization")
    }
    return
}
app.Router.Options("/*p", f, publicRouteConstraint)
}

Mais ça ne fonctionne pas.

Que peut-on faire pour le réparer?.

6
Yash Srivastava

J'utilise le package gorilla/mux pour construire le serveur API Go RESTful, et l'utilisation de JavaScript par le client peut fonctionner,

My Go Server s'exécute à localhost:9091 et le code serveur:

router := mux.NewRouter()
//api route is /people, 
//Methods("GET", "OPTIONS") means it support GET, OPTIONS
router.HandleFunc("/people", GetPeopleAPI).Methods("GET", "OPTIONS")
log.Fatal(http.ListenAndServe(":9091", router))

Je trouve important de donner OPTIONS ici, sinon une erreur se produira:

OPTIONS http: // localhost: 9091/people } _ 405 (méthode non autorisée)

Échec du chargement de http: // localhost: 9091/people }: la réponse à la demande de contrôle en amont ne réussit pas le contrôle du contrôle d'accès: aucun en-tête 'Contrôle d'accès-Autoriser-Origine' n'est présent sur la ressource demandée. Origin ' http: // localhost: 9092 ' n'est donc pas autorisé à accéder. La réponse avait le code d'état HTTP 405.

après permettre OPTIONS cela fonctionne très bien. Je tire l’idée de Cet article .

En outre, doc MDN CORS mentionne:

De plus, pour les méthodes de requête HTTP pouvant avoir des effets secondaires sur les données du serveur, la spécification exige que les navigateurs "preflight" contrôlent la demande, sollicitant du serveur les méthodes prises en charge avec une méthode de requête HTTP OPTIONS, et ensuite, après "approbation" du serveur, envoi de la requête réelle avec la méthode de requête HTTP réelle.

Voici la méthode api GetPeopleAPI, remarque dans la méthode que je donne commentaire // Autoriser CORS ici Par * ou Origine spécifique, j'ai une autre réponse similaire expliquant le concept de CORS Ici :

func GetPeopleAPI(w http.ResponseWriter, r *http.Request) {

    //Allow CORS here By * or specific Origin
    w.Header().Set("Access-Control-Allow-Origin", "*")

    w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
    // return "OKOK"
    json.NewEncoder(w).Encode("OKOK")
}

Dans le client, j'utilise html avec javascript sur localhost:9092, et javascript enverra une requête au serveur à partir de localhost:9092

function GetPeople() {
    try {
        var xhttp = new XMLHttpRequest();
        xhttp.open("GET", "http://localhost:9091/people", false);
        xhttp.setRequestHeader("Content-type", "text/html");
        xhttp.send();
        var response = JSON.parse(xhttp.response);
        alert(xhttp.response);
    } catch (error) {
        alert(error.message);
    }
}

et la demande peut obtenir avec succès la réponse "OKOK".

Vous pouvez également vérifier les informations d'en-tête de réponse/demande à l'aide d'outils tels que Fiddler.

10
yu yang Jian

Vous pouvez vérifier ceci https://github.com/rs/cors

Cela traiterait également la demande Options

6
Gaurav Manchanda

Merci pour l'indice - tout est dans l'en-tête! J'utilise uniquement ces en-têtes golang côté serveur:

w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.Header().Set("Access-Control-Allow-Origin", "*")

Fonctionne maintenant avec ce JQuery:

<script 
src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js">
</script>
<script>
$.ajax({
    type: 'GET',
    url: 'https://www.XXXXXXX.org/QueryUserID?u=juXXXXny&p=blXXXXXne',
    crossDomain: true,
    dataType: 'text',
    success: function(responseData, textStatus, jqXHR) {
        alert(responseData);
            },
    error: function (responseData, textStatus, errorThrown) {
        alert('POST failed.');
    }
});
</script>
5
user2099484

GO SERVER SETTING:

package main

import (
  "net/http"
)


  func Cors(w http.ResponseWriter, r *http.Request) {
  w.Header().Set("Content-Type", "text/html; charset=ascii")
  w.Header().Set("Access-Control-Allow-Origin", "*")
  w.Header().Set("Access-Control-Allow-Headers","Content-Type,access-control-allow-Origin, access-control-allow-headers")
          w.Write([]byte("Hello, World!"))
  }

  func main() {
  mux := http.NewServeMux()
  mux.HandleFunc("/plm/cors",Cors)
  http.ListenAndServe(":8081", mux)
}

Client JQUERY AJAX RÉGLAGE:

<head>
       <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js">
       </script>
</head>
<body>

              <br> Please confirm to proceed : <button class="myConfirmButton1">Go!!</button>

             <div id="loader1" style="display:none;">loading...</div>
             <div id="loader2" style="display:none;">...done</div>
             <div id="myFeedback1"></div>

          <script>
          $(document).ready(function(){
            $(".myConfirmButton1").click(function(){
              $('#loader1').show();
              $.ajax({
                url:"http://[webserver.domain.com:8081]/plm/cors",
                dataType:'html',
                headers: {"Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "access-control-allow-Origin, access-control-allow-headers"},
                type:'get',
                contentType: 'application/x-www-form-urlencoded',
                success: function( data, textStatus, jQxhr ){
                $('#loader1').hide();
                $('#loader2').show();
                $('#myFeedback1').html( data );
                        },
                error: function( jqXhr, textStatus, errorThrown ){
                $('#loader1').hide();
                $('#myFeedback1').html( errorThrown );
                alert("error" + errorThrown);
                        }
                });
           });
          });
          </script>
</body>

DEMANDE D'ESSAI du client avec curl et réponse obtenue:

curl -iXGET http: // [webserver.domain.com:8081]/plm/cors

HTTP/1.1 200 OK
Access-Control-Allow-Headers: Content-Type,access-control-allow-Origin, access-control-allow-headers
Access-Control-Allow-Origin: *
Content-Type: text/html; charset=ascii
Date: Wed, 17 Jan 2018 13:28:28 GMT
Content-Length: 13

Hello, World!
1
Pascal Louis-Marie

Pour autoriser CORS votre serveur doit intercepter toutes les Requête de contrôle en amont que le navigateur envoie avant la requête réelle avec la méthode OPTIONS sur le même chemin.

La première façon est de gérer cela manuellement avec quelque chose comme ceci:

func setupCORS(w *http.ResponseWriter, req *http.Request) {
    (*w).Header().Set("Access-Control-Allow-Origin", "*")
    (*w).Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
    (*w).Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
}

func indexHandler(w http.ResponseWriter, req *http.Request) {
    setupCORS(&w, req)
    if (*req).Method == "OPTIONS" {
        return
    }

    // process the request...
}

La deuxième façon est d’utiliser un paquet prêt à être utilisé comme https://github.com/rs/cors

package main

import (
    "net/http"

    "github.com/rs/cors"
)

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Content-Type", "application/json")
        w.Write([]byte("{\"hello\": \"world\"}"))
    })

    // cors.Default() setup the middleware with default options being
    // all origins accepted with simple methods (GET, POST). See
    // documentation below for more options.
    handler := cors.Default().Handler(mux)
    http.ListenAndServe(":8080", handler)
}
0
Maxim Shubin

Ajoutant à toutes les bonnes réponses: au lieu de définir les en-têtes dans chaque gestionnaire, vous voudrez probablement utiliser le appHandler pattern:

type Handler func(http.ResponseWriter, *http.Request) *Error

func (fn Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Access-Control-Allow-Origin", "*")
    w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
    if e := fn(w, r); e != nil { // e is *appError, not os.Error.
        http.Error(w, e.Message, e.Code)
    }
}

func Login(w http.ResponseWriter, r *http.Request) *Error {
   ...
   return nil
}

r.Handle("/login", Handler(Login))
0
ET-CS