एक्सपोर्ट किए गए Go बैकएंड को सुरक्षित कस्टम मिडलवेयर से बढ़ाना
एक्सपोर्ट किए गए Go बैकएंड में चेंज कैसे जोड़ें बिना उन्हें खोए: कस्टम कोड कहाँ रखें, मिडलवेयर और एन्डपॉइंट कैसे जोड़ें, और अपग्रेड की योजना कैसे बनाएं।

एक्सपोर्ट किए गए कोड को कस्टमाइज़ करने में क्या गलत होता है
एक्सपोर्ट किया गया कोड किसी हैंड‑रिटन Go रिपो जैसा नहीं होता। AppMaster जैसे प्लेटफ़ॉर्म पर बैकएंड विज़ुअल मॉडल (डेटा स्कीमा, बिज़नेस प्रोसेसेज़, API सेटअप) से जनरेट होता है। जब आप फिर से एक्सपोर्ट करते हैं, तो जनरेटर कोड के बड़े हिस्सों को अपडेटेड मॉडल से मेल करने के लिए फिर से लिख सकता है। यह साफ़‑सुथरा रखने के लिए अच्छा है, पर इसका मतलब यह है कि कस्टमाइज़ करने का तरीका अलग होना चाहिए।
सबसे आम समस्या जनरेटेड फाइलों को सीधे एडिट करना है। एक बार काम कर जाता है, फिर अगला एक्सपोर्ट आपकी चेंजेज़ को ओवरराइट कर देता है या कुरूप मर्ज कॉनफ्लिक्ट बनते हैं। उससे भी बदतर, छोटे मैनुअल एडिट्स जनरेटर की कुछ धारणाओं (राउटिंग ऑर्डर, मिडलवेयर चेन, रिक्वेस्ट वेलिडेशन) को तोड़ सकते हैं। एप्प बिल्ड तो हो जाएगा, पर व्यवहार बदल जाएगा।
सुरक्षित कस्टमाइज़ेशन का मतलब है कि आपकी चेंजेज़ दोहराने योग्य और रिव्यू करने में आसान हों। यदि आप बैकएंड को फिर से एक्सपोर्ट कर सकते हैं, अपनी कस्टम लेयर लागू कर सकते हैं, और स्पष्ट रूप से देख सकते हैं कि क्या बदला—तो सही जगह पर हैं। अगर हर अपग्रेड पुरातत्व जैसा लगे, तो यह ठीक नहीं है।
ग़लत जगह पर कस्टमाइज़ेशन होने पर आप आम तौर पर ये समस्याएँ देखते हैं:
- आपकी एडिट्स फिर से एक्सपोर्ट के बाद गायब हो जाती हैं, या आप घंटों कॉन्फ्लिक्ट सुलझाने में लगाते हैं।
- रूट शिफ्ट हो जाते हैं और आपका मिडलवेयर अब उस जगह नहीं चलता जहाँ आप उम्मीद करते थे।
- लॉजिक नो‑कोड मॉडल और Go कोड के बीच डुप्लीकेट हो जाता है और फिर ड्रिफ्ट कर जाता है।
- एक "लाइनों का छोटा बदलाव" एक ऐसा फोर्क बन जाता है जिसे कोई छूना नहीं चाहता।
एक साधारण नियम यह तय करने में मदद करता है कि बदलाव कहाँ जाना चाहिए। यदि बदलाव बिज़नेस बिहेवियर का हिस्सा है जिसे नॉन‑डेवलपर्स एडजस्ट कर सकें (फील्ड, वेलिडेशन, वर्कफ़्लोज़, परमिशन्स), तो उसे नो‑कोड मॉडल में रखें। यदि यह इन्फ्रास्ट्रक्चर बिहेवियर है (कस्टम ऑथ इंटीग्रेशन, रिक्वेस्ट लॉगिंग, स्पेशल हेडर, रेट‑लिमिट), तो उसे ऐसे कस्टम Go लेयर में रखें जो री‑एक्सपोर्ट पर टिका रहे।
उदाहरण: हर रिक्वेस्ट के लिए ऑडिट लॉगिंग आमतौर पर मिडलवेयर होता है (कस्टम कोड)। ऑर्डर पर नया आवश्यक फ़ील्ड आमतौर पर डेटा मॉडल में जाना चाहिए (नो‑कोड)। इस विभाजन को साफ रखें और अपग्रेड प्रेडिक्टेबल रहेंगे।
कोडबेस की मैपिंग: जनरेटेड पार्ट बनाम आपकी पार्ट्स
एक्सपोर्ट किया गया बैकएंड बढ़ाने से पहले, 20 मिनट लगाकर यह मैप करें कि री‑एक्सपोर्ट पर क्या फिर से जनरेट होगा और क्या आपकी जिम्मेदारी है। वह मैप ही अपग्रेड को बोरिंग बनाए रखेगा।
जनरेटेड कोड अक्सर खुद को दिखा देता है: "Code generated" या "DO NOT EDIT" जैसे हेडर कमेंट, लगातार नामकरण पैटर्न, और बहुत यूनिफॉर्म स्ट्रक्चर जिसमें कम ही इंसानी कमेंट होते हैं।
एक व्यावहारिक तरीका यह है कि रिपो की चीज़ों को तीन बकेट में बाँट दें:
- Generated (read-only): वे फाइलें जिन पर स्पष्ट जनरेटर मार्कर्स हों, दोहराने वाले पैटर्न हों, या ऐसे फ़ोल्डर जो फ्रेमवर्क सॉफ़्ट के कंकाल जैसा लगते हों।
- Owned by you: पैकेज जो आपने बनाए हैं, रैपर और कॉन्फ़िगरेशन जिसे आप नियंत्रित करते हैं।
- Shared seams: रजिस्ट्रेशन के लिए बने हुए वायरिंग पॉइंट—रूट्स, मिडलवेयर, हुक—जहाँ कभी‑कभार छोटे एडिट्स ज़रूरी हो सकते हैं पर वे न्यूनतम होने चाहिए।
पहले बकेट को रीड‑ओनली मानें भले ही तकनीकी रूप से आप उसे एडिट कर सकें। यदि आप उसे बदलते हैं, तो मान लें कि जनरेटर बाद में उसे ओवरराइट कर देगा या आप हमेशा के लिए मर्ज बोझ उठाएँगे।
टीम के लिए इस बॉउंडरी को स्पष्ट बनाने हेतु रिपो में एक छोटा नोट रखें (जैसे रूट README)। सरल रखें:
"Generator-owned files: anything with a DO NOT EDIT header and folders X/Y. Our code lives under internal/custom (or similar). Only touch wiring points A/B, and keep changes there small. Any wiring edit needs a comment explaining why it can't live in our own package."
यह एक नोट तेजी से किये गए फिक्स को स्थायी अपग्रेड दर्द में बदलने से रोकता है।
कस्टम कोड कहाँ रखें ताकि अपग्रेड सरल रहें
सबसे सुरक्षित नियम सरल है: एक्सपोर्टेड कोड को रीड‑ओनली मानें, और अपनी चेंजेज़ एक स्पष्ट रूप से मालिकाना कस्टम एरिया में रखें। जब आप बाद में फिर से एक्सपोर्ट करें (उदाहरण के लिए AppMaster से), आप चाहेंगे कि मर्ज ज्यादातर "जनरेटेड कोड को रिप्लेस करो, कस्टम कोड रखो" जैसा हो।
अपनी जोड़ियों के लिए अलग पैकेज बनाएँ। यह रिपो के अंदर रह सकता है, पर जनरेटेड पैकेजों में मिक्स न करें। जनरेटेड कोड कोर ऐप चलाता है; आपका पैकेज मिडलवेयर, रूट्स और हेल्पर्स जोड़ता है।
एक व्यावहारिक लेआउट:
internal/custom/— मिडलवेयर, हैंडलर्स, और छोटे हेल्पर्स के लिएinternal/custom/routes.go— एक जगह पर कस्टम रूट्स रजिस्टर करने के लिएinternal/custom/middleware/— रिक्वेस्ट/रेस्पॉन्स लॉजिक के लिएinternal/custom/README.md— भविष्य के एडिट्स के लिए कुछ नियम
सर्वर वायरिंग को पाँच अलग‑अलग जगहों पर एडिट करने से बचें। एक पतला "हुक पॉइंट" रखें जहाँ आप मिडलवेयर अटैच कर के एक्स्ट्रा रूट्स रजिस्टर करते हैं। यदि जनरेटेड सर्वर एक राउटर या हैंडलर चेन एक्स्पोज़ करता है, वहाँ प्लग‑इन करें। अगर नहीं करता, तो एंट्री‑पॉइंट के पास एक इंटीग्रेशन फ़ाइल जोड़ें जो कुछ ऐसा कॉल करे: custom.Register(router).
कस्टम कोड ऐसे लिखें जैसे कि आप इसे कल किसी नए एक्सपोर्ट में ड्रॉप कर सकते हों। Dependencies कम रखें, जहाँ तक संभव हो जनरेटेड टाइप्स को कॉपी करने से बचें, और छोटे एडैप्टर का उपयोग करें।
चरण दर चरण: सुरक्षित तरीके से कस्टम मिडलवेयर जोड़ना
मकसद है कि लॉजिक अपने पैकेज में रहे, और जनरेटेड कोड को केवल एक जगह पर वायर करने के लिए छुआ जाए।
सबसे पहले, मिडलवेयर को संकुचित रखें: रिक्वेस्ट लॉगिंग, सादे ऑथ चेक, रेट‑लिमिट, या रिक्वेस्ट ID। अगर यह तीन काम करने लगेगा, तो बाद में आपको और फाइलें बदलनी पड़ेंगी।
एक छोटा पैकेज बनाएं (उदा., internal/custom/middleware) जो पूरे ऐप की जानकारी की ज़रूरत न हो। सार्वजनिक सतह छोटी रखें: एक कंस्ट्रक्टर फ़ंक्शन जो मानक Go हैंडलर रैपर लौटाए।
package middleware
import "net/http"
func RequestID(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Add header, log, or attach to context here.
next.ServeHTTP(w, r)
})
}
अब एक इंटीग्रेशन पॉइंट चुनें: वह जगह जहाँ राउटर या HTTP सर्वर बनाया जाता है। वहाँ अपने मिडलवेयर को एक बार रजिस्टर करें, और अलग‑अलग रूट्स पर बदल‑बदल कर चेंज करने से बचें।
वेरिफिकेशन लूप छोटा रखें:
- एक फोकस्ड टेस्ट
httptestका उपयोग करते हुए जोड़ें जो एक आउटकम (स्टेटस कोड या हेडर) चेक करे। - एक मैनुअल रिक्वेस्ट कर के व्यवहार कन्फ़र्म करें।
- पुष्टि करें कि मिडलवेयर एरर पर भी समझदारी से व्यवहार करता है।
- रजिस्ट्रेशन लाइन के पास एक छोटा कमेंट जोड़ें कि यह क्यों मौजूद है।
छोटा डिफ़, एक वायरिंग पॉइंट, आसान री‑एक्सपोर्ट।
चरण दर चरण: नया एन्डपॉइंट जोड़ना बिना सब कुछ फोर्क किए
जनरेटेड कोड को रीड‑ओनली मानें और अपना एन्डपॉइंट एक छोटे कस्टम पैकेज में जोड़ें जिसे ऐप इम्पोर्ट करे। यही चेंजेज़ को री‑ऐप्रायबल रखता है।
शुरू करने से पहले कॉन्ट्रैक्ट लिखें: एन्डपॉइंट क्या स्वीकार करेगा (क्वेरी पेरामीटर्स, JSON बॉडी, हेडर)? क्या रिटर्न करेगा (JSON शेप)? स्टेटस कोड्स पहले से चुन लें ताकि व्यवहार "जो भी काम किया" जैसा न रहे।
कस्टम पैकेज में एक हैंडलर बनाएं। बोरिंग रखें: इनपुट पढ़ें, वेलिडेट करें, मौजूदा सर्विसेस या DB हेल्पर्स को कॉल करें, और जवाब लिखें।
रूट को उसी सिंगल इंटीग्रेशन पॉइंट पर रजिस्टर करें जहाँ आप मिडलवेयर रजिस्टर करते हैं, न कि जनरेटेड हैंडलर फाइलों के अंदर। अगर जनरेटेड प्रोजेक्ट यूज़र हुक्स या कस्टम रजिस्ट्रेशन सपोर्ट करता है, उसका उपयोग करें।
एक छोटा चेकलिस्ट व्यवहार को सुसंगत रखता है:
- इनपुट जल्दी वेलिडेट करें (required फ़ील्ड, फॉरमैट, मिन/मैक्स)।
- एक ही एरर शेप हर जगह रिटर्न करें (message, code, details)।
- जहाँ काम हैंग हो सकता है वहाँ context timeouts का उपयोग करें (DB, नेटवर्क कॉल)।
- अनपेक्षित एरर को एक बार लॉग करें, फिर एक साफ़ 500 रिटर्न करें।
- नया रूट हिट करके एक छोटा टेस्ट जोड़ें जो स्टेटस और JSON चेक करे।
साथ ही कन्फ़र्म करें कि राउटर आपका एन्डपॉइंट ठीक‑ठीक एक बार ही रजिस्टर कर रहा है। डुप्लीकेट रजिस्ट्रेशन पोस्ट‑मर्ज आम होता है।
इंटीग्रेशन पैटर्न जो चेंजेज़ को सीमित रखते हैं
जनरेटेड बैकएंड को एक डिपेंडेंसी की तरह संभालें। कंपोज़िशन को प्राथमिकता दें: जनरेटेड ऐप के आसपास फीचर्स वायर करें बजाय इसके कि इसके कोर लॉजिक को एडिट करें।
कॉन्फ़िगरेशन और कंपोज़िशन को प्राथमिकता दें
कोड लिखने से पहले देखें कि क्या व्यवहार कॉन्फ़िगरेशन, हुक्स, या स्टैण्डर्ड कंपोज़िशन के जरिए जोड़ा जा सकता है। मिडलवेयर एक अच्छा उदाहरण है: इसे एज पर (राउटर/HTTP स्टैक) जोड़ें ताकि बिना बिज़नेस लॉजिक के बदले इसे हटाया या रीडरर किया जा सके।
यदि आपको नया व्यवहार चाहिए (रेट‑लिमिटिंग, ऑडिट लॉगिंग, रिक्वेस्ट IDs), इसे अपने पैकेज में रखें और एक सिंगल इंटीग्रेशन फ़ाइल से रजिस्टर करें। रिव्यू में यह समझाना आसान होना चाहिए: "one new package, one registration point."
एडैप्टर्स का उपयोग करें ताकि जनरेटेड टाइप्स लीक न हों
जनरेटेड मॉडल और DTOs अक्सर एक्सपोर्ट्स के साथ बदलते हैं। अपग्रेड दर्द को कम करने के लिए बॉउंडरी पर ट्रांसलेट करें:
- जनरेटेड रिक्वेस्ट टाइप्स को अपनी इंटरनल स्ट्रक्ट में बदलें।
- डोमेन लॉजिक केवल अपनी स्ट्रक्ट्स पर चलाएँ।
- रिज़ल्ट्स को वापस जनरेटेड रिस्पॉन्स टाइप्स में बदलें।
इस तरह अगर जनरेटेड टाइप्स शिफ्ट करें, तो कम्पाइलर आपको एक जगह पर अपडेट करने के लिए निर्देश देगा।
जब आपको सचमुच जनरेटेड कोड को छूना पड़े, तो उसे एक सिंगल वायरिंग फाइल तक ही सीमित रखें। कई जनरेटेड हैंडलर्स में एडिट करने से बचें।
// internal/integrations/http.go
func RegisterCustom(r *mux.Router) {
r.Use(RequestIDMiddleware)
r.Use(AuditLogMiddleware)
}
एक व्यावहारिक नियम: यदि आप परिवर्तन को 2–3 वाक्यों में नहीं बता सकते तो वह शायद बहुत जटिल है।
समय के साथ डिफ्स को कैसे संभालें
लक्ष्य यह है कि री‑एक्सपोर्ट सप्ताह भर के कॉन्फ्लिक्ट में न बदल जाए। एडिट्स को छोटे, ढूँढने में आसान और समझाने में सरल रखें।
दिन एक से Git का उपयोग करें और जनरेटेड अपडेट्स को अपनी कस्टम वर्क से अलग रखें। यदि आप उन्हें मिक्स कर देंगे तो बाद में आप नहीं जान पाएंगे कि बग किसने पैदा किया।
एक कमिट रूटीन जो पठनीय रहे:
- हर कमिट का एक उद्देश्य हो ("Add request ID middleware", न कि "misc fixes").
- फॉर्मैटिंग‑ओनली चेंजेज़ को लॉजिक चेंजेज़ के साथ मिक्स न करें।
- हर री‑एक्सपोर्ट के बाद, पहले जनरेटेड अपडेट को कमिट करें, फिर अपनी कस्टम एडजस्टमेंट्स को कमिट करें।
- कमिट मैसेज में जिस पैकेज या फाइल को आपने छुआ उसका जिक्र करें।
एक साधारण CHANGELOG_CUSTOM.md रखें जिसमें हर कस्टमाइज़ेशन क्या है, क्यों है और कहाँ रखा है लिखा हो। यह खासकर AppMaster एक्सपोर्ट्स के साथ उपयोगी है क्योंकि प्लेटफ़ॉर्म कोड को पूरी तरह से पुनःजनरेट कर सकता है और आप जल्दी से देखना चाहेंगे कि क्या फिर से लागू या वेरिफ़ाई करना है।
डिफ़ नॉइज़ कम करने के लिए सुसंगत फॉर्मैटिंग और लिंट नियम अपनाएँ। हर कमिट पर gofmt चलाएँ और वही चेक CI में चलाएँ। अगर जनरेटेड कोड किसी खास स्टाइल का उपयोग करता है, तो उसे हाथ से "साफ़" न करें जब तक कि आप हर री‑एक्सपोर्ट पर वह क्लीनअप दोहराने के लिए तैयार न हों।
अगर टीम हर एक्सपोर्ट के बाद वही मैनुअल एडिट्स बार‑बार कर रही है, तो एक पैच वर्कफ़्लो पर विचार करें: एक्सपोर्ट, पैच लागू करें (या स्क्रिप्ट), टेस्ट चलाएँ, शिप करें।
अपग्रेड की योजना: री‑एक्सपोर्ट, मर्ज, और वेरिफ़ाई
अपग्रेड तब आसान होते हैं जब आप बैकएंड को ऐसे मानें जिसे आप पुनःजनरेट कर सकते हैं, न कि हमेशा हाथ से मेंटेन करना है। लक्ष्य स्थिर है: क्लीन कोड को फिर से एक्सपोर्ट करें, फिर हर बार अपने प्लान किए गए इंटीग्रेशन पॉइंट्स के माध्यम से कस्टम बिहेवियर फिर से लागू करें।
अपग्रेड की रिदम चुनें जो आपके रिस्क टोलरेंस और ऐप के बदलावों की आवृत्ति से मेल खाती हो:
- प्लेटफ़ॉर्म रिलीज़ के अनुसार अगर आपको सुरक्षा फिक्स या नई सुविधाएँ तेज़ी से चाहिए
- त्रैमासिक यदि ऐप स्थिर है और बदलाव छोटे हैं
- केवल आवश्यकता पड़ने पर अगर बैकएंड दुर्लभ रूप से बदलता है और टीम छोटी है
जब अपग्रेड का समय आए, तो अलग ब्रांच में ड्राइ‑रन री‑एक्सपोर्ट करें। पहले अकेले नए एक्सपोर्टेड वर्ज़न को बिल्ड और रन करें, ताकि आप जानें कि आपकी कस्टम लेयर शामिल होने से पहले क्या बदला।
फिर अपनी कस्टमाइज़ेशन को योजनाबद्ध सीमों (मिडलवेयर रजिस्ट्रेशन, कस्टम राउटर ग्रुप, आपका कस्टम पैकेज) के माध्यम से फिर से लागू करें। जनरेटेड फाइलों में सर्जिकल एडिट से बचें। यदि किसी परिवर्तन को सीम के माध्यम से व्यक्त नहीं किया जा सकता, तो यह संकेत है कि एक नया सीम एक बार जोड़ना चाहिए, और फिर हमेशा उसके माध्यम से परिवर्तन करें।
एक छोटा रिग्रेशन चेकलिस्ट के साथ वेरिफ़ाई करें:
- ऑथ फ्लो काम करता है (लॉगिन, टोकन रिफ्रेश, लॉगआउट)
- 3–5 प्रमुख API एंडपॉइंट्स वही स्टेटस कोड और शेप रिटर्न करते हैं
- हर एन्डपॉइंट का एक अनहैप्पी पाथ (खराब इनपुट, मिसिंग ऑथ)
- बैकग्राउण्ड जॉब्स या शेड्यूल्ड टास्क अभी भी चलते हैं
- हेल्थ/रीडिनेस एंडपॉइंट आपके डिप्लॉयमेंट सेटअप में OK रिटर्न करे
अगर आपने ऑडिट लॉगिंग मिडलवेयर जोड़ा है, तो हर री‑एक्सपोर्ट और मर्ज के बाद एक लेखन ऑपरेशन के लिए देखें कि लॉग में यूज़र ID और रूट नाम मौजूद हैं।
सामान्य गलतियाँ जो अपग्रेड को दर्दनाक बना देती हैं
आपकी अगली री‑एक्सपोर्ट को तब सबसे तेज़ी से ख़राब किया जा सकता है जब आप जनरेटेड फाइलों को "बस इस बार" एडिट करें। छोटे बग को ठीक करते समय यह हानिरहित लगता है, पर महीने बाद आप नहीं याद रख पाएँगे कि क्या बदला, क्यों बदला, या क्या जनरेटर अब वही आउटपुट पैदा करता है।
एक और फँसने वाली बात है कस्टम कोड को हर जगह बिखेर देना: एक हेल्पर एक पैकेज में, कस्टम ऑथ चेक दूसरे में, राउटिंग के पास मिडलवेयर ट्वीक, और एक वन‑ऑफ हैंडलर किसी यादृच्छिक फोल्डर में। किसी का मालिक नहीं होता, और हर मर्ज एक स्कैवेंजिंग हंट बन जाता है। चेंजेज़ को कुछ स्पष्ट स्थानों तक सीमित रखें।
जनरेटेड इन्टर्नल पर टाइट कपलिंग
अपग्रेड तब दर्दनाक हो जाते हैं जब आपका कस्टम कोड जनरेटेड internal structs, प्राइवेट फील्ड्स, या पैकेज लेआउट विवरणों पर निर्भर करता है। जनरेटेड कोड में छोटा रिफैक्टर भी आपकी बिल्ड तोड़ सकता है।
सुरक्षित सीमाएँ:
- कस्टम एंडपॉइंट्स के लिए आप नियंत्रित request/response DTOs का उपयोग करें।
- जनरेटेड लेयर्स के साथ एक्सपोर्टेड इंटरफेसेज़ या फ़ंक्शंस के माध्यम से इंटरैक्ट करें, न कि internal टाइप्स के साथ।
- मिडलवेयर निर्णय HTTP प्रिमिटिव्स (हेडर, मेथड, पाथ) पर आधारित रखें जहाँ संभव हो।
जहाँ ज़रूरत हो वहाँ टेस्ट स्किप करना
मिडलवेयर और राउटिंग बग टाइम बर्वर होते हैं क्योंकि फेल्योर अक्सर रैंडम 401s या "एन्डपॉइंट नॉट फाउंड" जैसे दिखते हैं। कुछ फोकस्ड टेस्ट घंटों बचाते हैं।
एक वास्तविक उदाहरण: आप ऑडिट मिडलवेयर जोड़ते हैं जो लॉग करने के लिए रिक्वेस्ट बॉडी पढ़ता है, और अचानक कुछ एंडपॉइंट्स को खाली बॉडी मिलना शुरू हो जाता है। राउटर के माध्यम से एक POST भेजकर दोनों: ऑडिट साइड‑इफेक्ट और हैंडलर व्यवहार की जाँच करने वाला छोटा टेस्ट उस रिग्रेशन को पकड़ लेता है और री‑एक्सपोर्ट के बाद भरोसा देता है।
प्री‑रिलीज़ के लिए त्वरित चेकलिस्ट
कस्टम चेंजेज़ शिप करने से पहले एक त्वरित पास करें जो अगली री‑एक्सपोर्ट के दौरान आपकी रक्षा करे। आपको ठीक‑ठीक पता होना चाहिए कि क्या फिर से लागू करना है, कहाँ रहता है और कैसे वेरिफ़ाई करना है।
- सारा कस्टम कोड एक स्पष्ट नाम वाले पैकेज या फोल्डर में रखें (उदा.,
internal/custom/). - जनरेटेड वायरिंग के साथ छूने के पॉइंट्स को एक या दो फाइलों तक सीमित रखें। उन्हें ब्रिज की तरह व्यवहार करें: एक बार रूट्स रजिस्टर करें, एक बार मिडलवेयर रजिस्टर करें।
- मिडलवेयर ऑर्डर और उसका कारण डॉक्यूमेंट करें ("Auth before rate limiting" और क्यों)।
- प्रत्येक कस्टम एन्डपॉइंट के लिए कम से कम एक टेस्ट सुनिश्चित करें कि वह काम करता है।
- एक रिपीटेबल अपग्रेड रूटीन लिखें: री‑एक्सपोर्ट, कस्टम लेयर फिर से लगाएँ, टेस्ट चलाएँ, डिप्लॉय करें।
यदि आप सिर्फ एक चीज़ करें, तो अपग्रेड नोट करें। यह "मुझे लगता है ठीक है" को "हम इसे साबित कर सकते हैं" में बदल देता है।
उदाहरण: ऑडिट लॉगिंग और एक हेल्थ एन्डपॉइंट जोड़ना
मान लें आपने एक Go बैकएंड एक्सपोर्ट किया (उदा., AppMaster से) और आप दो जोड़ियाँ चाहते हैं: रिक्वेस्ट ID प्लस एडमिन एक्शंस के लिए ऑडिट लॉगिंग, और मॉनिटरिंग के लिए एक सरल /health एन्डपॉइंट। लक्ष्य है कि आपकी चेंजेज़ री‑एक्सपोर्ट के बाद आसानी से फिर से लागू हो सकें।
ऑडिट लॉगिंग के लिए, कोड को internal/custom/middleware/ जैसे स्पष्ट मालिकाना स्थान पर रखें। मिडलवेयर बनाएँ जो (1) X-Request-Id पढ़े या जनरेट करे, (2) उसे रिक्वेस्ट कॉन्टेक्स में स्टोर करे, और (3) एडमिन रूट्स के लिए एक छोटा ऑडिट लाइन लॉग करे (method, path, user ID अगर उपलब्ध हो, और result)। हर रिक्वेस्ट के लिए एक लाइन रखें और बड़े पेलोड को डम्प करने से बचें।
इसे एज पर वायर करें, उस जगह के पास जहाँ रूट्स रजिस्टर होते हैं। अगर जनरेटेड राउटर का एक सिंगल सेटअप फ़ाइल है, वहाँ एक छोटा हुक जोड़ें जो आपका मिडलवेयर इम्पोर्ट कर के केवल एडमिन ग्रुप पर लागू करे।
/health के लिए, internal/custom/handlers/health.go में एक छोटा हैंडलर जोड़ें। 200 OK रिटर्न करें और छोटा बॉडी जैसे ok भेजें। अगर मॉनिटर्स को ऑथ की ज़रूरत है तो ही ऑथ जोड़ें और उसे डॉक्यूमेंट करें।
चेंज को री‑अप्रायबल रखने के लिए कमिट स्ट्रक्चर इस तरह रखें:
- Commit 1: Add
internal/custom/middleware/audit.goand tests - Commit 2: Wire middleware into admin routes (smallest diff possible)
- Commit 3: Add
internal/custom/handlers/health.goand register/health
अपग्रेड या री‑एक्सपोर्ट के बाद बेसिक्स वेरिफ़ाई करें: एडमिन रूट्स अभी भी ऑथ की मांग करते हैं, रिक्वेस्ट IDs एडमिन लॉग्स में दिखाई देते हैं, /health तेज़ी से रिस्पॉन्ड करता है, और मिडलवेयर हल्के लोड में नज़दीकी लेटेंसी नहीं जोड़ता।
अगले कदम: एक मेंटेनेबल कस्टमाइज़ेशन वर्कफ़्लो सेट करें
हर एक्सपोर्ट को एक ताजा बिल्ड मानें जिसे आप दोहराकर बना सकते हैं। आपका कस्टम कोड एक ऐड‑ऑन लेयर जैसा महसूस होना चाहिए, न कि एक री‑राइट।
अगली बार तय करें कि क्या कोड में होना चाहिए और क्या नो‑कोड मॉडल में। बिज़नेस नियम, डेटा शेप्स, और मानक CRUD लॉजिक आमतौर पर मॉडल में होना चाहिए। वन‑ऑफ इंटीग्रेशन और कंपनी‑विशिष्ट मिडलवेयर आमतौर पर कस्टम कोड में होना चाहिए।
अगर आप AppMaster (appmaster.io) का उपयोग कर रहे हैं, तो अपने कस्टम काम को जनरेटेड Go बैकएंड के चारों ओर एक साफ़ एक्सटेंशन लेयर के रूप में डिज़ाइन करें: मिडलवेयर, रूट्स और हेल्पर्स को कुछ छोटे फोल्डर्स में रखें जिन्हें आप री‑एक्सपोर्ट्स के पार आगे ले जा सकें, और जनरेटर‑ओनर फ़ाइलों को बिना छुए रखें।
एक व्यावहारिक अंतिम चेक: अगर एक टीम‑मेट एक घंटे से कम समय में री‑एक्सपोर्ट कर सके, आपके स्टेप्स लागू कर सके, और वही रिज़ल्ट प्राप्त कर सके, तो आपका वर्कफ़्लो मेंटेनेबल है।
सामान्य प्रश्न
Don’t edit generator-owned files. Put your changes in a clearly owned package (for example, internal/custom/) and connect them through one small integration point near server startup. That way a re-export mostly replaces generated code while your custom layer stays intact.
Assume anything marked with comments like “Code generated” or “DO NOT EDIT” will be rewritten. Also watch for very uniform folder structures, repetitive naming, and minimal human comments; those are typical generator fingerprints. Your safest rule is to treat all of that as read-only even if it compiles after you edit it.
Keep one “hook” file that imports your custom package and registers everything: middleware, extra routes, and any small wiring. If you find yourself touching five routing files or multiple generated handlers, you’re drifting toward a fork that will be painful to upgrade.
Write middleware in your own package and keep it narrow, like request IDs, audit logging, rate limits, or special headers. Then register it once at the router or HTTP stack creation point, not per-route inside generated handlers. A quick httptest check for one expected header or status code is usually enough to catch regressions after re-export.
Define the endpoint contract first, then implement the handler in your custom package and register the route at the same integration point you use for middleware. Keep the handler simple: validate input, call existing services, return a consistent error shape, and avoid copying generated handler logic. This keeps your change portable to a fresh export.
Routes can shift when the generator changes route registration order, grouping, or middleware chains. To protect yourself, rely on a stable registration seam and keep middleware order documented right next to the registration line. If ordering matters (for example, auth before audit), encode it intentionally and verify behavior with a small test.
If you implement the same rule in both places, they will drift over time and you’ll get confusing behavior. Put business rules that non-developers should adjust (fields, validation, workflows, permissions) in the no-code model, and keep infrastructure concerns (logging, auth integration, rate limits, headers) in your custom Go layer. The split should be obvious to anyone reading the repo.
Generated DTOs and internal structs can change across exports, so isolate that churn at the boundary. Convert inputs into your own internal structs, run your domain logic on those, then convert outputs back at the edge. When types shift after re-export, you update one adapter instead of chasing compile errors across your whole custom layer.
Separate generated updates from your custom work in Git so you can see what changed and why. A practical flow is to commit the re-exported generated changes first, then commit the minimal wiring and custom-layer adjustments. Keeping a short custom changelog that says what you added and where it lives makes the next upgrade much faster.
Do a dry-run re-export in a separate branch, build it, and run a short regression pass before merging your custom layer back in. After that, reapply customizations through the same seams each time, then validate a few key endpoints plus one unhappy path per endpoint. If something can’t be expressed through a seam, add one new seam once and keep future changes flowing through it.


