
أردت حقًا تسمية مقال "Proxy-service on Go in 3 lines" ، لكنني فوقه.
في الواقع ، هو ، يمكن أن يصلح المنطق الرئيسي في ثلاثة أسطر. لفارغ الصبر وأولئك الذين يريدون رؤية الجوهر:
proxy := httputil.NewSingleHostReverseProxy(url) r.Header.Set(header, value) proxy.ServeHTTP(w, r)
تحت القطة هي قصة أكثر تفصيلاً للوافدين الجدد إلى لغة جولانج وأولئك الذين يحتاجون إلى إنشاء وكيل عكسي في أقصر وقت ممكن.
دعونا نتعرف على سبب الحاجة إلى خدمة وكيل ، وكيفية تنفيذها وما هو تحت غطاء المكتبة القياسية.
عكس الوكيل
الوكيل العكسي هو نوع من الخادم الوكيل يتلقى طلبًا من عميل ، ويعيد توجيهه إلى خادم واحد أو أكثر ، ويعيد توجيه الاستجابة.
تتمثل الميزة المميزة للوكيل العكسي في أنها نقطة الدخول لتوصيل المستخدم بالخوادم التي يتصل بها الوكيل نفسه بواسطة منطق العمل. إنه يحدد الخوادم التي سيتم إرسال طلب العميل إليها. يظل منطق إنشاء شبكة خلف الوكيل مخفيًا عن المستخدم.

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

وكيل عادي (وكيل أمامي)
لماذا الاستخدام
يمكن تطبيق مفهوم الوكيل العكسي في مواقف مختلفة:
- موازنة الحمل ،
- اختبار A / B
- التخزين المؤقت للموارد ،
- ضغط بيانات الطلب ،
- تصفية حركة المرور ،
- إذن.
بالطبع ، لا يقتصر النطاق على هذه النقاط الست. حقيقة إمكانية معالجة الطلب قبل وبعد التوكيل تعطي مجالًا كبيرًا للإبداع. في هذه المقالة ، سنناقش استخدام الوكيل العكسي للترخيص.
مهمة
نعمل على تطوير لوحة التحكم الافتراضية VMmanager 6. في أحد الأيام ، قررنا منح المستخدمين مزيدًا من الحرية في مراقبة وتصور هذه المجموعات. لهذه الأغراض ، اختاروا غرافانا .
لكي يعمل Grafana مع بياناتنا ، كان من الضروري تكوين التفويض. ليس من الصعب القيام بذلك ، إن لم يكن لثلاث "أعمال".
- لدينا بالفعل نقطة دخول واحدة - خدمة ترخيص.
- نحن لا نريد أن نبدأ المستخدمين ونفوضهم في Grafana.
- لا نريد منح المستخدمين إمكانية الوصول إلى Grafana مباشرة.
للامتثال للشروط ، قررنا وضع Grafana على الشبكة الداخلية وكتابة وكيل عكسي. سيتحقق من الحقوق في خدمة التفويض وفقط بعد نقل الطلب إلى غرافانا.
فكرة
الفكرة الرئيسية هي نقل مسؤولية الترخيص في Grafana إلى الخادم الوكيل العكسي ( الوثائق الرسمية ). ستقبل Grafana أي طلب كما هو معتمد إذا كان يحتوي على رأس محدد. قبل استبدال هذا العنوان ، يجب علينا التأكد من أن المستخدم الحالي لديه حقوق للعمل مع Grafana.

