/** * i-net software provides programming examples for illustration only, without warranty * either expressed or implied, including, but not limited to, the implied warranties * of merchantability and/or fitness for a particular purpose. This programming example * assumes that you are familiar with the programming language being demonstrated and * the tools used to create and debug procedures. i-net software support professionals * can help explain the functionality of a particular procedure, but they will not modify * these examples to provide added functionality or construct procedures to meet your * specific needs. * * Copyright © 1999-2025 i-net software GmbH, Berlin, Germany. **/ package proxyservlet; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.Enumeration; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; /** * A proxy implementation for using in a frontend web server to forward the requests to a standalone backend server. */ public class ProxyServlet extends HttpServlet { /** Setup the URL of the report server here. You can do it statically or dynamically in init(). */ private static String REPORTING_URL = "http://localhost:9000"; /** * Forward the request to the reporting server {@inheritDoc} */ @Override protected void service( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException { String pathInfo = request.getPathInfo(); String context = request.getRequestURI(); String backendUrl; if( pathInfo == null ) { backendUrl = "/"; } else { backendUrl = pathInfo; context = context.substring( 0, context.length() - pathInfo.length() ); } if( request.getQueryString() != null ) { backendUrl += '?' + request.getQueryString(); } URL url = new URL( REPORTING_URL + backendUrl ); HttpURLConnection http = (HttpURLConnection)url.openConnection(); http.setAllowUserInteraction( false ); //disable NTLM support, we does not want login the frontend server in the backend server //you does not need it if you are sure that the backend server will never request a NTLM authentication try { java.lang.reflect.Field field = http.getClass().getDeclaredField( "tryTransparentNTLMServer" ); field.setAccessible( true ); field.set( http, Boolean.FALSE ); } catch( Exception e1 ) { e1.printStackTrace(); } String method = request.getMethod(); http.setRequestMethod( method ); http.setInstanceFollowRedirects( false ); // copy the header from client to server Enumeration headers = request.getHeaderNames(); while( headers.hasMoreElements() ) { String header = headers.nextElement(); Enumeration values = request.getHeaders( header ); while( values.hasMoreElements() ) { String value = (String)values.nextElement(); if( value != null ) { http.addRequestProperty( header, value ); } } } // set some additional header String host = request.getHeader( "Host" ); if( host == null ) { host = request.getServerName() + ":" + request.getServerPort(); } http.addRequestProperty( "X-Forwarded-Host", host ); http.addRequestProperty( "X-Forwarded-For", request.getRemoteAddr() ); http.addRequestProperty( "X-Forwarded-Proto", request.getScheme() ); http.addRequestProperty( "X-Forwarded-Context", context ); http.setUseCaches( false ); boolean noData = "GET".equalsIgnoreCase( method ) || "HEAD".equalsIgnoreCase( method ); InputStream result; try { if( !noData ) { // copy the data http.setDoOutput( true ); OutputStream out = http.getOutputStream(); copy( request.getInputStream(), out ); } result = http.getInputStream(); } catch( Exception e ) { result = http.getErrorStream(); } int resposeCode = http.getResponseCode(); response.setStatus( resposeCode ); // copy the header from server to the client for( int h = 0;; h++ ) { String header = http.getHeaderFieldKey( h ); String value = http.getHeaderField( h ); if( header == null && value == null ) { break; } if( header != null && value != null ) { if( "Transfer-Encoding".equalsIgnoreCase( header ) ) { continue; } if( "WWW-Authenticate".equalsIgnoreCase( header ) && "NTLM".equalsIgnoreCase( value ) ) { //NTLM does not work with a proxy continue; } response.addHeader( header, value ); } } // copy the data from server to the client if( result != null ) { copy( result, response.getOutputStream() ); } } /** * Copy the data from the input to the output * @param input the input data * @param output the target * @throws IOException if IO issues */ private void copy( InputStream input, OutputStream output ) throws IOException { byte[] buf = new byte[4096]; int len; while( (len = input.read( buf )) > 0 ) { output.write( buf, 0, len ); } } }