HTTP हेडर सेट करना


165

मैं अपने गो वेब सर्वर में हेडर सेट करने का प्रयास कर रहा हूं। मैं उपयोग कर रहा हूं gorilla/muxऔर net/httpपैकेज।

मैं Access-Control-Allow-Origin: *क्रॉस डोमेन AJAX की अनुमति देना चाहता हूं ।

यहाँ मेरा Go कोड है:

func saveHandler(w http.ResponseWriter, r *http.Request) {
// do some stuff with the request data
}

func main() {
    r := mux.NewRouter()
    r.HandleFunc("/save", saveHandler)
    http.Handle("/", r)
    http.ListenAndServe(":"+port, nil)
}

net/httpमैं बिल्कुल यकीन है कि कैसे सेट प्रतिक्रिया हेडर के लिए नहीं कर रहा हूँ - पैकेज प्रलेखन के रूप में अगर यह एक ग्राहक थे http अनुरोध शीर्षलेख भेजने का वर्णन है?

जवाबों:


227

कोई बात नहीं, मैंने यह पता लगा लिया - मैंने Set()विधि का इस्तेमाल किया है Header()(दोह!)

मेरा हैंडलर अब इस तरह दिखता है:

func saveHandler(w http.ResponseWriter, r *http.Request) {
    // allow cross domain AJAX requests
    w.Header().Set("Access-Control-Allow-Origin", "*")
}

शायद यह किसी को कैफीन से वंचित करने में मदद करेगा जैसा कि कुछ समय पहले :)


2
मैं एक ही मुद्दा रहा है, यह भी जोड़ने के लिए उपयोगी हो सकता है: w.Header().Add("Access-Control-Allow-Methods", "PUT") w.Header().Add("Access-Control-Allow-Headers", "Content-Type")
रे

1
AJAX क्लाइंट सेट withCredentials:true(क्रेडेंशियल भेजे जाने पर "*" मान की अनुमति नहीं है, जो सामान्य उपयोग है) के मामले में यह काम नहीं करेगा । आपको मूल को आवश्यक रूप से सेट करना होगा (नीचे देखें मैट बुक्की का जवाब कैसे दें)।
orcaman 12

98

उपरोक्त सभी उत्तर गलत हैं क्योंकि वे विकल्प प्रीफ़्लाइट अनुरोध को संभालने में विफल रहते हैं, इसका समाधान मक्स राउटर के इंटरफ़ेस को ओवरराइड करना है। कस्टम हेडर (कोर में आवंटित) के साथ AngularJS $ http अनुरोध प्राप्त करना विफल देखें

func main() {
    r := mux.NewRouter()
    r.HandleFunc("/save", saveHandler)
    http.Handle("/", &MyServer{r})
    http.ListenAndServe(":8080", nil);

}

type MyServer struct {
    r *mux.Router
}

func (s *MyServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
    if origin := req.Header.Get("Origin"); origin != "" {
        rw.Header().Set("Access-Control-Allow-Origin", origin)
        rw.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
        rw.Header().Set("Access-Control-Allow-Headers",
            "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
    }
    // Stop here if its Preflighted OPTIONS request
    if req.Method == "OPTIONS" {
        return
    }
    // Lets Gorilla work
    s.r.ServeHTTP(rw, req)
}

19
"उपरोक्त सभी" ... उत्तर कई तरह से हल किए जा सकते हैं, इसलिए इस वाक्यांश का मतलब यह नहीं है कि आप इसे क्या चाहते हैं।
डेव सी

सरल कोर अनुरोधों में कोई पूर्वाभास नहीं है, यह सब इस बात पर निर्भर करता है कि आप क्या सेवा करना चाहते हैं।
laike9m

Access-Control-Allow-Credentials": "true"HttpOnly कुकीज़ के साथ अनुरोधों के लिए मत भूलना ।
फेडेरिको

23

उत्पत्ति के लिए '*' का उपयोग न करें, जब तक कि आपको वास्तव में पूरी तरह से सार्वजनिक व्यवहार की आवश्यकता न हो।
जैसा कि विकिपीडिया कहता है :

"*" का मान इस मायने में खास है कि यह क्रेडेंशियल्स, HTTP प्रमाणीकरण, क्लाइंट-साइड एसएसएल प्रमाणपत्रों की आपूर्ति करने के अनुरोधों को अनुमति नहीं देता है, न ही यह कुकीज़ को भेजने की अनुमति देता है। "

इसका मतलब है कि, आपको बहुत सी त्रुटियां मिलेंगी, खासकर क्रोम में जब आप एक साधारण प्रमाणीकरण उदाहरण के लिए लागू करने का प्रयास करेंगे।

यहाँ एक सही आवरण है:

// Code has not been tested.
func addDefaultHeaders(fn http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        if origin := r.Header.Get("Origin"); origin != "" {
            w.Header().Set("Access-Control-Allow-Origin", origin)
        }
        w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
        w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token")
        w.Header().Set("Access-Control-Allow-Credentials", "true")
        fn(w, r)
    }
}