سلسلة المكالمات "Grafana-proxy ، أو Round-trip"
تطبيق
وتتمثل المهمة الرئيسية هي جميلة القياسية. نبدأ http-server ، الذي سيقبل الاتصالات على منفذ 4000 ونعالج أي عنوان "/" سيحدث الاتصال به.
func main() { http.HandleFunc("/", handlerProxy) if err := http.ListenAndServe(":4000", nil); err != nil { panic(err) } }
يحدث الجزء الأكبر من العمل في معالج الطلب.
[كود كامل تحت قص] func handlerProxy(w http.ResponseWriter, r *http.Request) { fmt.Println(r.URL.Host) if strings.HasPrefix(r.URL.String(), "/api") {
دعنا نذهب من خلال المعلمات. المتغيرات الرئيسية في المثال الذي أضعه في الثوابت:
grafanaUser = "admin"
على سبيل المثال ، هذا يكفي ؛ في الممارسة العملية ، قد تحتاج إلى إعداد هذه القيم مسبقًا. يمكنك تمريرهم بروكسيات كمعلمات لسطر الأوامر ، ثم استخدام العلم أو الحزم الأكثر تقدماً لتحليلها. غالبًا ما تستخدم بيئة الحاوية متغيرات البيئة لتكوين الخدمات ، وسوف يساعدك os.Getenv على طول الطريق.
التالي هو التحقق من التفويض:
if strings.HasPrefix(r.URL.String(), "/api") { err := CheckRights(r.Header) if err != nil { SendJSONError(w, err.Error()) return } }
إذا كان الطلب يذهب إلى grafana.host/api ، فإننا نتحقق من حقوق المستخدم الحالي في استخدام Grafana. التحقق ضروري حتى لا يزعج نقطة التفويض لكل طلب GET من برنامج نصي JS أو أيقونة PNG. سنقوم وكيل محتوى ثابت دون عمليات تفتيش إضافية. للقيام بذلك ، نقوم بتمرير الخريطة مع الرؤوس التي تحتوي على جلسة المستخدم إلى خدمة الترخيص. قد يكون هذا طلبًا منتظمًا. جهاز خدمة الترخيص لا يهم هنا. إذا كانت بيانات التفويض غير مناسبة ، فأغلق الاتصال ، وأرجع خطأً.
بعد عمليات الفحص ، نقوم بتكوين كائن المسار الأساسي:
url, err := url.Parse(fmt.Sprintf("http://%s/", grafanaHost))
باستخدام حزمة httputil القياسية ، التي تمدد حزمة http ، نقوم بتكوين كائن ReverseProxy.
proxy := httputil.NewSingleHostReverseProxy(url)
ReverseProxy هو معالج طلب يقبل طلبًا واردًا ، ويرسله إلى Grafana ويمرر الاستجابة إلى العميل.
ستقوم بإعادة توجيه جميع الطلبات إلى العنوان "المسار الأساسي + عنوان url المطلوب". إذا جاء المستخدم إلى وكيل العنوان: 4000 / api / something ، فسيتم تحويل طلبه إلى grafana: 3000 / api / something ، حيث grafana: 3000 هو المسار الأساسي الذي تم تمريره إلى NewSingleHostReverseProxy ، و / api / something هو الطلب الوارد.
أضف رأس التفويض لـ Grafana واتصل بالطريقة ServeHTTP ، والتي ستنفذ الجزء الأكبر من معالجة الطلب.
r.Header.Set(grafanaHeader, grafanaUser) proxy.ServeHTTP(w, r)
تحت الغطاء ، يقوم ServeHTTP بالكثير من العمل ، على سبيل المثال ، يقوم بمعالجة استجابة خادم X-Forwarded-For أو 101 لتغيير البروتوكول. العمل الرئيسي لهذه الطريقة هو إرسال طلب إلى عنوان مركب ونقل الإجابة المستلمة إلى ResponseWriter.

يؤدي
كل رمز متاح على جيثب .
تفتيش
محاكاة نظامنا باستخدام Docker. لنقم بإنشاء حاويتين - الوكيل و Grafana في شبكة واحدة. لن نخلق نقطة تفويض ، نحن نعتقد أنها تجيب دائمًا بالإيجاب. لن تتوفر حاوية Grafana في وضع عدم الاتصال ، وتكون حاوية الوكيل متاحة على منفذ معين.
إنشاء شبكة:
docker network create --driver=bridge --subnet=192.168.0.0/16 gnet
ارفع حاوية Grafana مع وضع التفويض المكوّن من خلال الرأس:
docker run -d --name=grafana --network=gnet -e "GF_AUTH_PROXY_ENABLED=true" -e "GF_AUTH_PROXY_HEADER_NAME=X-GRAFANA-AUTH" grafana/grafana
يرجى ملاحظة أن هذا هو العرض التوضيحي وليس التكوين النهائي. كحد أدنى ، يجب عليك تعيين كلمة مرور المسؤول وحظر تسجيل المستخدم التلقائي.
رفع الوكيل العكسي:
docker run -d --name proxy -p 4000:4000 --network=gnet grafana_proxy:latest
في المستعرض ، انتقل إلى المضيف المحلي: 4000.
عظيم ، لدينا أذن Grafana أمامنا.
قفص الاتهام لبناء حاوية مع وكيل وتعليمات أكثر تفصيلا حول رفع الحاويات على جيثب .