Closed machinehum closed 1 week ago
@bshaffer Any thoughts?
@Hectorhammett (who is on rotation this week)
Just by skimming this, I know when I've used proxies in the past I've had to set "verify" to "false" in the guzzle client constructor.
I would suggest working directly with the guzzle client, and even making an HTTP call to our APIs directly with the guzzle client, instead of using the GAPIC client (you can authenticate using these instructions). Because if you can get that to work, then your above code should work as well. That will at least help you isolate the issue, to know if the problem is in your Guzzle configuration or your Google Client configuration.
Looking at your code, everything looks fine, so I'm guessing you need to configure something differently in guzzle. If that's not the case, we can help you debug from there. Good luck!
I'm working on doing more tests as you described, but to be clearer on the initial issue: Nothing I do in the Guzzle configurations has any effect whatsoever. The configured Guzzle object shows up in e.g. GapicClientTrait debug as I shared before, but as far as I can tell that client is being completely ignored and a default one used when it comes time to actually make the OAuth requests. So either injecting it in the manner I did isn't actually supported, or there's a bug in the library that's causing it to be ignored. Can you clarify whether that method of injecting a Guzzle client should actually work?
I would pass in the client like this:
use Google\Auth\HttpHandler\HttpHandlerFactory;
use Google\Analytics\Admin\V1beta\Client\AnalyticsAdminServiceClient;
$proxyHttpClient = new \GuzzleHttp\Client([
'proxy' => 'http://foo.com:3128',
'exceptions' => false,
'base_uri' => 'https://www.googleapis.com'
]);
$proxyHttpHandler = HttpHandlerFactory::build($proxyHttpClient);
$adminClient = new AnalyticsAdminServiceClient([
// pass the HTTP handler in to the "credentialsConfig" option
'credentialsConfig' => ['authHttpHandler' => $proxyHttpHandler],
// ensure we are using "rest" transport (gRPC is the default when the grpc.so extension is enabled)
'transport' => 'rest',
// set the http handler on the RestTransport
'transportConfig' => ['rest' => ['httpHandler' => $proxyHttpHandler]]
]);
Testing this way, it seems to work. I'm going to keep testing to narrow down where the issue in the original code is.
One note: using the created Guzzle client for authHttpHandler
worked, but trying to use it in the rest transport config caused a fatal error in RestTransport (with or without a proxy set in the Guzzle client). Here's my test code:
`use Google\Auth\ApplicationDefaultCredentials; use GuzzleHttp\Client; use GuzzleHttp\HandlerStack; use Google\Auth\HttpHandler\HttpHandlerFactory; use Google\Analytics\Admin\V1beta\Client\AnalyticsAdminServiceClient; use Google\Analytics\Admin\V1beta\GetPropertyRequest; use Google\Analytics\Admin\V1beta\Property; use Google\ApiCore\ApiException;
// specify the path to your application credentials putenv('GOOGLE_APPLICATION_CREDENTIALS=credentials.json');
// define the scopes for your API call $scopes = ['https://www.googleapis.com/auth/drive.readonly','https://www.googleapis.com/auth/analytics.edit', 'https://www.googleapis.com/auth/analytics.manage.users', 'https://www.googleapis.com/auth/analytics.manage.users.readonly', 'https://www.googleapis.com/auth/analytics.readonly'];
// create middleware $middleware = ApplicationDefaultCredentials::getMiddleware($scopes); $stack = HandlerStack::create(); $stack->push($middleware);
// create the HTTP client $client = new Client([ // 'proxy' => 'http://foo.com', 'verify' => false, 'exceptions' => false, 'handler' => $stack, 'base_uri' => 'https://www.googleapis.com', 'auth' => 'google_auth' // authorize all requests ]);
// make the request $response = $client->get('drive/v2/files');
// show the result! print_r((string) $response->getBody());
$proxyHttpHandler = HttpHandlerFactory::build($client);
$adminClient = new AnalyticsAdminServiceClient([ // pass the HTTP handler in to the "credentialsConfig" option 'credentialsConfig' => ['authHttpHandler' => $proxyHttpHandler], // ensure we are using "rest" transport (gRPC is the default when the grpc.so extension is enabled) 'transport' => 'rest', // set the http handler on the RestTransport 'transportConfig' => ['rest' => ['httpHandler' => $proxyHttpHandler]] ]);
$request = (new GetPropertyRequest()) ->setName('properties/9999999999999');
$response = $adminClient->getProperty($request); print_r((string) $response->getBody());`
The drive call works as expected. The AnalyticsAdminServiceClient call issues this fatal:
`Fatal error: Uncaught Error: Call to undefined method GuzzleHttp\Psr7\Response::then() in /vendor/google/gax/src/Transport/RestTransport.php:123 Stack trace:
thrown in /vendor/google/gax/src/Transport/RestTransport.php on line 123`
That error is because it's expecting a Promise but it's getting a Response. That can be fixed by calling async
on the HttpHandler instead of just passing in the handler, e.g. passing in this to the transport config instead of $httpHandler
:
[$httpHandler, 'async']
Any updates @machinehum ? Did the suggested solution worked?
Closed due inactivities! If you need more assistance please let us know!
I'm trying to retrieve Google Analytics 4 data with the google cloud PHP libraries and having a devil of a time with proxy settings (server is behind an outbound proxy). I'll start by saying that if I set the
https_proxy
env var, then everything works as expected, so my config is working otherwise. For various reasons that's not ideal and I'd rather deal with it in code, and that seems to be supported via things like passing anauthHttpHandler
to CredentialsWrapper, or rest transport configs, but I've tried a hundred permutations and can't make it work. I also can't find solid docs.Here's one example (slightly simplified):
This code times out at the proxy, at the first step of trying to reach oauth.googleapis.com. If I set
https_proxy
env var, it works. When I do some debug inspecting in CredentialsWrapper, it seems to be getting the correct arguments. I inspected a bunch of things at various points of GapicClientTrait::buildClientOptions and ::setClientOptions, and it seemed right. I tried a few permutations of the client constructor arguments, for example usingcredentialsConfig
instead of constructing the CredentialsWrapper. No difference.This feels hard to call a "bug" because there isn't real clear documentation the right way to do this, but I'm hoping to get some help here. In case it's useful this is what the credentialWrapper looks like at the end of GapicClientTrait:: setClientOptions: