आजकल लगभग सभी वेब डेवलपमेंट फ्रेमवर्क के साथ किया जाता है। चाहे आप Rails, Sinatra, या Lotus का उपयोग करें, आपको वास्तव में यह सोचने की ज़रूरत नहीं है कि कुकीज़ और अन्य हेडर्स Nginx या Apache से एप्लिकेशन सर्वर और फिर आपके ऐप तक कैसे पहुँचते हैं। वे बस पहुँच जाते हैं।
HTTP हेडर्स क्या हैं?
जब भी कोई वेब ब्राउज़र रिक्वेस्ट भेजता है, तो उसके साथ HTTP हेडर्स नामक चीज़ें भेजी जाती हैं। इनमें कुकीज़, यूज़र एजेंट के बारे में जानकारी, कैशिंग जानकारी — बहुत सारा उपयोगी सामान होता है।
आप अपने ब्राउज़र के डेवलपमेंट टूल्स में रिक्वेस्ट देखकर देख सकते हैं कि कौन से हेडर्स भेजे जा रहे हैं। यहाँ एक उदाहरण है। जैसा कि आप देख सकते हैं, हेडर्स कोई जादुई चीज़ नहीं हैं। वे बस एक खास तरीके से फ़ॉर्मेट किया गया टेक्स्ट हैं।

हेडर्स आपके ऐप तक कैसे नहीं पहुँचते
अगर आपने कभी Rack ऐप लिखा है, तो आपने शायद env हैश देखा होगा, जिसमें ऐप के एनवायरनमेंट वेरिएबल्स होते हैं। अगर आप इसके अंदर देखें, तो पाएंगे कि सामान्य सिस्टम एनवायरनमेंट वेरिएबल्स के अलावा, इसमें सभी रिक्वेस्ट हेडर्स भी होते हैं।
# config.ru
run lambda { |env| [200, {"Content-Type" => "text/plain"}, [env.inspect]] }
# आउटपुट:
# { "HTTP_HOST"=>"localhost:9000", "HTTP_CONNECTION"=>"keep-alive", "HTTP_PRAGMA"=>"no-cache", "HTTP_CACHE_CONTROL"=>"no-cache", "HTTP_ACCEPT"=>"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "HTTP_UPGRADE_INSECURE_REQUESTS"=>"1", "HTTP_USER_AGENT"=>"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36", ... }
यह नहीं है कि Nginx आपके ऐप को हेडर्स कैसे भेजता है। :)
एप्लिकेशन सर्वर्स
आजकल, अधिकांश Ruby वेब ऐप्स Unicorn जैसे एप्लिकेशन सर्वर्स पर चलते हैं। चूंकि ऐप सर्वर्स Nginx द्वारा स्पॉन नहीं किए जाते, Nginx उनके एनवायरनमेंट वेरिएबल्स सेट नहीं कर सकता।
तो हेडर्स Nginx से Unicorn तक कैसे पहुँचते हैं? सरल। जब Nginx रिक्वेस्ट को ऐप सर्वर को फ़ॉरवर्ड करता है, तो वह पूरी रिक्वेस्ट — हेडर्स सहित — भेजता है।
यह दिखाने के लिए, मैंने एक सिंपल एप्लिकेशन सर्वर बनाया जो Nginx द्वारा भेजी गई हर चीज़ को STDOUT पर डंप करता है।
require "socket"
# सॉकेट बनाएं और इसे फाइल सिस्टम में "सेव" करें
server = UNIXServer.new('/tmp/socktest.sock')
# Nginx द्वारा कनेक्शन का इंतज़ार करें
socket = server.accept
# सॉकेट से सब कुछ पढ़ें
while line = socket.readline
puts line.inspect
end
socket.close
अगर आप Nginx को Unicorn के बजाय इस सर्वर से कनेक्ट करने के लिए कॉन्फ़िगर करते हैं, तो आप ठीक वही देखेंगे जो ऐप सर्वर को भेजा जा रहा है: बस एक नॉर्मल HTTP रिक्वेस्ट। हेडर्स और सब कुछ।

सिंपल अपस्ट्रीम ऐप सर्वर लिखने के बारे में अधिक जानकारी के लिए, यूनिक्स सॉकेट्स पर मेरी पोस्ट देखें।
फिर एनवायरनमेंट वेरिएबल्स का झंझट क्यों?
1993 में, NSCA ने "कॉमन गेटवे इंटरफ़ेस" या संक्षेप में CGI नामक किसी चीज़ के लिए एक स्पेक प्रकाशित किया।

यह Apache जैसे सर्वर्स के लिए डिस्क पर मनमाने प्रोग्राम चलाकर डायनामिक वेबपेज जनरेट करने का एक तरीका था। एक यूज़र पेज रिक्वेस्ट करता, और Apache सचमुच शेल आउट करके रिजल्ट जनरेट करने के लिए एक प्रोग्राम चलाता। चूंकि Apache ऐप्स को सीधे स्पॉन करता था, इसलिए वह उनके एनवायरनमेंट वेरिएबल्स सेट कर सकता था।
CGI स्टैंडर्ड निर्दिष्ट करता है कि HTTP हेडर्स को एनवायरनमेंट वेरिएबल्स के रूप में पास किया जाए। और मौजूदा एनवायरनमेंट वेरिएबल्स के साथ किसी भी नाम टकराव से बचने के लिए, यह निर्दिष्ट करता है कि नाम के आगे "HTTP_" प्रीपेंड किया जाना चाहिए।
तो आपके पास एनवायरनमेंट वेरिएबल्स का एक गुच्छा होता है जो इस तरह दिखते हैं:
HTTP_ACCEPT="text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
HTTP_ACCEPT_CHARSET="ISO-8859-1,utf-8;q=0.7,*;q=0.7"
HTTP_ACCEPT_ENCODING="gzip, deflate"
HTTP_ACCEPT_LANGUAGE="en-us,en;q=0.5"
HTTP_CONNECTION="keep-alive"
HTTP_HOST="example.com"
HTTP_USER_AGENT="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:5.0) Gecko/20100101 Firefox/5.0"
आजकल नई डेवलपमेंट के लिए शायद ही कोई CGI का उपयोग करता है, लेकिन HTTP हेडर्स को एनवायरनमेंट वेरिएबल्स के रूप में स्टोर होते देखना अभी भी बहुत आम है — भले ही वे कभी-कभी नकली एनवायरनमेंट वेरिएबल्स हों।
ऐप सर्वर्स इसे कैसे नकली बनाते हैं
एप्लिकेशन सर्वर्स रॉ HTTP रिक्वेस्ट से हेडर्स को पार्स करते हैं। तो वे एनवायरनमेंट में कैसे पहुँचते हैं? खैर, ऐप सर्वर उन्हें वहाँ रखता है।
मैंने WEBrick में थोड़ा खोजबीन की और स्मोकिंग गन ढूंढ निकाला:
self.each{|key, val|
next if /^content-type$/i =~ key
next if /^content-length$/i =~ key
name = "HTTP_" + key
name.gsub!(/-/o, "_")
name.upcase!
meta[name] = val
}
आखिरकार, ये "नकली" एनवायरनमेंट वेरिएबल्स अन्य अधिक वास्तविक एनवायरनमेंट वेरिएबल्स के साथ मर्ज हो जाते हैं और आपके Rack ऐप में पास किए जाते हैं और फिर Rails तक, जो उन्हें वापस एनवायरनमेंट हैश से निकाल लेता है। :)