Guzzle always convert all my headers to lowercase - php

I have a script that uses guzzle to make an API call. The api server checks for headers and it is case sensitive.
Below is an example code of mine
<?php
$headers = [
'set_headers' => [
'Connection' => 'Keep-Alive',
'Accept-Encoding' => ‘gzip’,
'Accept-Language' => ‘en_US’,
'US-Token' => '1f23a-d234s-3s45d-452g',
'AToken' => 'XXXX'
],
];
// Build HTTP request object.
$request = \GuzzleHttp\Psr7\Request( // Throws (they didn't document that properly).
'POST',
'htps://api.website.com/',
$headers,
bodystream() //StreamInterface
);
// Default request options (immutable after client creation).
$_guzzleClient = new \GuzzleHttp\Client([
'handler' => $stack, // Our middleware is now injected.
'allow_redirects' => [
'max' => 8, // Allow up to eight redirects (that's plenty).
],
'connect_timeout' => 30.0, // Give up trying to connect after 30s.
'decode_content' => true, // Decode gzip/deflate/etc HTTP responses.
'timeout' => 240.0, // Maximum per-request time (seconds).
// Tells Guzzle to stop throwing exceptions on non-"2xx" HTTP codes,
// thus ensuring that it only triggers exceptions on socket errors!
// We'll instead MANUALLY be throwing on certain other HTTP codes.
'http_errors' => false,
]);
// Add critically important options for authenticating the request.
$guzzleOptions = [
'cookies' => ($_cookieJar instanceof CookieJar ? $_cookieJar : false),
'verify' => file_exists('/etc/ssl/certs/cacert.pem') ? '/etc/ssl/certs/cacert.pem' : $_verifySSL,
'proxy' => ($_proxy !== null ? $_proxy : null),
'curl' => [
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2, // Make http client work with HTTP 2/0
CURLOPT_SSLVERSION => 1,
CURLOPT_SSL_VERIFYPEER => false
]
];
// Attempt the request. Will throw in case of socket errors!
$response = $_guzzleClient->send($request, $guzzleOptions); ?>
I tested the same request with cURL and it works perfectly. Is there a way I can rectify this in the guzzle php library, thanks in advance.

Related

Error: Failure when receiving data from the peer php GuzzleHttp

I'm trying to make post request and the post request is working but I'm not getting the response
$client = new \GuzzleHttp\Client(['headers' => ['Authorization' => 'Basic ' . 'token==']]);
$data = $client->post(
'url',
[
'form_params' => [
'address' => 'addreww',
'name' => 'Zia Sultan',
'phone_number' => '2136000000',
]
]
);
return $data;
What I'm getting in my insomnia
Error: Failure when receiving data from the peer
You're code is working, post method returns ResponseInterface, we need to fetch the content from it, we need to first fetch the StreamInterface by calling getBody() and chaining it will getContents() gives us the actual response. Keep debug mode On, to get find the exact error for Error: Failure when receiving data from the peer, and when this error occurs, share the entire trace with us
try {
$response = (new \GuzzleHttp\Client())->post(
'url',
[
'headers' => [
'Authorization' => 'Basic ' . 'token=='
],
'form_params' => [
'address' => 'addreww',
'name' => 'Zia Sultan',
'phone_number' => '2136000000',
],
// 'http_errors' => false, // Set to false to disable throwing exceptions on an HTTP protocol errors (i.e., 4xx and 5xx responses)
// 'debug' => true,
// 'connect_timeout' => 30 // number of seconds to wait while trying to connect to a server, Use 0 to wait indefinitely (the default behavior)
// 'read_timeout' => 10 // timeout to use when reading a streamed body, default value is default_socket_timeout in php.ini
// 'timeout' => 30 // the total timeout of the request in seconds. Use 0 to wait indefinitely (the default behavior).
]
);
return $response->getBody()->getContents();
} catch (Throwable $exception) {
print_r($exception);
}
I was returning the data only but I needed to return getBody() like this way
$data->getBody()
Its working now

