2010-06-03 15 views
25

मैं एक सरल HTTP सर्वर लिख रहा हूं जो क्लाइंट के रूप में अधिकतर curl से PUT अनुरोध स्वीकार करेगा और मुझे Expect: 100-continue शीर्षलेख को संभालने के साथ कुछ समस्या हो रही है।"100 जारी रखें" HTTP संदेश को कैसे संभालें?

के रूप में मैं इसे समझते हैं, सर्वर, शीर्ष लेख को पढ़ने के कनेक्शन पर एक HTTP/1.1 100 Continue प्रतिक्रिया वापस भेज धारा Content-Length पर मूल्य तक पढ़ और फिर वापस असली जवाब कोड (आमतौर पर HTTP/1.1 200 OK लेकिन किसी अन्य भेजने के लिए माना जाता है वैध HTTP उत्तर करना चाहिए)।

ठीक है, यह वही है जो मेरा सर्वर करता है। समस्या यह है कि, जाहिर है, अगर मैं 100 Continue उत्तर भेजता हूं, तो curl किसी भी बाद के HTTP त्रुटि कोड की रिपोर्ट करने में विफल रहता है और मानता है कि अपलोड सफल रहा। उदाहरण के लिए, यदि सामग्री की प्रकृति के कारण अपलोड अस्वीकार कर दिया गया है (एक मूल डेटा जांच हो रही है), मैं चाहता हूं कि कॉलिंग क्लाइंट समस्या का पता लगाने और तदनुसार कार्य करे।

क्या मुझे कुछ याद आ रही है?

संपादित करें: यहाँ एक माध्यमिक हेडर के साथ cURL से एक नमूना उत्पादन एक त्रुटि युक्त:

