I have implemented a WS client in Java from an existing WSDL I got.
I can connect, invoke WS methods and everything works great. But....
I am supposed to use a Proxy for communication!!!
Already tried many ways to do that, but nothing works:
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("host",Integer.parseInt("8008")));
URL url = new URL(theUrl);
HttpURLConnection uc = (HttpURLConnection)url.openConnection(proxy);
uc.connect();
Or i tried
System.setPropertry(String, String)
So can set host and proxy and proxySet= true.
But according to colleagues this is not what I should do as it sets global properties and it will not work with many individual runs within out System.
Any ideas how I am supposed to do this?
Any help appreciated, thanks
Eventually I used a class to extend java.net.ProxySelector let's call it MyProxySelector.java
And in the implemented select() method, I check the URI, if it is a URI I which to connect through a proxy, that is the Web service's URI then I create a proxy:
SocketAddress addr = new InetSocketAddress(theHost, thePort);
proxy = new Proxy(Proxy.Type.HTTP, addr);
add it to my proxy list:
List<Proxy> proxyList = new ArrayList<Proxy>();
proxyList.add(proxy);
and return the proxy list.
Related
I can successfully reach following OData-service using different browsers and also using Postman even so I am behind a proxy:
String SERVICE_ROOT = http://services.odata.org/V4/TripPinService/
However, using Apache Olingo in Java I am not able to access this service.
JVM parameters like -Dhttp.proxySet=true -Dhttp.proxyHost=http-proxy.example.com -Dhttp.proxyPort=8080 allow me to perform basic URL functions, like retrieving HTTP status codes (google returns 200). Nevertheless, access of the OData-Service using an ODataClient is not possible (code below). No errors are thrown.
ODataClient client = ODataClientFactory.getClient();
ODataServiceDocumentRequest request = client.getRetrieveRequestFactory().getServiceDocumentRequest(SERVICE_ROOT);
ODataRetrieveResponse<ClientServiceDocument> response = request.execute();
I tried using the proxy capabilities within Olingo, however without any success:
client.getConfiguration().setHttpClientFactory(new ProxyWrappingHttpClientFactory(URI.create("http://http-proxy.example.com:8080")));
What am I doing wrong, what options do I have left?
Thank you very much.
If you are behind an NTLM proxy you can try with NTLMAuthHttpClientFactory.
NTLMAuthHttpClientFactory ntlm = new NTLMAuthHttpClientFactory(username, password, workstation, domain);
client.getConfiguration().setHttpClientFactory(ntlm);
In case that doesn't work, you can try with cntlm. Install it, change username, password, domain and proxy in C:\Program Files (x86)\Cntlm\cntlm.ini and then invoke net start cntlm.
Use this for Olingo:
client.getConfiguration().setHttpClientFactory(new ProxyWrappingHttpClientFactory(URI.create("http://localhost:3128")));
URI uri;
String scheme = "http";
try {
uri = new URI (scheme,null,host,port,null,null,null);
} catch (URISyntaxException e) {
throw(e);
}
HttpClientFactory clientProxy = new ProxyWrappingHttpClientFactory(uri,userName,password );
client.getConfiguration().setHttpClientFactory(clientProxy);
I somehow solved the problem by myself. Within VM arguments I now only have
-Djava.net.preferIPv4Stack=true
Further I defined a proxy config only within the application:
client = ODataClientFactory.getClient();
client.getConfiguration().setHttpClientFactory(
new ProxyWrappingHttpClientFactory(URI.create("http-prox.example.com:8080")));
This worked for me. :)
In our project we need to access the Blob Storage through a Proxy Server (squid).
We are planning to use the Microsoft Azure Storage SDK for Java version 2.2.0.
But it looks like setting the proxy is not provided by the API.
The only way I could make it go through the proxy is by setting the System properties
System.setProperty("http.proxyHost", "127.0.0.1");
System.setProperty("http.proxyPort", "3128");
But this affect all services that are running on my JVM which harms other services that not supposed to go via the Proxy.
Looking at the java code it looks like
com.microsoft.azure.storage.core.BaseRequest.createURLConnection(URI, RequestOptions, UriQueryBuilder, OperationContext). Is calling java.net.URL.openConnection() without proxy.
While using java.net.URL.openConnection(Proxy) could provide the required support?
It looks wired to me that this is not supported?
Do I miss something here?
UPDATE: I opened an issue on this in azure-storage-java git, I would be happy to get your input as I want to suggest a pull request for this.
So far there have been no Java SDK API support access directly Azure Storage through proxy server, because BaseRequest Class miss "url.openConnection(proxy)" in the function "public static HttpConnection createURLConnection(...)".
Per my experience, there are two ways to help you implement the access function.
The one is that you can use Azure Storage REST API through the java.net.Proxy Class to access storage service.
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(host, port));
URLConnection conn = url.openConnection(proxy);
And if you should be authorize proxy user & password, you can do it as the follows:
//Proxy-Authorization: Basic <Base64.encode(user:password)>
String headerKey = "Proxy-Authorization";
String headerValue = "Basic " + Base64.encode(user+":"+password);
conn.setRequestProperty(headerKey, headerValue);
The last one is that you can modify Azure SDK API and overwrite the method “createURLConnection” in Class “BaseRequest” to implement accessing. The Azure Storage SDK v2.2.0 project on GitHub is https://github.com/Azure/azure-storage-java/tree/v2.2.0/.
Note:
public static HttpURLConnection createURLConnection(final URI uri, final RequestOptions options, UriQueryBuilder builder, final OperationContext opContext, java.net.Proxy proxy)
and
final HttpURLConnection retConnection = (HttpURLConnection) resourceUrl.openConnection(proxy);
public static HttpURLConnection createURLConnection(final URI uri, final RequestOptions options, UriQueryBuilder builder, final OperationContext opContext, java.net.Proxy proxy) throws IOException, URISyntaxException, StorageException {
if (builder == null) {
builder = new UriQueryBuilder();
}
final URL resourceUrl = builder.addToURI(uri).toURL();
final HttpURLConnection retConnection = (HttpURLConnection) resourceUrl.openConnection(proxy);
if (options.getTimeoutIntervalInMs() != null && options.getTimeoutIntervalInMs() != 0) {
builder.add(TIMEOUT, String.valueOf(options.getTimeoutIntervalInMs() / 1000));
}
// Note: ReadTimeout must be explicitly set to avoid a bug in JDK 6.
// In certain cases, this bug causes an immediate read timeout exception to be thrown even if ReadTimeout is not set.
retConnection.setReadTimeout(Utility.getRemainingTimeout(options.getOperationExpiryTimeInMs(), options.getTimeoutIntervalInMs()));
// Note : accept behavior, java by default sends Accept behavior as text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
retConnection.setRequestProperty(Constants.HeaderConstants.ACCEPT, Constants.HeaderConstants.XML_TYPE);
retConnection.setRequestProperty(Constants.HeaderConstants.ACCEPT_CHARSET, Constants.UTF8_CHARSET);
// Note : Content-Type behavior, java by default sends Content-type behavior as application/x-www-form-urlencoded for posts.
retConnection.setRequestProperty(Constants.HeaderConstants.CONTENT_TYPE, Constants.EMPTY_STRING);
retConnection.setRequestProperty(Constants.HeaderConstants.STORAGE_VERSION_HEADER,
Constants.HeaderConstants.TARGET_STORAGE_VERSION);
retConnection.setRequestProperty(Constants.HeaderConstants.USER_AGENT, getUserAgent());
retConnection.setRequestProperty(Constants.HeaderConstants.CLIENT_REQUEST_ID_HEADER,
opContext.getClientRequestID());
return retConnection;
}
By the way, You need to call above method in every CloudXXXClient(CloudBlobClient, etc) Class.
Following the issue-48 opened by me based on this question and additional one opened by strazh issue-65, The proxy support was improved in version 4.2.0 see here.
Added support for setting a library-wide proxy. The default proxy can
be set on OperationContext.
See the JUnits for full example
https://github.com/Azure/azure-storage-java/blob/master/microsoft-azure-storage-test/src/com/microsoft/azure/storage/GenericTests.java
Look for testDefaultProxy and testProxy
Azure Storage team has released a new SDK (v10), where the Proxy is now supported through the HttpPipeline. You can share the pipeline across all operations by passing it to StorageURL or just use in a single Blob by passing it to the BlobURL object.
AnonymousCredentials creds = new AnonymousCredentials();
// Use PipelineOptions to define a retry strategy and a proxy - you can also pass your own HttpClient to this if you like
PipelineOptions po = new PipelineOptions();
// Proxy configuration shown here as a sample
HttpClientConfiguration configuration = new HttpClientConfiguration(
new Proxy(Proxy.Type.HTTP, new InetSocketAddress("localhost", 8888)), false); //pass true if the Proxy endpoint is HTTPS
po.client = HttpClient.createDefault(configuration);
// Create a URI with SAS token, and pass it to the PageBlobURL with an HttpPipeline created by createPipeline method
URL u = new URL("https://myaccount.blob.core.windows.net/mycontainer/myfile?sv=2017-04-17&sr=b&si=14169767-6354-41ed-a99b-c9db8dcc66bc&sig=8NUr%2BSpmRH%2BB2z%2FpQZDPDquTQ7rbgWfE9a6AePLlFT0%3D");
PageBlobURL blobURL = new PageBlobURL(u, PageBlobURL.createPipeline(creds, po));
Our application need to send some request to SOAP service. We use wsimport command to generate class for our client. But sometime when service down or some network problem, our request hang until timeout and that is rather too long. We want to control timeout value so we try serveral method.
For calling service method, after reading from other post, we set something like this:
((BindingProvider) port).getRequestContext().put("sun.net.client.defaultReadTimeout", 3000);
((BindingProvider) port).getRequestContext().put("sun.net.client.defaultConnectTimeout", 10000);
But before that,we have to call get port which will read wsdl file. We try to create URL like this:
url = new URL(null, "http://theirsite/WS?WSDL", new URLStreamHandler() {
#Override
protected URLConnection openConnection(URL url) throws IOException {
logger.info("URLStreamHandler got call!");
URL clone_url = new URL(url.toString());
HttpURLConnection clone_connection
= (HttpURLConnection) clone_url.openConnection();
clone_connection.setConnectTimeout(5000);
clone_connection.setReadTimeout(3000);
return (clone_connection);
}
});
And then we use this url as parameter when create Service object. But our URLStreamHandler never got call.
We even try to set system property like this:
System.setProperty("sun.net.client.defaultReadTimeout", "" + 3000);
System.setProperty("sun.net.client.defaultConnectTimeout", "" + 5000);
But so far nothing work for us.
So any1 can help me with this case? Or is there a better approach ? Need to mention that we don't want to read wsdl file from local.
Maybe the properties you are using are not the right ones.
Try these ones:
((javax.xml.ws.BindingProvider) port).getRequestContext().put("com.sun.xml.internal.ws.connect.timeout",
Integer.valueOf(timeout));
((javax.xml.ws.BindingProvider) port).getRequestContext().put("com.sun.xml.internal.ws.request.timeout",
Integer.valueOf(timeout));
Also, take care, there is a difference between com.sun.xml.ws.request.timeout and com.sun.xml.internal.ws.request.timeout. You should use internal when you are working with JDK JAX-WS implementation.
I am writing a code that connects to websites and checks some code, like a crawler. But I need to connect trough a proxy and change the IP address (so it doesn't show the client's IP in the server logs).
How can this be done through java?
You can use the java system properties to set up a proxy or pass it as command line options.
You can find some details and samples here.
Ex: Before opening the connection
System.setProperty("http.proxyHost", "myProxyServer.com");
System.setProperty("http.proxyPort", "80");
Or you can use the default network proxies configured in the sytem
System.setProperty("java.net.useSystemProxies", "true");
Since Java 1.5 you can create a instance of proxy and pass it to the openConnection() method.
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("123.0.0.1", 8080));
URL url = new URL("http://www.yahoo.com");
HttpURLConnection uc = (HttpURLConnection)url.openConnection(proxy);
uc.connect();
Or as lisak suggested, you can use some 3rd party libraries which supports your need better.
Or you can also use HttpClient which would suit your needs better. Check out the documentation, it's brief and very informative.
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpHost proxy = new HttpHost("someproxy", 8080);
httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("123.0.0.1", 8080));
URL url = new URL("http://www.yahoo.com");
HttpURLConnection uc = (HttpURLConnection)url.openConnection(proxy);
uc.connect();
This worked for me. I was able to use the proxy for the specific connection or transfer. Earlier we were using System.setProperty which used to set it at system level and all the requests internal/external started using the same proxy.
Also Proxy.Type.HTTP works for both http and https
I want to connect to as site through proxy in java. This is the code which I have written:
public class ConnectThroughProxy
{
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy ip", 8080));
public static void main(String[] args)
{
try
{
URL url = new URL("http://www.rgagnon.com/javadetails/java-0085.html");
URLConnection connection=url.openConnection();
String encoded = new String(Base64.encode(new String("user_name:pass_word").getBytes()));
connection.setDoOutput(true);
connection.setRequestProperty("Proxy-Authorization","Basic "+encoded);
String page="";
String line;
StringBuffer tmp = new StringBuffer();
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
while ((line=in.readLine()) != null)
{
page.concat(line + "\n");
}
System.out.println(page);
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
While trying to run this code it throws the following error:
java.lang.IllegalArgumentException: Illegal character(s) in message header value: Basic dXNlcl9uYW1lOnBhc3Nfd29yZA==
at sun.net.www.protocol.http.HttpURLConnection.checkMessageHeader(HttpURLConnection.java:323)
at sun.net.www.protocol.http.HttpURLConnection.setRequestProperty(HttpURLConnection.java:2054)
at test.ConnectThroughProxy.main(ConnectThroughProxy.java:30)
Any Idea how to do it?
If you're just trying to make HTTP requests through an HTTP proxy server, you shouldn't need to go to this much effort. There's a writeup here: http://java.sun.com/javase/6/docs/technotes/guides/net/proxies.html
But it basically boils down to just setting the http.proxyHost and http.proxyPort environment properties, either on the command line, or in code:
// Set the http proxy to webcache.mydomain.com:8080
System.setProperty("http.proxyHost", "webcache.mydomain.com");
System.setProperty("http.proxyPort", "8080");
// Next connection will be through proxy.
URL url = new URL("http://java.sun.com/");
InputStream in = url.openStream();
// Now, let's 'unset' the proxy.
System.clearProperty("http.proxyHost");
// From now on HTTP connections will be done directly.
It seems to me, that you are not using your Proxy instance at all. I think you should pass it when you are creating URLConnection instance:
URLConnection connection=url.openConnection(proxy);
Setting of environment properties http.proxy is easier and when using some 3rd party libraries without Proxy instance passing support only possible solution, but its drawback is that it is set globally for the whole process.
I was using the Google Data APIs and the only way I got the proxy settings to work was to provide ALL the parameters related to proxy, even thought they are set to be empty:
/usr/java/jdk1.7.0_04/bin/java -Dhttp.proxyHost=10.128.128.13
-Dhttp.proxyPassword -Dhttp.proxyPort=80 -Dhttp.proxyUserName
-Dhttps.proxyHost=10.128.128.13 -Dhttps.proxyPassword -Dhttps.proxyPort=80
-Dhttps.proxyUserName com.stackoverflow.Runner
Where, username and password are NOT required, and the same http and https servers are set to be the same, as well as the port number (if that's your case as well). Note that the same HTTP proxy is also provided as the HTTPS server, as well as its port number (reference from https://code.google.com/p/syncnotes2google/issues/detail?id=2#c16).
If your Java class has an instance of the class "URL", it should pick those configurations up...