Golang تطوير خادم الويب - من السهل إلى المجمع



منذ خمس سنوات ، بدأت في تطوير Gophish ، مما أتاح تعلُّم اللغة Golang. أدركت أن Go هي لغة قوية ، وقد استكملت قدراتها من خلال العديد من المكتبات. Go عالمي: على وجه الخصوص ، من خلال مساعدتها ، من الممكن تطوير تطبيقات الخادم دون مشاكل.

هذه المقالة تدور حول كتابة خادم في Go. لنبدأ بأشياء بسيطة ، مثل "Hello world!" ، وننتهي بتطبيق يتضمن الميزات التالية:

- استخدام Let's Encrypt for HTTPS.
- العمل كموجه API.
- العمل مع الوسيطة.
- معالجة الملفات الثابتة.
- الاغلاق الصحيح.

توصي Skillbox بما يلي: The Python Developer من البداية إلى نقطة الصفر .

نذكرك: لجميع قراء "Habr" - خصم بقيمة 10،000 روبل عند التسجيل في أي دورة تدريبية في Skillbox باستخدام الرمز الترويجي "Habr".

مرحبا العالم!


إن إنشاء خادم ويب على Go سريع للغاية. فيما يلي مثال على استخدام معالج يقوم بإرجاع "Hello، world!" الموعودة أعلاه.

package main import ( "fmt" "net/http" ) func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello World!") }) http.ListenAndServe(":80", nil) } 

بعد ذلك ، إذا قمت ببدء تشغيل التطبيق وفتحت صفحة المضيف المحلي ، سترى على الفور النص "Hello، world!" (بالطبع ، إذا كان كل شيء يعمل بشكل صحيح).

بعد ذلك ، سوف نستخدم المعالج بشكل متكرر ، ولكن أولاً ، دعونا نفهم كيف يعمل كل شيء.

صافي / HTTP


يستخدم المثال الحزمة net/http ، وهي الأداة الرئيسية في Go لتطوير الخوادم وعملاء HTTP. لفهم الكود ، دعونا نلقي نظرة على معنى العناصر الثلاثة المهمة: http.Handler و http.ServeMux و http.Server.

معالجات HTTP


عندما نتلقى طلبًا ، يقوم المعالج بتحليله وتشكيل استجابة. يتم تنفيذ معالجات Go على النحو التالي:

 type Handler interface { ServeHTTP(ResponseWriter, *Request) } 

يستخدم المثال الأول وظيفة المساعد http.HandleFunc. يلتف وظيفة أخرى ، والتي بدورها تقبل http.ResponseWriter و http.Request في ServeHTTP.

بمعنى آخر ، يتم تمثيل معالجات Golang من خلال واجهة واحدة ، والتي توفر العديد من الفرص للمبرمج. لذلك ، على سبيل المثال ، يتم تطبيق الوسيطة باستخدام معالج ، حيث يقوم ServeHTTP أولاً بعمل شيء ما ، ثم يستدعي طريقة ServeHTTP لمعالج آخر.

كما ذكرنا أعلاه ، يقوم المعالجون ببساطة بإنشاء استجابات للطلبات. لكن أي معالج خاص يجب استخدامه في وقت معين؟

طلب التوجيه


لعمل الاختيار الصحيح ، استخدم مُضاعِف HTTP. يطلق عليه اسم muxer أو جهاز التوجيه في عدد من المكتبات ، لكن الأمر نفسه. وظيفة المضاعف هي تحليل مسار الطلب وتحديد المعالج المناسب.

إذا كنت بحاجة إلى دعم للتوجيه المعقد ، فمن الأفضل استخدام مكتبات الجهات الخارجية. واحدة من أكثرها تقدماً هي الغوريلا / mux و go-chi / chi ، هذه المكتبات تجعل من الممكن تنفيذ المعالجة المتوسطة دون أي مشاكل. من خلال مساعدتهم ، يمكنك تكوين توجيه أحرف البدل وتنفيذ عدد من المهام الأخرى. الإضافة الخاصة بهم هي التوافق مع معالجات HTTP القياسية. نتيجة لذلك ، يمكنك كتابة رمز بسيط مع إمكانية تعديله في المستقبل.