How to set GuzzleHttp verify to false in Laravel app

I want to use a package (Cloudinary) to upload an image, after all the setup, I am getting an error
This is the code from Cloudinary documentation,
$uploadedFileUrl = cloudinary()->upload($request->file('profile_image')->getRealPath())->getSecurePath();
So I can't set Guzzle verification to false in this way
$client = new Client([
'base_uri' => ''
, 'headers' => $headers,
'verify' => false,
'VERIFY_PEER' => true,
'http_errors' => false,
]);
My problem is, how do I set Guzzle Http Client verification to false, generally in the application
If you want to add any Guzzlehttp's options within Laravel app you can just use the withOptions method.
https://laravel.com/docs/9.x/http-client#guzzle-options
Http::withOptions([
'verify' => false,
])->get('http://whatever.com');

cURL error 60: SSL certificate problem: self signed certificate (see http://curl.haxx.se/libcurl/c/libcurl-errors.html)

I use Guzzle in my Laravel 5.8 project
I'm trying to make a GET to a URL (signed cert) serve on https
"https://172.1.1.1:443/accounts"
public static function get($url) {
// dd($url);
try {
$client = new Client();
$options = [
'http_errors' => true,
'connect_timeout' => 3.14,
'read_timeout' => 3.14,
'timeout' => 3.14,
'curl' => array(
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_SSL_VERIFYPEER => false
)
];
$headers = [
'headers' => [
'Keep-Alive' => 'timeout=300'
]
];
$result = $client->request('GET', $url, $headers, $options);
// dd($result);
} catch (ConnectException $e) {
//Logging::error($e);
return null;
}
return json_decode($result->getBody(), true);
}
I used these 2 flags already
CURLOPT_SSL_VERIFYHOST => false,
URLOPT_SSL_VERIFYPEER => false
I'm not sure why I kept getting,
the only sensible explanation (short of cosmic rays and ram errors) is that Client (whatever Client is) is either overriding your custom curl settings, or ignoring them. there should be no way to get that error with CURLOPT_SSL_VERIFYHOST & CURLOPT_SSL_VERIFYPEER disabled.
... btw if that is a Guzzle\Client, have you tried adding 'verify' => 'false' to $options ? that's supposedly the guzzle-way of disabling it, wouldn't surprise me if Guzzle is overriding your custom settings because of Guzzle's verify option not being disabled (it's enabled by default)
I'm agree with #hanshenrik, I tested it and it's the exact problem. By default the client you create have the following configuration:
$defaults = [
'allow_redirects' => RedirectMiddleware::$defaultSettings,
'http_errors' => true,
'decode_content' => true,
'verify' => true,
'cookies' => false
];
So you have to change it to:
public static function get($url) {
// dd($url);
try {
$client = new Client(['verify' => false]);
$options = [
'http_errors' => true,
'connect_timeout' => 3.14,
'read_timeout' => 3.14,
'timeout' => 3.14
)
];
$headers = [
'headers' => [
'Keep-Alive' => 'timeout=300'
]
];
$result = $client->request('GET', $url, $headers, $options);
// dd($result);
} catch (ConnectException $e) {
//Logging::error($e);
return null;
}
return json_decode($result->getBody(), true);
}

How to set CURLOPT_PROXY in Guzzle right way?