> PUT /test1%2Epdf HTTP/1.1 
> Authorization: Basic xxxx 
> User-Agent: curl/7.20.0 (i386-pc-win32) libcurl/7.20.0 OpenSSL/0.9.8l zlib/1.2.3 
> Host: localhost 
> Accept: */* 
> Content-Length: 24 
> Expect: 100-continue 
> 
< HTTP/1.1 100 Continue 
< HTTP/1.1 415 Unsupported Media Type 
< Connection: close 
< Content-Type: text/xml 
< Content-Length: 289 
< 
+0

है नहीं तो आप के बाद 'HTTP/1.1 100 CONTINUE' रिक्त पंक्ति की ज़रूरत है? – YOU

+1

एक है। तथ्य यह है कि यह लॉग नहीं किया जा रहा है curl के साथ एक प्रदर्शन मुद्दा प्रतीत होता है। – Stephane

+0

बस स्पष्ट करने के लिए, एक पूरी तरह से मान्य HTTP प्रतिक्रिया वापस भेजें ('HTTP/1.1 100 जारी रखें \ r \ n \ r \ n') न केवल स्ट्रिंग' HTTP/1.1 100 जारी रखें "। curl क्लाइंट तब तक इंतजार करेगा जब तक कि वह उन दो अनुक्रम प्राप्त करता है, और यदि यह छोड़ देता है, तो यह "100-जारी रखने के लिए प्रतीक्षा कर रहा है" संदेश आउटपुट (वर्बोज मोड में) होगा। – bishop

उत्तर

9

आप libcURL उपयोग कर रहे हैं अपने क्लाइंट-साइड प्रोग्राम लिखने के लिए आप के लिए CURLOPT_FAILONERROR विकल्प सेट सुनिश्चित करें प्रयास 1। उदाहरण के लिए, सी में, आप की तरह कुछ करना होगा:

curl_easy_setopt (curl_handle, CURLOPT_FAILONERROR, 1L); 

libcURL documentation के अनुसार, इस विकल्प "यदि HTTP कोड लौटे पुस्तकालय बताता चुपचाप विफल के बराबर या 400 से भी बड़ा है"

इसके अलावा, प्रलेखन यह स्पष्ट करता है कि "डिफ़ॉल्ट कार्रवाई पृष्ठ को सामान्य रूप से वापस करने के लिए होगी, उस कोड को अनदेखा कर देगा।"

यदि आप कर्ल कमांड लाइन टूल का उपयोग कर रहे हैं, तो बस अपने कर्ल कमांड में -f या --fail जोड़कर ऊपर वर्णित जैसा व्यवहार होगा। यह कर्ल man page में भी वर्णित है।

ध्यान दें कि इन दोनों तरीकों असफल-सुरक्षित नहीं कर रहे हैं, के रूप में स्पष्ट रूप से डॉक्स में कहा गया है:

"This method is not fail-safe and there are occasions where non-successful response codes will slip through, especially when authentication is involved (response codes 401 and 407)."

+0

के बाद एक खाली रेखा है मैं कमांड लाइन उपकरण का उपयोग कर रहा हूं लेकिन -फ फ्लैग इस बात को प्रभावित नहीं करता है कि उपकरण कैसे व्यवहार करता है। मैंने तब से अपना खुद का क्लाइंट लिखने के लिए बस गए हैं जो इन असफल अपलोड को सही तरीके से संभालता है। उत्तर के लिए धन्यवाद, हालांकि – Stephane

6

असल में वहाँ असली हैडर होना चाहिए 100 हैडर जारी के बाद

तो, मैं आम तौर पर इस पर पसंद करते हैं ग्राहक की ओर।

$contents=curl_exec($ch); 

list($header, $contents) = explode("\r\n\r\n", $contents , 2); 
if(strpos($header," 100 Continue")!==false){ 
    list($header, $contents) = explode("\r\n\r\n", $contents , 2); 
} 
+0

ठीक है, मैं कोड 100 उत्तर के बाद एक असली शीर्षलेख भेजता हूं। ऐसा लगता है कि curl परवाह नहीं है, यद्यपि। – Stephane

3

, 100 के बाद लाइन (RFC 2616, Section 6 देखें) जारी एक खाली पंक्ति (CRLF) जोड़ने

+0

ऐसा लगता है कि गायब रेखा एक बग है। मैंने कोड की जांच की है और "100 जारी रखें" – Stephane

19

मैं जानता हूँ कि इस पुरानी है, लेकिन यहाँ की "100 जारी रखें"

मेरी समझ है आपका सर्वर क्लाइंट से अकेले हेडर के आधार पर अनुरोध को सत्यापित करना है यानी यदि अनुरोध अमान्य है, "100 जारी रखें" भेजें लेकिन वास्तविक http त्रुटि इसके बजाय 403. यह क्लाइंट को डेटा को पोस्ट करने से रोक सकता है जो मैं समझता हूं कि सर्वर पर राउंडट्रिप का पूरा बिंदु है (यानी ग्राहक "100 जारी रखने" के लिए प्रतीक्षा कर रहा है)।

यदि आप वास्तविक पोस्ट किए गए डेटा को सत्यापित कर रहे हैं, तो आपको यहां उच्च स्तरीय प्रोटोकॉल लागू करने की आवश्यकता है यानी।वैध HTTP प्रतिक्रिया सामग्री में लिपटे आपकी त्रुटि भेजें। हां, यह सीमा की तरह लगता है और मुझे लगता है कि यह प्रोटोकॉल सीमा नहीं है; एक बार से अधिक सर्वर प्रतिक्रिया को संभालने के लिए क्लाइंट भ्रम की संभावना अधिक है।

+3

उत्तर के लिए धन्यवाद। आप सही हैं: यह एक पुराना सवाल है लेकिन आपको यह बहुत सही लगता है। मेरा असली मुद्दा यह है कि, "100" सफलता त्रुटि कोड नहीं है: क्लाइंट को हमेशा वास्तविक प्रतिक्रिया में निहित रिटर्न कोड की जांच करनी चाहिए। जाहिर है, यह नहीं है कि curl क्या कर रहा है। – Stephane

+0

"यह क्लाइंट को डेटा पोस्ट करने से रोकना चाहिए" - यह शायद आरएफसी का सबसे गलत समझा हिस्सा है। 100-जारी रखने की कमी क्लाइंट को जारी रखने से नहीं रोकती है, आरएफसी ने स्पष्ट रूप से कहा है कि ग्राहक अनुरोध निकाय भेजना जारी रख सकता है। दरअसल प्रतिक्रिया का प्रबंधन करने का एकमात्र वैध तरीका शरीर को भेजना या डिस्कनेक्ट करना है। –

+0

कर्ल/वेब सर्वर द्वारा इस गलतफहमी पर अतिरिक्त सहायक पृष्ठभूमि अगर लोग कर्ल मेलिंग सूची में रूचि रखते हैं: [पोस्ट पर और 100-जारी रखने के साथ PUT पर] (https://curl.haxx.se/mail/lib-2004- 08/0002.html) – paperclip

4

आप का जवाब पर विस्तार से चर्चा करते हैं और अभी भी एक उदाहरण के रूप PHP का उपयोग:

ऐसा नहीं है कि कई 100 Continue शीर्षलेख प्राप्त किया जा सकता है संभव है। मैं धीरे धीरे हेडर के माध्यम से काम करते हैं और 100 Continue प्रतिक्रियाओं में से प्रत्येक को दूर करने के निम्न का उपयोग कर यदि वे मौजूद:

<?php 
// a little setup first 
$ch = curl_init(); 
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); 
curl_setopt($ch,CURLOPT_HEADER,1); 
// etc... 
$str = curl_exec($ch); 

// the goods 
$delimiter = "\r\n\r\n"; // HTTP header delimiter 
// check if the 100 Continue header exists 
while (preg_match('#^HTTP/[0-9\\.]+\s+100\s+Continue#i',$str)) { 
    $tmp = explode($delimiter,$str,2); // grab the 100 Continue header 
    $str = $tmp[1]; // update the response, purging the most recent 100 Continue header 
} // repeat 

// now we just have the normal header and the body 
$parts = explode($delimiter,$str,2); 
$header = $parts[0]; 
$body = $parts[1]; 
?> 
+0

यह मुझे बचाया, धन्यवाद! – Aidin

संबंधित मुद्दे