You are viewing the documentation for Blueriq 16. Documentation for other versions is available in our documentation directory.

Blueriq has a standard Material Theme packaged but when creating your own theme this must be deployed somehow. 
A way to do so can be done via nginx / Tomcat / or whatever you prefer to use. Below you will find an example on how to do this for nginx


Yarn build

The Material Kickstarted comes with 2 build scripts and both use a different environment.ts file which can be configured if needed. Configurating in this case means changing the baseUrl.

  1. Change the `environment.runtime.ts` baseUrl to `/server`
  2. Run `yarn build:runtime` (which uses the environment.runtime.ts's configuration)
  3. When finished: Copy the content of /dist to a application server you prefer (for NGINX that would be: /html

NGINX

For getting started with NGINX please take a look at their documentation: https://www.nginx.com/resources/wiki/ 
The following configuration is the minimum needed to get the theme up and running. You could need adjustments to fit your own specific setup.

nginx.conf
error_log logs/error.log;

events {
	worker_connections 1024;
}

http {
	upstream revProxyRuntime {
		# 1: Replace <host>:<port>, example: my.runtime.local:8080
		server <host>:<port>;
	}
	
	server {
		include ../conf/mime.types;
		listen 1337;

		# Instruct the browser to always verify that its cache is up-to-date
		add_header Cache-Control 'max-age=0, must-revalidate';

		location / {
			root html;
			index index.html index.htm;
			try_files $uri $uri/ /index.html =404;
		}
		
		# 2: /server matches with what was configured in the environment.ts baseUrl
		location /server/ {
			proxy_set_header Host $host;
			proxy_set_header X-Forwarded-Host $host:$server_port;
			proxy_set_header X-Forwarded-Server $host;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
			proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-Forwarded-Port $server_port;
			
			# 3: This uses the upstream (step 1): So this becomes: http://<host>:<port>/<context>/server/$and_the_rest_of_it;
			# Change the <context> part to the context root of the runtime. This is 'Runtime' if you installed Blueriq with the installer.
			proxy_pass http://revProxyRuntime/<context>$request_uri;
			
			proxy_cookie_path /<context> /;
		}

	}
}

External Theme

When your custom theme is configured as a external theme in the Development Tools Component, you should add an additional location block for /runtime calls. Without doing so the development toolbar is unable to retrieve session information from the runtime when you start a project using the your custom theme as the external theme. More information about configuring external themes can be found here

nginx.conf
error_log logs/error.log;

events {
	worker_connections 1024;
}

http {
	upstream revProxyRuntime {
		# 1: Replace <host>:<port>, example: my.runtime.local:8080
		...
	}
	
	server {
		include ../conf/mime.types;
		listen 1337;

		# Instruct the browser to always verify that its cache is up-to-date
		add_header Cache-Control 'max-age=0, must-revalidate';

		location / {
			...
		}
		
		# 2: /server matches with what was configured in the environment.ts baseUrl
		location /server/ {
			...
		}

		# 3: /runtime matches Runtime calls which are made by the development toolbar
		location /runtime/ {
			proxy_set_header Host $host;
			proxy_set_header X-Forwarded-Host $host:$server_port;
			proxy_set_header X-Forwarded-Server $host;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
			proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-Forwarded-Port $server_port;
			
			proxy_pass http://revProxyRuntime$request_uri;
			
			proxy_cookie_path /Runtime /;
		}

	}
}

  • No labels

2 Comments

  1. Sometimes the frontend is build with the following baseUrl `/runtime`, but `/runtime/server/` is expected. The following rewrite rule will rewrite this 
    `rewrite ^/runtime/(?!server)(.*)$ /runtime/server/$1 break;`

    Note how it only rewrites if it did not already contain `/server`

  2. If the frontend is on a aws s3 bucket, you can also add a S3ReverseProxyServlet: 

    package nl.nn.blueriq.reverseproxy;

    import java.io.IOException;
    import java.io.OutputStream;
    import java.util.concurrent.TimeUnit;

    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import com.amazonaws.ClientConfiguration;
    import com.amazonaws.Protocol;
    import com.amazonaws.SdkClientException;
    import com.amazonaws.services.s3.AmazonS3;
    import com.amazonaws.services.s3.AmazonS3ClientBuilder;
    import com.amazonaws.services.s3.model.GetObjectRequest;
    import com.amazonaws.services.s3.model.Region;
    import com.amazonaws.services.s3.model.S3Object;
    import com.amazonaws.services.s3.model.S3ObjectInputStream;

    public class S3ReverseProxyServlet extends HttpServlet
    {
        private static final String REGION_ID = Region.EU_Ireland.getFirstRegionId();
        protected String bucketName = "mybucket";

        private AmazonS3 s3Client;

        @Override
        public String getServletInfo()
        {
            return "s3 reverse proxy";
        }

        @Override
        public void init()
            throws ServletException
        {
            ClientConfiguration config = new ClientConfiguration();
            config.setProtocol(Protocol.HTTPS);
            config.setRequestTimeout((int) TimeUnit.MINUTES.toMillis(3));
            config.setSocketTimeout((int) TimeUnit.MINUTES.toMillis(3));
            s3Client = AmazonS3ClientBuilder.standard().withRegion(FIRST_REGION_ID).withClientConfiguration(config).build();

       }

        @Override
        public void destroy()
        {
            if (s3Client != null)
                super.destroy();
        }

        @Override
        protected void service(HttpServletRequest servletRequest, HttpServletResponse servletResponse)
            throws ServletException, IOException
        {
        String pathInfo = servletRequest.getPathInfo();
        if (pathInfo != null && pathInfo.length() > 1) {
          // Remove starting slash
          String filename = pathInfo.substring(1);
          String mimeType = getServletContext().getMimeType(filename);
          servletResponse.setContentType(mimeType);
          streamS3File(servletResponse.getOutputStream(), bucketName, filename);
          System.out.println("BlueriqReverseProxy handled request:" + pathInfo + "  ContentType: " + mimeType);
        }
        else {
          servletResponse.getOutputStream().println("BlueriqReverseProxy");
        }
        }

        private void streamS3File(final OutputStream output, String bucketName, String key)
        {
            GetObjectRequest req = new GetObjectRequest(bucketName, key);
            S3Object s3Object = s3Client.getObject(req);
            S3ObjectInputStream objectContent = s3Object.getObjectContent();
            try {
                byte[] buffer = new byte[1024 * 10];
                int bytesRead = -1;
                while ((bytesRead = objectContent.read(buffer)) > -1) {
                    output.write(buffer, 0, bytesRead);
                }
            }
            catch (IOException ex) {
                objectContent.abort();
                throw new SdkClientException("Unable to transfer content from Amazon S3 to the output stream", ex);
            }
            finally {
                try {
                    objectContent.close();
                }
                catch (IOException ex) {
                }
            }
        }
    }