Java HTTP Proxy Server
In today’s corporate development environment, we have to deal with proxies, usually as system administrators. In most cases, the application will be configured to the system’s default setting, but if you want very tight control over your application like proxy setting, for such cases, Java allows APIs.
The proxy server is like an intermediate system between the client-side application and other servers. In an enterprise application, which is used to provide control over the user’s content across network boundaries. The below image demonstrates the behavior of the proxy server:
In this topic, we will understand how to connect through proxy servers in Java. We will follow two approaches to create a connection along with proxy servers in Java.
- The first approach is an older approach that is JVM-wide and configured with system properties. It is used globally by many developers.
- The second approach is by using the Proxy class, which provides more control by allowing configuration on the basis of per connection.
The Proxy API is available since Java 5.0. However, the old approaches are still valid and can be used with our projects. But the Proxy class approach is more effective and customizable.
Advantages of Using Proxy Servers
The proxy servers are useful in the following cases:
- To capture the traffic between a client and server.
- To control and limit the uploading/downloading the bandwidth to discover the loading of the website with slow connections.
- To analyze the system reaction when there is trouble in your network.
- To update the content of a client/server.
- To create statistics about traffic.
System Properties
Java supports proxy handlers for different protocols such as FTP, HTTP, HTTPS, and SOCKs. We can define an individual proxy for an individual handler as the hostname and port number. The following system properties are available in Java proxy configuration:
- proxyHost: It defines the hostname for the HTTP proxy server.
- proxyPort: It defines the port number for the HTTP proxy server
- The port property is an optional property it will be set to defaults to 80 if not provided.
- nonProxyHosts : It defines a pipe-delimited (“|”) for the available host patterns for which we want to bypass the proxy. It can be applied to both the HTTP and HTTPS handlers.
- SocksProxyHost: It defines the SOCKS proxy server’s hostname.
- SocksProxyPort: It defines the SOCKS proxy server’s port number.
Note: We may start or end a host pattern using a wildcard character (“*”) in the case of nonProxyHosts. But on the Windows platform, it is necessary to remove the “|” delimiter. The list of all available proxy system properties can be found Here.
Using a Global Setting
Java provides several system properties that we have discussed above to configure the JVM-wide behavior. These properties are easy to implement for a particular use case.
We can also set the necessary properties using the command line while invoking the JVM. There is an alternative way to do so, and they can be set by calling the System.setProperty() method at runtime.
Let’s understand how to set them using the command line:
Set Proxy Using the Command Line
We can also set the proxy properties using the command line arguments. To define the proxies using the command line, pass the settings as system properties as follows:
By starting process in this way, we can use openConnection() method on the URL without doing any further effort as follows:
Set Proxy Using the System.setProperty() Method
If we face difficulty while using the command line, there is an alternative way to do so by using the System.setProperty() method. To set the Proxy using this method, define it within our program as follows:
Later, we can unset the system properties, and if we want, then they will be removed from our application. To unset the system property, make it null by defining it within our program as follows:
The Global setting has some limitations; here, the concept of Proxy API came into the picture. Let’s discuss the limitations of the Global setting:
Limitations of Global Configuration Approach
The Global Configuration approach is the simplest way to define the proxy, but this approach has some limitations.
This approach provides the implementation on the JVM-wide, so the settings define for a particular protocol are active for the life of the JVM or until we unset them manually.
To get over this limitation, it may be attractive to flip the settings on and off, if needed. But, it would be necessary to ensure the measures to protect against concurrency issues in a multi-threaded program.
So, as an alternative, the Proxy API is more efficient and provides more control over proxy configuration.
Set Proxy Using the Proxy API
The Java Proxy class provides a convenient way to configure proxies on the basis of the connection. If we set the proxy using the Proxy class, it will override the existing JVM-wide proxy setting.
There are three types of proxies that can be defined by using Proxy.Type() method of Proxy class:
- HTTP proxy (using the HTTP protocol)
- SOCKS proxy (using the SOCKS protocol)
- DIRECT proxy ( It is an explicitly configured direct connection without a proxy).
Let’s understand these proxies:
1) HTTP Proxy
To use an HTTP proxy, wrap the SocketAddress instance with proxy and provide type as Proxt.Type.HTTP. Now, we can simply pass the proxy instance to URLConnection.openConnection(). Consider the below code:
Now, we’ll connect to URL_STRING but then route that connection through a proxy server hosted at 127.0.0.1:3020.
2) DIRECT Proxy
The Direct Proxy is useful for connecting directly to a host. In this case, we have to explicitly bypass a proxy that may be configured globally by using the static “proxy.NO_PROXY” instance. Internally, the Proxy API creates a new proxy instance using the Proxy.Type.Direct type.
Consider the below code:
Basically, if there is no globally configured proxy, then this will work the same as calling openConnection() with no arguments.
3) Socks Proxy
The Socks proxy works in a similar way to HTTP variant while dealing with URLConnection. In Socks proxy, first we wrap a SocketAddress instance with a Proxy using the Proxy.Type.SOCKS type. After that, the Proxy instance is passed to URLConnection.openConnection. Consider the below code:
We can also use a SOCKs proxy when connecting to a TCP socket. In order to do so, we need to use the Proxy instance to create a Socket. After that, the destination SocketAddress instance is passed to Socket.connect() method.
Consider the below code:
Java Program to Create a Simple Proxy Server
TestProxyServer.java:
Output: