Guzzle अपवाद को हैंडल करें और HTTP बॉडी प्राप्त करें


122

जब सर्वर 4xx और 5xx स्थिति कोड लौटाता है, तो मैं गुज़ल से त्रुटियों को संभालना चाहूंगा। मैं इस तरह से एक अनुरोध करता हूं:

$client = $this->getGuzzleClient();
$request = $client->post($url, $headers, $value);
try {
    $response = $request->send();
    return $response->getBody();
} catch (\Exception $e) {
    // How can I get the response body?
}

$e->getMessageकोड जानकारी देता है, लेकिन HTTP प्रतिक्रिया का मुख्य भाग नहीं है। मुझे प्रतिक्रिया निकाय कैसे मिल सकता है?


1
यह प्रश्न इस प्रश्न से संबंधित है stackoverflow.com/questions/17658283/… और उत्तर कुछ मदद के भी हो सकते हैं।
ट्रेंडफिशर

जवाबों:


84

गज़ल 3.x

प्रति डॉक्स , आप (उचित अपवाद प्रकार पकड़ कर सकते हैं ClientErrorResponseException4xx त्रुटियों के लिए) और उसके फोन getResponse()प्रतिक्रिया ऑब्जेक्ट प्राप्त करने के लिए विधि है, तो फोन getBody()पर:

use Guzzle\Http\Exception\ClientErrorResponseException;

...

try {
    $response = $request->send();
} catch (ClientErrorResponseException $exception) {
    $responseBody = $exception->getResponse()->getBody(true);
}

फ़ंक्शन trueको पास करना getBodyइंगित करता है कि आप प्रतिक्रिया शरीर को एक स्ट्रिंग के रूप में प्राप्त करना चाहते हैं। अन्यथा आप इसे कक्षा के रूप में प्राप्त करेंगे Guzzle\Http\EntityBody


232

गुझिया 6.x

प्रति डॉक्स , अपवाद प्रकार आप पकड़ की जरूरत हो सकती हैं:

  • GuzzleHttp\Exception\ClientException 400-स्तरीय त्रुटियों के लिए
  • GuzzleHttp\Exception\ServerException 500-स्तरीय त्रुटियों के लिए
  • GuzzleHttp\Exception\BadResponseException दोनों के लिए (यह उनकी सुपरक्लास है)

इस तरह की त्रुटियों को संभालने के लिए कोड अब कुछ इस तरह दिखता है:

$client = new GuzzleHttp\Client;
try {
    $client->get('http://google.com/nosuchpage');    
}
catch (GuzzleHttp\Exception\ClientException $e) {
    $response = $e->getResponse();
    $responseBodyAsString = $response->getBody()->getContents();
}

12
मेरे $response->getBody()->getContents()लिए एक खाली स्ट्रिंग लौटाएगा। मैं फिर डॉक्स में इस पर ठोकर खाई : \GuzzleHttp\Psr7\str($e->getResponse()) Psr7 स्ट्रिंग के रूप में प्रतिक्रिया को कास्टिंग करना मुझे एक अच्छी तरह से स्वरूपित और पूर्ण त्रुटि संदेश मिला।
एंडी प्लेस