I am trying to set CURLOPT_PROXY but it doesn't work. Curl is enabled. If I do this by "raw" curl request - everything works.. So? What could be the solution?
$client = new GuzzleHttp\Client();
$res = $client->get('http://www.ipmango.com/api/myip', [
'config' => [
'curl' => [
'CURLOPT_PROXY' => '194.135.220.18:8081',
],
]
]);
echo $res->getBody(); // displays my ip addess, not that what I set.
I spent numerous hours finding out myself that you will also need to set the option CURLOPT_HTTPPROXYTUNNEL to 1. So something like:
<?php
$res = $client->get('http://www.ipmango.com/api/myip', [
'config' => [
'curl' => [
'CURLOPT_PROXY' => '194.135.220.18:8081',
'CURLOPT_HTTPPROXYTUNNEL' => 1,
]
]
]);
GuzzleHttp Client automatically detects if environment variables HTTP_PROXY and HTTPS_PROXY are set.
(see lines 165-175 of \path\to\project\vendor\guzzlehttp\guzzle\src\Client.php)
So set both HTTP_PROXY=http://ip:port and HTTPS_PROXY=https://ip:port as system environment variables. Now restart your command line, and rerun php artisan serve
You may be able to configure authentication for your proxy in the environment variable as well, if it's required
Guzzle docs give info about setting proxy for a single request
$client->request('GET', '/', ['proxy' => 'tcp://localhost:8125']);
http://docs.guzzlephp.org/en/latest/request-options.html#proxy
But you can set it to all requests when initializing client
$client = new Client([
'base_uri' => 'http://doma.in/',
'timeout' => 10.0,
'cookie' => true,
'proxy' => 'tcp://12.34.56.78:3128',
]);

Privoxy, Tor and cURL using Zend HTTP

I am really stuck in this, and need expert help. Let me explain what I am trying achieve and the setup. I had a script which posts over a https form using Zend_Http_Client. On the server setup I have tor & privoxy running. Everything just worked fine, but now I need to make the code more scalable by running multiple instances of tor & privoxy on the same server.
Hence I shifted the Adapter for Zend from Zend_Http_Client_Adapter_Curl to Zend_Http_Client_Adapter_Proxy . But after changing the adapter I have bumped into a strange error which says - 400 Invalid header received from client and when I dump the object of Zend client, I see the following -
MyWebClientResponse::__set_state(array(
'json' => NULL,
'version' => '1.1',
'code' => 400,
'message' => 'Invalid header received from client',
'headers' =>
array (
'Proxy-agent' => 'Privoxy 3.0.19',
'Content-type' => 'text/plain',
'Connection' => 'close',
),
'body' => 'Invalid header received from client.
',
))
I do not understand what is that I am doing wrong. The code is done in Yii Framework so it is hard to share all the classes and Models, but I am sharing the main parts of the code, which are responsible for this -
$client = MyWebClient::factory();
$adapter = $client->getAdapter();
$adapter->setConfig(array('timeout' => 120,
'proxy_host' => 'localhost',
'proxy_port' => 8124
));
$client->setAdapter($adapter);
$client->setCookieJar(true);
$client->setParameterPost(array(
'name' => 'firstname',
'password' => 'password,
'login' => 'home'
));
$response = $client->setUri('https://www.domain.com/post.php')->requestApi('POST', false);
Here's the constructor of the class MyWebClient, just in case it it required, all other methods are standard.
static public function factory($new = false)
{
if (!isset(self::$client))
{
self::$client = new MyWebClient();
self::$client->setConfig(array(
'adapter' => 'Zend_Http_Client_Adapter_Proxy',
// 'proxy_host' => 'localhost',
// 'proxy_port' => 8118,
'persistent' => false,
'timeout' => 120
));
}
return self::$client;
}
The headers are being set in the requestAPI method and the snippet is -
$headers = array(
'X-PHX' => 'true',
'X-Requested-With' => 'XMLHttpRequest',
'Referer' => 'https://domain.com/index.html',
'User-Agent' => self::getRandomUserAgent()
);
$this->setHeaders($headers);
I would really appreciate help in this regard. Think it's privoxy which is not letting go the request out of the server.
Sachin
Looks like you may need to wrap the user-agent with quotes. Try this when setting the headers and see if that fixes the problem.
$headers = array(
'X-PHX' => 'true',
'X-Requested-With' => 'XMLHttpRequest',
'Referer' => 'https://domain.com/index.html',
'User-Agent' => "'".self::getRandomUserAgent()."'"
);
$this->setHeaders($headers);
Finally I decided to use the native cURL library and the cookieJar which comes with it. It worked like expected.
Cheers,
Sachin

Categories