لن يتطلب العمل مع الأطر المعقدة في الوضع الطبيعي حلولًا قياسية تمامًا ، وهذا يعقد إلى حد كبير استخدام المعالجات الافتراضية. لإنشاء الغالبية العظمى من التطبيقات ، مزيج من المكتبة الافتراضية وجهاز توجيه بسيط يكفي.

طلب المعالجة


بالإضافة إلى ذلك ، نحتاج إلى مكون "يستمع" إلى الاتصالات الواردة ويعيد توجيه جميع الطلبات إلى المعالج الصحيح. يمكن القيام بهذه المهمة بسهولة بواسطة http.Server.

فيما يلي يوضح أن الخادم مسؤول عن جميع المهام المتعلقة بمعالجة الاتصال. هذا ، على سبيل المثال ، العمل على بروتوكول TLS. لتطبيق استدعاء http.ListenAndServer ، يتم استخدام خادم HTTP قياسي.

الآن دعونا ننظر إلى أمثلة أكثر تعقيدا.

مضيفا دعونا تشفير


بشكل افتراضي ، يعمل تطبيقنا على بروتوكول HTTP ، لكن يوصى باستخدام بروتوكول HTTPS. في Go ، يمكن القيام بذلك دون مشاكل. إذا تلقيت شهادة ومفتاحًا خاصًا ، فما عليك سوى تسجيل ListenAndServeTLS مع الشهادة وملفات المفاتيح الصحيحة.

 http.ListenAndServeTLS(":443", "cert.pem", "key.pem", nil) 

يمكنك دائما أن تفعل أفضل.

دعونا تشفير يعطي شهادات مجانية مع القدرة على التجديد تلقائيا. من أجل استخدام الخدمة ، تحتاج إلى حزمة autocert .

أسهل طريقة لتكوينه هي استخدام طريقة autocert.NewListener بالاشتراك مع http.Serve. تسمح لك هذه الطريقة بتلقي وتجديد شهادات TLS ، بينما يقوم خادم HTTP بمعالجة الطلبات:

 http.Serve(autocert.NewListener("example.com"), nil) 

إذا فتحنا example.com في المتصفح ، فسوف نحصل على استجابة HTTPS "مرحبًا يا عالم!".

إذا كنت بحاجة إلى تكوين أكثر شمولاً ، فعليك استخدام مدير autocert.Manager. ثم نقوم بإنشاء مثيل http.Server الخاص بنا (حتى الآن استخدمناه افتراضيًا) وأضف المدير إلى خادم TLSConfig:

 m := &autocert.Manager{ Cache: autocert.DirCache("golang-autocert"), Prompt: autocert.AcceptTOS, HostPolicy: autocert.HostWhitelist("example.org", "www.example.org"), } server := &http.Server{ Addr: ":443", TLSConfig: m.TLSConfig(), } server.ListenAndServeTLS("", "") 

هذه طريقة سهلة لتنفيذ دعم HTTPS الكامل مع تجديد الشهادة التلقائي.

إضافة طرق مخصصة


جهاز التوجيه الافتراضي المضمّن في المكتبة القياسية جيد ، لكنه بسيط للغاية. تتطلب معظم التطبيقات توجيهًا أكثر تعقيدًا ، بما في ذلك المسارات المتداخلة والبدل ، أو الإجراء الخاص بتعيين الأنماط ومعلمات المسار.

في هذه الحالة ، يجب عليك استخدام حزم gorilla / mux و go-chi / chi . سنتعلم كيفية التعامل مع هذا الأخير - يتم عرض مثال أدناه.