और इन सभी हेडर को प्रीफ्लाइट ऑप्शन्स रिक्वेस्ट के जवाब देना न भूलें।


1
मैं इस रैपर के उपयोग को नहीं समझता, क्या आप इस बात का उदाहरण दे सकते हैं कि आप इस कोड के साथ अपना http हैंडल कैसे लपेटेंगे? मैं गोरिल्ला मक्स का उपयोग कर रहा हूं इसलिए मेरा वर्तमान उपयोग है router.HandleFunc("/user/action", user.UserAction) http.Handle("/", router) http.ListenAndServe(":8080", nil).Set("Access-Control-Allow-Origin", "*")
मैट बुक्की

2
मैं अब अपने हैंडल कॉल्स को addDefaultHeaders के साथ लपेट रहा हूं, जैसे router.HandleFunc("/user/action", addDefaultHeaders(user.UserAction)) कि मेरे पास लगभग 16 मार्ग हैं, जो आदर्श नहीं है, क्या यह http पैकेज या mux राउटर लेयर में रैपर के रूप में निर्दिष्ट करने का कोई तरीका है
मैट बुक्की

14

एक उचित गोलंग मिडलवेयर सेट करें, ताकि आप किसी भी समापन बिंदु पर पुन: उपयोग कर सकें।

हेल्पर टाइप और फंक्शन

type Adapter func(http.Handler) http.Handler
// Adapt h with all specified adapters.
func Adapt(h http.Handler, adapters ...Adapter) http.Handler {
    for _, adapter := range adapters {
        h = adapter(h)
    }
    return h
}

वास्तविक मिडलवेयर

func EnableCORS() Adapter {
    return func(h http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

            if origin := r.Header.Get("Origin"); origin != "" {
                w.Header().Set("Access-Control-Allow-Origin", 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")
            }
            // Stop here if its Preflighted OPTIONS request
            if r.Method == "OPTIONS" {
                return
            }
            h.ServeHTTP(w, r)
        })
    }
}

endpoint

याद! मध्यवर्तियों को रिवर्स ऑर्डर पर लागू किया जाता है (ExpectGET () को पहले आग मिलती है)

mux.Handle("/watcher/{action}/{device}",Adapt(api.SerialHandler(mux),
    api.EnableCORS(),
    api.ExpectGET(),
))

14

यदि आप अपने राउटर को ओवरराइड नहीं करना चाहते हैं (यदि आपके पास आपका ऐप इस तरह से कॉन्फ़िगर करने का तरीका नहीं है, या जो रूट के आधार पर किसी रूट पर कोर्स को कॉन्फ़िगर करना चाहते हैं), पूर्व उड़ान अनुरोध को संभालने के लिए एक विकल्प हैंडलर जोड़ें। ।

यानी, गोरिल्ला मक्स के साथ आपके मार्ग जैसे दिखेंगे:

accounts := router.Path("/accounts").Subrouter()
accounts.Methods("POST").Handler(AccountsCreate)
accounts.Methods("OPTIONS").Handler(AccountsCreatePreFlight)

ऊपर ध्यान दें कि हमारे POST हैंडलर के अलावा, हम एक विशिष्ट विकल्प विधि हैंडलर को परिभाषित कर रहे हैं

और फिर वास्तविक विकल्प पूर्वधारणा विधि को संभालने के लिए, आप खातों को परिभाषित कर सकते हैंप्रेपलाइट जैसे:

// Check the origin is valid.
origin := r.Header.Get("Origin")
validOrigin, err := validateOrigin(origin)
if err != nil {
    return err
}

