How to set GuzzleHttp verify to false in Laravel app - php

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');

Related

Guzzle always convert all my headers to lowercase

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.

problem accessing soap web service's production environment

I hope this question won't be marked as duplicate as I read many related questions and answers on the site: although I tried most of the suggestions out there I still couldn't resolve my problem.
My codebase : (I left comments on purpose to give an idea of what I have been trying so far, based on my browsing)
try {
$opts = array(
//~mrossw 'http' => array(
//~mrossw 'user_agent' => 'PHPSoapClient'
//~mrossw ),
//~mrossw 'socket' => array('bindto' => '158.69.189.149')
'socket' => array('bindto' => '127.0.0.1')
//~mrossw ,
//~mrossw 'ssl' => [
//~mrossw 'verify_peer' => true,
//~mrossw 'verify_peer_name' => true,
//~mrossw 'allow_self_signed' => true
//~mrossw ]
);
$context = stream_context_create($opts);
$client = new SoapClient("https://ws_provider_hostname:xxxx/foo/bar/blah/Operaciones/OpFooBarBlahReqABCS?wsdl",
//~mrossw $client = new SoapClient($doc_root.'OpCotizadorVehiculoExtReqABCS.xml',
array(
'location' => "https://ws_provider_hostname:xxxx/foo/bar/blah/Operaciones/OpFooBarBlahReqABCS?wsdl",
'uri' => "https://ws_provider_hostname:xxxx/foo/bar/blah/Operaciones",
// Stuff for development.
'trace' => 1,
'exceptions' => true,
'keep_alive' => true,
'connection_timeout' => 120,
'stream_context' => $context,
'cache_wsdl' => WSDL_CACHE_NONE,
'compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP | SOAP_COMPRESSION_DEFLATE,
//~mrossw 'local_cert' => $certRequest_param['sslcertfile'],
//~mrossw 'login'=>'username',
//~mrossw 'password' => 'password'
)
);
} catch (Exception $e) {
echo \"<h2>Exception Error!</h2>\";
echo $e->getMessage();
// print_r($e);
}
The WS provider has an dev environment on port xxxx and a prod env on port yyyy. Hostname and path request are the same.
SoapClient instanciation and operation call work perfect in dev env.
When i change the port to fetch against prod env I get the following error:
SOAP-ERROR: Parsing WSDL: Couldn't load from 'https://ws_provider_hostname:xxxx/foo/bar/blah/Operaciones/OpFooBarBlahReqABCS?wsdl' : failed to load external entity "https://ws_provider_hostname:xxxx/foo/bar/blah/Operaciones/OpFooBarBlahReqABCS?wsdl"
Provider says my public web server's IP is correctly set as allowed in their firewall. It looks right because when I tried to run the code from a different server with different IP and it fails with the same error in both dev and prod env.
When I run that code from a server inside a private network, it works in both
environment ! I don't know much about security, but this sounds to me like a security breach. I mention it here though, in case it can give a clue. I guess this is because this server has a private ip and the provider's firewall don't filter it.
When I go to https://ws_provider_hostname:xxxx/foo/bar/blah/Operaciones/OpFooBarBlahReqABCS?wsdl in my PC browser i get the correct wsdl's xml.
Do you have an idea of what can prevent the code to work form my public web server ?
Or maybe what else can I check ?
For example I couldn't find a way to check the ws server's http response code from outside my browser.
I could neither get a curl request form bash to return the wsdl xml, but that should be another question maybe.
Also let me know if i can provide any other relevant test or data.

PHP: Is it better to close SoapClient connection?

I created the following helper function:
function mainSoap(){
return new SoapClient('https://soap.url',[
'stream_context' => stream_context_create([
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
]
]);
]);
}
and I'm using it like $result=mainSoap()->GetSometing($parameters);
Everything works fine, but in terms of performance, I would like to know if is better to close the soap connection or not.
UPDATE
I created another function in order to close the connection after getting the response, but I still could't find a close method for SoapClient.
function mainSoap(string $call=null, array $vars=[]){
$url="https://soap.url";
$wsdl=new SoapClient($url,[
'trace' => false,
'keep_alive' => false,
'stream_context' => stream_context_create([
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
]
]),
'compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP | SOAP_COMPRESSION_DEFLATE
]);
$response=$wsdl->__soapCall($call,$vars);
//Looking for something like $wsdl->close();
return $response;
}
and I'm using it like $result=mainSoap('GetSometing',[$parameters]);
The SoapClient follows the normal HTTP Request life cycle,
That is to say, your SoapClient does not maintain a constant connection to the server, it will only connect out and receive data when called, similarly to how your browser does not maintain a connection to a server once a request completes, as the request is terminated, unless you set keep_alive to true.
So, in short, you can't "close" a SoapClient because there's nothing to close after you've called it, it's already closed the connection.
Relevant Links:
Wikipedia article on Http (Persistent Connections Section)
MDN Documentation on Keep-Alive header

Why does Laravel create a new session after a GuzzleHttp POST request to the same subdomain?

I'm trying to make a post request to the same subdomain with GuzzleHttp in a Laravel 5.1 installation, but as a response the login page is returned, showing that a new Session has been created in the request. The current session is not affected.
Why does Laravel create a new session?
In session.php I have the following values:
'driver' => env('SESSION_DRIVER', 'file'),
'lifetime' => 120,
'expire_on_close' => true,
'files' => storage_path('framework/sessions'),
'cookie' => 'admin_mydomain_com_session',
'path' => '/',
'domain' => 'admin.mydomain.com',
'secure' => false
In my controller I use the following code to make the request:
// Create headers
$headers = array(
'X-CSRF-Token' => csrf_token()
);
// Create data
$data = array(
'param' => 'param',
'_token' => csrf_token()
);
// Create a POST request
$client = new Client();
$res = $client->request('POST', 'http://admin.mydomain.com/my-url',
array(
'headers' => $headers,
'form_params' => $data
)
);
$statusCode = $res->getStatusCode();
$body = $res->getBody();
echo $body; // Shows me the login page
The answer is really to understand how sessions work. When you make a request via a browser lets say, the response issued by the server will include a cookie with a session id. That id is what identifies you to the server. When you navigate a site through your browser the request it issues includes the cookies.
So when your creating a request via Guzzle your leaving out the cookie from the previous response. Hence the server will always create a new session id for you.

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',
]);

Categories