يتم تقديم ملف api / v1 / api.go الذي يحتوي على طرق لواجهة برمجة التطبيقات:

 / HelloResponse is the JSON representation for a customized message type HelloResponse struct { Message string `json:"message"` } // HelloName returns a personalized JSON message func HelloName(w http.ResponseWriter, r *http.Request) { name := chi.URLParam(r, "name") response := HelloResponse{ Message: fmt.Sprintf("Hello %s!", name), } jsonResponse(w, response, http.StatusOK) } // NewRouter returns an HTTP handler that implements the routes for the API func NewRouter() http.Handler { r := chi.NewRouter() r.Get("/{name}", HelloName) return r } 

وضعنا بادئة api / vq للطرق في الملف الرئيسي.

يمكننا بعد ذلك تحميل هذا على جهاز التوجيه الرئيسي لدينا تحت api / v1 / البادئة مرة أخرى في تطبيقنا الرئيسي:

 // NewRouter returns a new HTTP handler that implements the main server routes func NewRouter() http.Handler { router := chi.NewRouter() router.Mount("/api/v1/", v1.NewRouter()) return router } http.Serve(autocert.NewListener("example.com"), NewRouter()) 

تتيح بساطة العمل مع المسارات المعقدة في Go تبسيط الهيكلة من خلال تقديم التطبيقات المعقدة الكبيرة.

العمل مع الوسيطة


في حالة المعالجة الوسيطة ، يتم استخدام التفاف معالج HTTP مع معالج آخر ، مما يجعل من الممكن المصادقة بسرعة ، وضغط ، ومجلة ، وبعض الوظائف الأخرى.

على سبيل المثال ، ضع في الاعتبار http.Handler الواجهة ، بمساعدتها نكتب معالجًا بمصادقة مستخدمي الخدمة.

 func RequireAuthentication(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if !isAuthenticated(r) { http.Redirect(w, r, "/login", http.StatusTemporaryRedirect) return } // Assuming authentication passed, run the original handler next.ServeHTTP(w, r) }) } 

هناك أجهزة توجيه تابعة لجهات خارجية ، على سبيل المثال ، chi ، والتي تسمح لك بتوسيع وظيفة المعالجة المتوسطة.

العمل مع الملفات الثابتة


تتضمن مكتبة Go القياسية ميزات للعمل مع المحتوى الثابت ، بما في ذلك الصور ، وكذلك ملفات JavaScript و CSS. يمكن الوصول إليها من خلال وظيفة http.FileServer. تقوم بإرجاع معالج يقوم بتوزيع الملفات من دليل محدد.

 func NewRouter() http.Handler { router := chi.NewRouter() r.Get("/{name}", HelloName) //     staticPath, _ := filepath.Abs("../../static/") fs := http.FileServer(http.Dir(staticPath)) router.Handle("/*", fs) return r 

تجدر الإشارة إلى أن http.Dir يعرض محتويات الدليل إذا لم يكن لديه ملف index.html الرئيسي. في هذه الحالة ، لمنع اختراق الدليل ، يجدر استخدام الحزمة غير unindexed .

الاغلاق الصحيح


يحتوي Go أيضًا على ميزة مثل إيقاف تشغيل خادم HTTP بشكل صحيح. يمكن القيام بذلك باستخدام طريقة إيقاف التشغيل (). يبدأ الخادم في goroutine ، ثم يتم الاستماع للقناة لتلقي إشارة المقاطعة. بمجرد تلقي الإشارة ، يتم إيقاف تشغيل الخادم ، ولكن ليس فورًا ، ولكن بعد بضع ثوانٍ.

 handler := server.NewRouter() srv := &http.Server{ Handler: handler, } go func() { srv.Serve(autocert.NewListener(domains...)) }() // Wait for an interrupt c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt) <-c // Attempt a graceful shutdown ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() srv.Shutdown(ctx) 

في الختام


Go هي لغة قوية بها مكتبة قياسية عالمية تقريبًا. قدراته الافتراضية واسعة للغاية ، ويمكنك تقويتها بمساعدة الواجهات - وهذا يسمح لك بتطوير خوادم HTTP موثوقة حقًا.
توصي Skillbox بما يلي:

Source: https://habr.com/ru/post/ar446454/


All Articles