1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
14: namespace Cake\Http\Client\Adapter;
15:
16: use Cake\Http\Client\AdapterInterface;
17: use Cake\Http\Client\Request;
18: use Cake\Http\Client\Response;
19: use Cake\Http\Exception\HttpException;
20:
21: 22: 23: 24: 25: 26: 27: 28:
29: class Curl implements AdapterInterface
30: {
31: 32: 33:
34: public function send(Request $request, array $options)
35: {
36: $ch = curl_init();
37: $options = $this->buildOptions($request, $options);
38: curl_setopt_array($ch, $options);
39:
40: $body = $this->exec($ch);
41: if ($body === false) {
42: $errorCode = curl_errno($ch);
43: $error = curl_error($ch);
44: curl_close($ch);
45:
46: $status = 500;
47: if ($errorCode === CURLE_OPERATION_TIMEOUTED) {
48: $status = 504;
49: }
50: throw new HttpException("cURL Error ({$errorCode}) {$error}", $status);
51: }
52:
53: $responses = $this->createResponse($ch, $body);
54: curl_close($ch);
55:
56: return $responses;
57: }
58:
59: 60: 61: 62: 63: 64: 65:
66: public function buildOptions(Request $request, array $options)
67: {
68: $headers = [];
69: foreach ($request->getHeaders() as $key => $values) {
70: $headers[] = $key . ': ' . implode(', ', $values);
71: }
72:
73: $out = [
74: CURLOPT_URL => (string)$request->getUri(),
75: CURLOPT_HTTP_VERSION => $request->getProtocolVersion(),
76: CURLOPT_RETURNTRANSFER => true,
77: CURLOPT_HEADER => true,
78: CURLOPT_HTTPHEADER => $headers
79: ];
80: switch ($request->getMethod()) {
81: case Request::METHOD_GET:
82: $out[CURLOPT_HTTPGET] = true;
83: break;
84:
85: case Request::METHOD_POST:
86: $out[CURLOPT_POST] = true;
87: break;
88:
89: default:
90: $out[CURLOPT_POST] = true;
91: $out[CURLOPT_CUSTOMREQUEST] = $request->getMethod();
92: break;
93: }
94:
95: $body = $request->getBody();
96: if ($body) {
97: $body->rewind();
98: $out[CURLOPT_POSTFIELDS] = $body->getContents();
99: }
100:
101: if (empty($options['ssl_cafile'])) {
102: $options['ssl_cafile'] = CORE_PATH . 'config' . DIRECTORY_SEPARATOR . 'cacert.pem';
103: }
104: if (!empty($options['ssl_verify_host'])) {
105:
106: $options['ssl_verify_host'] = 2;
107: }
108: $optionMap = [
109: 'timeout' => CURLOPT_TIMEOUT,
110: 'ssl_verify_peer' => CURLOPT_SSL_VERIFYPEER,
111: 'ssl_verify_host' => CURLOPT_SSL_VERIFYHOST,
112: 'ssl_cafile' => CURLOPT_CAINFO,
113: 'ssl_local_cert' => CURLOPT_SSLCERT,
114: 'ssl_passphrase' => CURLOPT_SSLCERTPASSWD,
115: ];
116: foreach ($optionMap as $option => $curlOpt) {
117: if (isset($options[$option])) {
118: $out[$curlOpt] = $options[$option];
119: }
120: }
121: if (isset($options['proxy']['proxy'])) {
122: $out[CURLOPT_PROXY] = $options['proxy']['proxy'];
123: }
124: if (isset($options['proxy']['username'])) {
125: $password = !empty($options['proxy']['password']) ? $options['proxy']['password'] : '';
126: $out[CURLOPT_PROXYUSERPWD] = $options['proxy']['username'] . ':' . $password;
127: }
128: if (isset($options['curl']) && is_array($options['curl'])) {
129:
130: foreach ($options['curl'] as $key => $value) {
131: $out[$key] = $value;
132: }
133: }
134:
135: return $out;
136: }
137:
138: 139: 140: 141: 142: 143: 144:
145: protected function createResponse($handle, $responseData)
146: {
147: $headerSize = curl_getinfo($handle, CURLINFO_HEADER_SIZE);
148: $headers = trim(substr($responseData, 0, $headerSize));
149: $body = substr($responseData, $headerSize);
150: $response = new Response(explode("\r\n", $headers), $body);
151:
152: return [$response];
153: }
154:
155: 156: 157: 158: 159: 160:
161: protected function exec($ch)
162: {
163: return curl_exec($ch);
164: }
165: }
166: