Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ProxyError: 407: Authentification required #540

Closed
hein3r opened this issue Feb 23, 2024 · 5 comments
Closed

ProxyError: 407: Authentification required #540

hein3r opened this issue Feb 23, 2024 · 5 comments
Assignees

Comments

@hein3r
Copy link

hein3r commented Feb 23, 2024

Hi guys,

I am sitting behind a company firewall and have to use our proxy for any requests.

In other projects we relied on the requests package. Everything works fine here:

import requests
proxies = {
    'http': 'http://[DOMAIN]%5C[USER]:[PWD]@[HOST]:8080'
} 
 r = requests.get("http://www.google.com", proxies=proxies)

However, having specified the exact same URL for the proxy in the googleads.yaml I get the following error for any request:

urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='ads.google.com', port=443): Max retries exceeded with url: /apis/ads/publisher/v202402/ActivityService?wsdl (Caused by ProxyError('Unable to connect to proxy', OSError('Tunnel connection failed: 407 authenticationrequired')))

For example:
ad_manager_client = ad_manager.AdManagerClient.LoadFromStorage("googleads.yaml")
activity_service = ad_manager_client.GetService('ActivityService', version='v202402')

Any suggestions?

Thanks in advance.

@msaniscalchi
Copy link
Contributor

Hello,

I strongly suspect the core issue here is that you're defining the proxy outside of the library. As currently implemented, we use ProxyConfig to pass the proxy details along to Zeep. This can be configured in googleads.yaml, or passed along as an argument for AdManagerClient if you prefer to set it up manually.

Regards,
Mark

@msaniscalchi msaniscalchi self-assigned this Feb 23, 2024
@hein3r
Copy link
Author

hein3r commented Feb 26, 2024

Hi Mark,

thanks for the quick reply.

I doubt that this is the case (maybe my hint about requests was misleading, because I do not use this in the current Google Ads project).

I do specify the proxy in the googleads.yaml like so:

proxy_config:
    'http': 'http://[DOMAIN]%5C[USER]:[PWD]@[HOST]:8080'

This config is then used

from googleads import ad_manager
ad_manager_client = ad_manager.AdManagerClient.LoadFromStorage("googleads.yaml")
activity_service = ad_manager_client.GetService('ActivityService', version='v202402')

When I try to get the ActivityService for example, I get the 407.

@msaniscalchi
Copy link
Contributor

Hello,

Thanks for clarifying, I had in fact misinterpreted that original post, sorry about that!

So, I'll be upfront about it–it would be quite difficult for me to troubleshoot your specific proxy issue, but I can say that the fact you received an HTTP 407 response strongly suggests that the library passed along your proxy configuration to Zeep, which then made the request, and did at least communicate with your proxy so that it could return the authentication error. I'd like to at least provide some explanation on why this doesn't appear to be an issue with this library though, so read on if that interests you.

Looking at the underlying implementation, LoadFromStorage eventually extracts a ProxyConfig based on your proxy_config found in googleads.yaml. When you call GetService, that ProxyConfig is then passed to GetServiceClassForLibrary, which uses ZeepServiceProxy to initialize a transport with the ProxyConfig, which is used by Zeep's Client to handle communication. I can confirm that the proxy configuration is passed to Zeep and should be applied to its requests, so as far as this library is concerned it appears to be working as intended.

For some additional context, the transport created above is a _ZeepProxyTransport, which applies the proxies to the Session used by the Zeep Client to make requests. As an example, for the GetService call, Zeep eventually calls the transport's _load_remote_data, where the following is used to retrieve the WSDL:

        response = self.session.get(url, timeout=self.load_timeout)

Once again, I can confirm that the proxy configuration is applied to the session used to make the call, so it appears to be working as intended.

@hein3r
Copy link
Author

hein3r commented Feb 29, 2024

Hi Marc,
thank you for this extensive explanation. With that I was able to resolve the issue.
Figuring out that request does in fact handle Zeep's transport, I worked up a minimal example for a proxied session. As it turned out, request was ignoring the explicitly configured proxy in favor of a environment varible that was still set and I didn't know about. Removing that env var (either by session.trust_env=False or manually) the proxy config was then recognized correctly.
Thanks again and best regards

@hein3r hein3r closed this as completed Feb 29, 2024
@msaniscalchi
Copy link
Contributor

Great, happy to hear you were able to figure it out!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants