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?.
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
.
Vous pouvez vérifier ceci https://github.com/rs/cors
Cela traiterait également la demande Options
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>
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!
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)
}
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))