All the connections from my spring boot application which connect to an external service must be routed through a proxy.
I am using Squidmen for mocking a local proxy with provided services for 127.0.0.1 on port 3333.
To test if the proxy is working, I can make the following request and see the request in the Squidmen access logs.
curl -x http://127.0.0.1:3333 -L http://google.ch
I found this similar issue to configure my spring boot application. So I'm setting my environment variables as follows:
http.proxyHost=127.0.0.1
http.proxyPort=3333
http.proxySet=true
https.proxyHost=127.0.0.1
https.proxyPort=3333
https.proxySet=true
server.use-forwarded-headers=true
Analog to my curl request, this is my java request:
URL url = new URL("https://google.com");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
System.out.println(con.getResponseCode());
System.out.println(con.getHeaderField("Content-Type"));
However, with the specified configuration the request is not forward to the proxy. How can I make sure that these kind of request to external serivces are routed through the proxy.
Related
I'm using java.net.Proxy to connect to my server via Nginx proxy. The Nginx proxy is SSL enabled. My server URL is https.
When I try the example code below I'm getting 400 error:
client sent plain HTTP request to HTTPS port while reading client request headers
This is probably happening since I cannot specify in the code "https" as the proxy ip address so Nginx proxy thinks its an http request, and generates the error.
It works fine when Nginx proxy SSL is disabled or when I connect directly to my server.
Can this be solved programatically, or only by configuring the Nginx proxy to redirect http requests to https ?
String url = "https://myserver.com";
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("1.2.3.4", 444));
HttpURLConnection con = (HttpURLConnection) (new URL(url).openConnection(proxy));
con.connect();
We are using spring-security-saml for our SAML authentication. The app is working fine and when we try to run the app on demo machine, the connection to SAML metadata url is timing out.
we have given the metadata url in our application.yml as
security:
saml2:
metadata-url: https://dev-715244.oktapreview.com/app/<app_id>/sso/saml/metadata
Tried setting the proxy to the jvm while running the jar but same issue is there. But this URL is reachable through CURL.
Any idea as to how to set proxy details to the HTTP Client used by spring SAML?
Yes, you need to create a bean as follows to your WebSecurityConfig:
#Bean
public HttpClient httpClient() {
HttpClient client = new HttpClient(this.multiThreadedHttpConnectionManager);
HostConfiguration hostConfiguration = new HostConfiguration();
hostConfiguration.setProxy("PROXYHOST", PROXYPORT);
client.setHostConfiguration(hostConfiguration);
return client;
}
I wrote Java code to login to Salesforce and ran this code on a firewalled server. For this, I have to specify the proxy url and proxy port before connecting to Salesforce due to the firewall. However, I'm getting an unknownhostexception error for the proxy url. If I try to login via curl with the proxy settings, I am able to connect. How come there is a problem connecting using Java then? Any help is appreciated.
Apparently the issue was caused by JVM configs. We have to configure JVM to use the proxy settings as follows:
System.setProperty("http.proxyHost", crmProxyURL);
System.setProperty("http.proxyPort", crmProxyPort);
Depending on your HTTP library the System settings might not be enough or not needed. In the Salesforce context it is quite possible that one would try using the Jetty HTTP Client. In this case the System properties are ignored and proxy needs to be handled by the Jetty client:
ProxyConfiguration proxyConfig = httpClient.getProxyConfiguration();
HttpProxy proxy = new HttpProxy("proxyHost", proxyPort);
proxyConfig.getProxies().add(proxy);
The Apache HTTP Client, another popular choice, also uses its own little mechanism:
HttpHost proxy = new HttpHost("proxyHost", proxyPort, "https");
RequestConfig config = RequestConfig.custom().setProxy(proxy).build();
HttpGet request = new HttpGet(someURL);
request.setConfig(config);
Interesting here: one can specify to use http or https as the proxy protocol.
In general I found using one of the http client much easier that the JDK low level functions.
I was using Jersey 2.25 client with Jackson, I configured everything correctly in Jersey, it worked normally on my development machine when I ran it in a test class, but Jersey client could never connect to a certain host that we have when deployed on our STG environment and always throws a read timeout exception.
I also know that the problem is not in our environment because I can connect using curl
But when switched to HTTPClient it worked normally.
This is how we created our Jersey Client:
Client client = ClientBuilder.newBuilder()
.register(JacksonFeature.class)
.property(ClientProperties.CONNECT_TIMEOUT,5000)
.property(ClientProperties.READ_TIMEOUT,15000)
.build();
The only difference here is the flow of the app, and also the major change that happens in the flow that could affect the connection is that somewhere before calling the Jersey client another class sets a proxy in the system config:
System.setProperty("http.proxyHost",strProxyHost);
System.setProperty("http.proxyPort",strProxyPort);
System.setProperty("https.proxyHost",strProxyHost);
System.setProperty("https.proxyPort",strProxyPort);
However we can establish a connection normally using HTTPClient:
HttpConnectionManagerParams params = new HttpConnectionManagerParams();
params.setConnectionTimeout(5000);
params.setSoTimeout(10000);
HttpConnectionManager manager = new SimpleHttpConnectionManager();
manager.setParams(params);
HttpClient httpClient = new HttpClient(manager);
We are using HTTPClient 3 because part of this app is legacy and we cannot update the version, but it works normally.
What could be causing this connection problem with Jersey? is there something global that Jersey reads when it's trying to connect?
Jersey by default uses HttpURLConnection and HttpURLConnection uses following global settings for proxy configuration -
System.setProperty("http.proxyHost",strProxyHost);
System.setProperty("http.proxyPort",strProxyPort);
System.setProperty("https.proxyHost",strProxyHost);
System.setProperty("https.proxyPort",strProxyPort);
It means if these system variables are set, Jersey will send all the requests through this configured proxy. Check Details here
However, Apache HttpClient does not follow these settings. For using proxy in Apache HttpClient, you have to use HostConfiguration class. Check details here
So, now to your problem, It looks that your STG environment is not able to connect to specified proxy but able to connect with the service directly.
So, while using Jersey, client is not able to connect to proxy and hence ReadTimeoutException is occurring. Since, you haven't configured HttpClient for using any proxy, it is able to connect with the service directly.
I have an EJB Stateless Bean that is executed automatically by an Scheduler inside Websphere. My EJB is installed in Websphere. Inside my EJB I would like to make an http request to a webservice exposed by other application (inside de same Server). I tried just using relative path because that is how I usually make requests between applications, but inside my bean I don't know how to get the host name and port to build the URL.
I managed to get the host (ip) by doing this:
InetAddress.getLocalHost().toString();
But I also require the port number. The question is: how to get the host and port number of the application server (Websphere) where my EJB application is installed? Is this possible?
This code is how I try to make the request, but this does not work because I need the full path:
URL url = new URL("/MyOtherAppName/myservice");
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("Content-Length",
Integer.toString(urlParameters.getBytes().length));
connection.setRequestProperty("Content-Language", "en-US");
connection.setUseCaches(false);
connection.setDoOutput(true);
-edit 1 ----
I think the approach of user Gas is nice, and makes my application easier to configure.
I followed this guide to implement the URL Provider approach:
URL Provider Websphere
I'd suggest different approach, rather than getting server host and port use the URL resource and then get it in the EJB. It will be more portable across servers and also more flexible in case you ever move your service somewhere else.
See Using URL resources within an application
Define URL via console in app server, and use #Resource annotation in your EJB like this:
#Resource(name="serviceURL", lookup="url/myurl")
URL myURL;