@@ -35,6 +35,7 @@ public function __construct(ZendClient $client = null, ResponseFactory $response
3535 */
3636 public function sendRequest (RequestInterface $ request )
3737 {
38+ $ request = $ this ->sanitizeRequest ($ request );
3839 $ headers = new Headers ();
3940
4041 foreach ($ request ->getHeaders () as $ key => $ value ) {
@@ -44,10 +45,25 @@ public function sendRequest(RequestInterface $request)
4445 $ zendRequest = new Request ();
4546 $ zendRequest ->setMethod ($ request ->getMethod ());
4647 $ zendRequest ->setUri ((string ) $ request ->getUri ());
47- $ zendRequest ->setVersion ($ request ->getProtocolVersion ());
4848 $ zendRequest ->setHeaders ($ headers );
4949 $ zendRequest ->setContent ($ request ->getBody ()->getContents ());
5050
51+ $ options = [
52+ 'httpversion ' => $ request ->getProtocolVersion (),
53+ ];
54+
55+ if (extension_loaded ('curl ' )) {
56+ $ options ['curloptions ' ] = [
57+ CURLOPT_HTTP_VERSION => $ this ->getProtocolVersion ($ request ->getProtocolVersion ()),
58+ ];
59+ }
60+
61+ $ this ->client ->setOptions ($ options );
62+
63+ if ($ this ->client ->getAdapter () instanceof ZendClient \Adapter \Curl && $ request ->getMethod ()) {
64+ $ request = $ request ->withHeader ('Content-Length ' , '0 ' );
65+ }
66+
5167 try {
5268 $ zendResponse = $ this ->client ->send ($ zendRequest );
5369 } catch (RuntimeException $ exception ) {
@@ -62,4 +78,77 @@ public function sendRequest(RequestInterface $request)
6278 $ zendResponse ->getVersion ()
6379 );
6480 }
81+
82+ private function sanitizeRequest (RequestInterface $ request )
83+ {
84+ $ request = $ this ->sanitizeWithTrace ($ request );
85+ $ request = $ this ->sanitizeWithCurl ($ request );
86+
87+ return $ request ;
88+ }
89+
90+ /**
91+ * Zend request remove the body if it's a trace but does not rewrite the content length header,
92+ * This can lead to error from the server has it can expect a specific content length, but don't have
93+ * a body, so we set content-length to 0 to avoid bad reading from the server.
94+ *
95+ * @param RequestInterface $request
96+ *
97+ * @return RequestInterface|static
98+ */
99+ private function sanitizeWithTrace (RequestInterface $ request )
100+ {
101+ if ($ request ->getMethod () === 'TRACE ' ) {
102+ $ request = $ request ->withHeader ('Content-Length ' , '0 ' );
103+ }
104+
105+ return $ request ;
106+ }
107+
108+ /**
109+ * Get specific curl options for Zend Curl Adapter
110+ *
111+ * @param RequestInterface $request
112+ *
113+ * @return RequestInterface|static
114+ */
115+ private function sanitizeWithCurl (RequestInterface $ request )
116+ {
117+ if ($ this ->client ->getAdapter () instanceof ZendClient \Adapter \Curl && !in_array ($ request ->getMethod (), [
118+ 'POST ' ,
119+ 'PUT ' ,
120+ 'PATCH '
121+ ], true )) {
122+
123+ $ request = $ request ->withHeader ('Content-Length ' , '0 ' );
124+ }
125+
126+ return $ request ;
127+ }
128+
129+ /**
130+ * Return cURL constant for specified HTTP version
131+ *
132+ * @param string $requestVersion
133+ *
134+ * @throws \UnexpectedValueException if unsupported version requested
135+ *
136+ * @return int
137+ */
138+ private function getProtocolVersion ($ requestVersion )
139+ {
140+ switch ($ requestVersion ) {
141+ case '1.0 ' :
142+ return CURL_HTTP_VERSION_1_0 ;
143+ case '1.1 ' :
144+ return CURL_HTTP_VERSION_1_1 ;
145+ case '2.0 ' :
146+ if (defined ('CURL_HTTP_VERSION_2_0 ' )) {
147+ return CURL_HTTP_VERSION_2_0 ;
148+ }
149+ throw new \UnexpectedValueException ('libcurl 7.33 needed for HTTP 2.0 support ' );
150+ }
151+
152+ return CURL_HTTP_VERSION_NONE ;
153+ }
65154}
0 commit comments