// If it is, allow CORS.
if validOrigin {
    w.Header().Set("Access-Control-Allow-Origin", origin)
    w.Header().Set("Access-Control-Allow-Methods", "POST")
    w.Header().Set("Access-Control-Allow-Headers",
        "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
}

वास्तव में यह सब मेरे लिए क्लिक करता है (वास्तव में यह समझने के अलावा कि कोर कैसे काम करता है) यह है कि प्रीफ़लाइट अनुरोध का HTTP तरीका वास्तविक अनुरोध के HTTP विधि से अलग है। CORS आरंभ करने के लिए, ब्राउज़र HTTP मेथड ऑप्शंस के साथ प्रीफ़्लाइट रिक्वेस्ट भेजता है, जिसे आपको अपने राउटर में स्पष्ट रूप से हैंडल करना होता है, और फिर, यदि यह "Access-Control-Allow-Origin": originआपके एप्लिकेशन से उचित प्रतिक्रिया (या "सभी के लिए") प्राप्त करता है, तो यह वास्तविक आरंभ करता है निवेदन।

मेरा यह भी मानना ​​है कि आप केवल मानक प्रकार के अनुरोधों (यानी: GET) के लिए "*" कर सकते हैं, लेकिन दूसरों के लिए आपको स्पष्ट रूप से मूल सेट करना होगा जैसे मैं ऊपर करता हूं।


12

मैं इस मामले के लिए रैपर बनाता हूं:

func addDefaultHeaders(fn http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Access-Control-Allow-Origin", "*")
        fn(w, r)
    }
}

1

मेरे पास एक ही मुद्दा था जैसा कि ऊपर दिए गए समाधानों के ऊपर वर्णित है, सही है, मेरे पास सेट अप 1 इस प्रकार है) क्लाइंट 2 के लिए एंगुलरज) गो सर्वर के लिए बीगो फ्रेमवर्क

कृपया इन बिंदुओं का अनुसरण करते हुए 1) CORS सेटिंग्स को केवल GO सर्वर 2 पर सक्षम किया जाना चाहिए) इसके अलावा कोणीयJS में किसी भी प्रकार के हेडर न जोड़ें।

.config(['$httpProvider', function($httpProvider) {
        $httpProvider.defaults.useXDomain = true;
        delete $httpProvider.defaults.headers.common['X-Requested-With'];
    }])

आप में GO सर्वर से अनुरोध शुरू होने से पहले CORS सेटिंग्स जोड़ें ताकि प्रीफ़लाइट अनुरोध को 200 OK प्राप्त हो जिसके बाद विकल्प विधि GET, POST, PUT में परिवर्तित हो जाएगी या कभी भी आपका अनुरोध प्रकार क्या होगा।


-7

मुझे पता है कि यह उत्तर पर एक अलग मोड़ है, लेकिन क्या यह वेब सर्वर के लिए चिंता का विषय नहीं है? उदाहरण के लिए, nginx , मदद कर सकता है।

Ngx_http_headers_module मॉड्यूल की अनुमति देता है, "समय-सीमा समाप्त" और "कैश-नियंत्रण" शीर्ष लेख फ़ील्ड, और मनमाने ढंग से फ़ील्ड जोड़ने एक प्रतिक्रिया हेडर को

...

location ~ ^<REGXP MATCHING CORS ROUTES> {
    add_header Access-Control-Allow-Methods POST
    ...
}
...

उत्पादन में अपनी गो सेवा के सामने नेग्नेक्स जोड़ना बुद्धिमान लगता है। यह अनुरोधों को अधिकृत करने, लॉग करने और संशोधित करने के लिए बहुत अधिक सुविधा प्रदान करता है। इसके अलावा, यह नियंत्रित करने की क्षमता देता है कि आपकी सेवा तक कौन पहुंचता है और न केवल वह बल्कि आपके ऐप में विशिष्ट स्थानों के लिए अलग-अलग व्यवहार निर्दिष्ट कर सकता है, जैसा कि ऊपर दिखाया गया है।

मैं इस बारे में जा सकता हूं कि आपके गो एपीआई के साथ वेब सर्वर का उपयोग क्यों किया जाए, लेकिन मुझे लगता है कि यह एक और चर्चा का विषय है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.