3
PSA 7 पर एक नज़र डालने के बाद @AndyPlace (जो डॉक्स के खंड द्वारा संदर्भित नहीं था जिसे मैं उस समय लिंक करता हूं जो मैंने यह उत्तर लिखा था, लेकिन अब यह तुरंत मेरे लिए स्पष्ट नहीं है कि कॉलिंग के Psr7\str()अलग परिणाम क्यों होंगे को ->getContents()। क्या आपके पास इसका प्रदर्शन करने वाला एक न्यूनतम उदाहरण है, जो शायद मुझे यह समझने दे और शायद इस उत्तर को अपडेट करूं?
मार्क ऐमी

24
इस बात का उल्लेख करते हुए कि 'http_errors' => falseविकल्प को गुज़ले अनुरोध में पारित किया जा सकता है जो अपवादों को फेंकने में अक्षम है। फिर आप $response->getBody()किसी भी स्थिति के साथ शरीर प्राप्त कर सकते हैं कि स्थिति कोड क्या है, और यदि आवश्यक हो तो आप स्थिति कोड का परीक्षण कर सकते हैं $response->getStatusCode()
कांपना

2
@AndyPlace के रूप में, $response->getBody()->getContents()मुझे एक मामले में एक खाली स्ट्रिंग देता है, मुझे समझ नहीं आता कि क्यों। लेकिन \GuzzleHttp\Psr7\str()सभी HTTP प्रतिसाद को एक स्ट्रिंग के रूप में देता है, और मैं केवल HTTP निकाय का उपयोग करता हूं। जैसा कि प्रलेखन में कहा गया है , शरीर को स्ट्रिंग के लिए कास्टिंग करके इस्तेमाल किया जा सकता है। $stringBody = (string) $clientException->getResponse()->getBody();
एंथनीबी

1
इसने मेरे लिए यह किया, हालांकि मुझे \GuzzleHttp\Exception\RequestExceptionइसके बजाय एक 400स्थिति कोड वापस मिल रहा था । {{$ request-> api ('POST', 'endpoint.json') आज़माएँ; } catch (RequestException $ e) {print_r ($ e-> getResponse () -> getBody () -> getContents ()); }
जेपिकारस

54

जबकि उपरोक्त उत्तर अच्छे हैं, वे नेटवर्क त्रुटियों को नहीं पकड़ेंगे। जैसा कि मार्क ने उल्लेख किया है, BadResponseException सिर्फ ClientException और ServerException के लिए एक सुपर क्लास है। लेकिन RequestException भी BadResponseException का एक सुपर क्लास है। केवल 400 और 500 त्रुटियों के लिए RequestException को फेंक दिया जाएगा, लेकिन नेटवर्क त्रुटियों और अनंत पुनर्निर्देशन भी। तो मान लें कि आप नीचे पेज का अनुरोध करते हैं, लेकिन आपका नेटवर्क चल रहा है और आपका कैच केवल BadResponseException की अपेक्षा कर रहा है। खैर आपका आवेदन एक त्रुटि फेंक देगा।

इस मामले में बेहतर है कि RequestException की उम्मीद करें और प्रतिक्रिया के लिए जांच करें।

try {
  $client->get('http://123123123.com')
} catch (RequestException $e) {

  // If there are network errors, we need to ensure the application doesn't crash.
  // if $e->hasResponse is not null we can attempt to get the message
  // Otherwise, we'll just pass a network unavailable message.
  if ($e->hasResponse()) {
    $exception = (string) $e->getResponse()->getBody();
    $exception = json_decode($exception);
    return new JsonResponse($exception, $e->getCode());
  } else {
    return new JsonResponse($e->getMessage(), 503);
  }

}

है JsonResponseguzzle से एक वर्ग?
शाम

JsonResponseसिम्फनी से आता है
चाप

14

२०१ ९ के अनुसार यहाँ मैं ऊपर दिए गए उत्तरों से विस्तृत हूँ और अपवाद को संभालने के लिए गूज़ल डॉक्स , प्रतिक्रिया निकाय, स्थिति कोड, संदेश और कभी-कभी मूल्यवान प्रतिक्रिया आइटम प्राप्त करता हूं ।

try {
    /**
     * We use Guzzle to make an HTTP request somewhere in the
     * following theMethodMayThrowException().
     */
    $result = theMethodMayThrowException();
} catch (\GuzzleHttp\Exception\RequestException $e) {
    /**
     * Here we actually catch the instance of GuzzleHttp\Psr7\Response
     * (find it in ./vendor/guzzlehttp/psr7/src/Response.php) with all
     * its own and its 'Message' trait's methods. See more explanations below.
     *
     * So you can have: HTTP status code, message, headers and body.
     * Just check the exception object has the response before.
     */
    if ($e->hasResponse()) {
        $response = $e->getResponse();
        var_dump($response->getStatusCode()); // HTTP status code;
        var_dump($response->getReasonPhrase()); // Response message;
        var_dump((string) $response->getBody()); // Body, normally it is JSON;
        var_dump(json_decode((string) $response->getBody())); // Body as the decoded JSON;
        var_dump($response->getHeaders()); // Headers array;
        var_dump($response->hasHeader('Content-Type')); // Is the header presented?
        var_dump($response->getHeader('Content-Type')[0]); // Concrete header value;
    }
}
// process $result etc. ...

देखा। आपको प्रतिक्रिया की जानकारी आसानी से अलग की गई वस्तुओं में मिलती है।

साइड नोट्स:

catchक्‍लॉज के साथ हम इनहेरिटेंस चेन PHP रूट अपवाद क्‍लास \Exceptionको पकड़ते हैं क्‍योंकि गुज्‍जले कस्‍टम अपवाद इसे बढ़ाते हैं।

यह दृष्टिकोण उन मामलों के उपयोग के लिए उपयोगी हो सकता है, जहां गज़ल का उपयोग लारवेल या एडब्ल्यूएस एपीआई पीएचडी एसडीके जैसे हुड के तहत किया जाता है ताकि आप वास्तविक गज़ल अपवाद को पकड़ न सकें।

इस मामले में, अपवाद वर्ग गज़ल डॉक्स (उदाहरण GuzzleHttp\Exception\RequestExceptionके लिए मूल अपवाद के रूप में) में उल्लिखित नहीं हो सकता है ।

इसलिए आपको \Exceptionइसके बजाय पकड़ना होगा लेकिन ध्यान रखें कि यह अभी भी गुज़ले अपवाद वर्ग का उदाहरण है।

हालांकि देखभाल के साथ उपयोग करें। उन आवरणों में गुज्झल $e->getResponse()वस्तु के वास्तविक तरीके उपलब्ध नहीं हो सकते हैं। इस मामले में, आपको रैपर के वास्तविक अपवाद स्रोत कोड को देखना होगा और यह पता लगाना होगा कि गज़ल $responseके तरीकों का उपयोग करने के बजाय स्थिति, संदेश आदि कैसे प्राप्त करें ।

यदि आप सीधे अपने आप को गुज्झल कहते हैं, तो आप अपने उपयोग के मामले की शर्तों के संबंध GuzzleHttp\Exception\RequestExceptionमें उनके अपवाद डॉक्स में किसी को भी पकड़ सकते हैं।


1
$responseजब तक आपने जाँच $e->hasResponse()न की $responseहो , अपवादों को संभालते समय आपको अपने ऑब्जेक्ट पर तरीकों को कॉल नहीं करना चाहिए , अन्यथा हो सकता है nullऔर किसी भी तरीके की कॉल एक घातक त्रुटि का कारण होगी।
pwaring

@pwaring, सच। बिल्कुल जैसा कि गुज़ले अपवाद डॉक्स कहते हैं। उत्तर अपडेट किया गया। धन्यवाद।
वेलेंटाइन शि

1
... लेकिन यह तय होने के बाद भी समस्याग्रस्त है। आप सभी अपवादों को पकड़ रहे हैं, न केवल गज़ल वाले, बल्कि फिर आप $e->hasResponseपरिणाम पर कॉल कर रहे हैं , एक विधि जो निश्चित रूप से, गैर-गज़ल अपवादों के लिए मौजूद नहीं है। इसलिए यदि आप एक गैर-गुज़ले अपवाद को उठाते हैं theMethodMayThrowException(), तो यह कोड इसे पकड़ लेगा, गैर-मौजूद पद्धति को कॉल करने का प्रयास करेगा, और गैर-मौजूद विधि के कारण दुर्घटनाग्रस्त हो जाएगा, प्रभावी रूप से त्रुटि का असली कारण छिपाएगा। इससे बचने के GuzzleHttp\Exception\RequestExceptionबजाय प्रिफरेबल को पकड़ना होगा Exception
मार्क अमेरी

1
@ मार्की, आपकी बात पूरी तरह से मान्य है। धन्यवाद। मैंने उत्तर निकाय को अद्यतन किया।
वेलेंटाइन शी

1
@JaberAlNahian सुनकर खुशी हुई :) कि मेरा इरादा था। हमेशा स्वागत है।
वेलेंटाइन शी

4

अगर 'http_errors' => falseगुज्जर अनुरोध विकल्पों में डाला जाता है, तो यह 4xx या 5xx त्रुटि प्राप्त करते समय थ्रो अपवाद को रोक देगा, जैसे $client->get(url, ['http_errors' => false]):। तब आप प्रतिक्रिया को पार्स करते हैं, इससे कोई फर्क नहीं पड़ता कि यह ठीक है या त्रुटि, यह अधिक जानकारी के लिए प्रतिक्रिया में होगा


यह प्रश्न त्रुटि त्रुटियों को रोकने के लिए नहीं पूछ रहे हैंडल त्रुटियों के बारे में है
Dlk
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.