Expand my Community achievements bar.

Advanced Networking in AEMaaCs | HTTP/HTTPS connections on non-standard ports for flexible port egress

Avatar

Community Advisor

11/22/24

Advanced Networking in AEMaaCs | HTTP/HTTPS connections on non-standard ports for flexible port egress

 
by Nikhil Kumar

AEM as a Cloud Service provides advanced networking features that allows for precise management of connections to and from AEM as a Cloud Service programs. In this article we will  learn how to set up and use flexible port egress to support external connections from AEM as a Cloud Service to external services.
Flexible port egress allows for custom, specific port forwarding rules to be attached to AEM as a Cloud Service, allowing connections from AEM to external services to be made.

Recently i was trying to make an API call from my AEMaaCs to an endpoint where the data was coming from a specific port for example: https://test.securedummy.com:8076/v2/cred, Now this used to run properly on my local environment whereas on AEMaaCs environments it was throwing 500. As AEMaaCs blocks some request for non-standard ports (i.e, except 80/443).
So lets see how I made HTTP/HTTPS connections on non-standard ports for flexible port egress.

HTTP/HTTPS connections on non-standard ports (not 80/443) must be proxied out of AEM as a Cloud Service, however they do not need any special portForwards rules, and can use AEM’s advanced networking’s AEM_PROXY_HOST and a reserved proxy port AEM_HTTP_PROXY_PORT or AEM_HTTPS_PROXY_PORT depending on is the destination is HTTP/HTTPS.

 

Below Java code example is of an OSGi service that can run in AEM as a Cloud Service that makes an HTTP connection to an external web server on 8080. Connections to HTTPS web servers use the environment variables AEM_PROXY_HOST and AEM_HTTPS_PROXY_PORT (default to proxy.tunnel:3128 in AEM releases < 6094).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package com.adobe.aem.wknd.examples.core.connections.impl;
 
import com.adobe.aem.wknd.examples.core.connections.ExternalService;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ProxySelector;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
 
public class HttpExternalServiceImpl implements ExternalService {
    private static final Logger log = LoggerFactory.getLogger(HttpExternalServiceImpl.class);
 
    @Override
    public boolean isAccessible() {
        HttpClient client;
 
        // Use System.getenv("AEM_PROXY_HOST") and proxy port System.getenv("AEM_HTTP_PROXY_PORT")
        // or System.getenv("AEM_HTTPS_PROXY_PORT"), depending on if the destination requires HTTP/HTTPS
 
        if (System.getenv("AEM_PROXY_HOST") != null) {
            // Create a ProxySelector that uses to AEM's provided AEM_PROXY_HOST, with a fallback of proxy.tunnel, and proxy port using the AEM_HTTP_PROXY_PORT variable.
            // If the destination requires HTTPS, then use the variable AEM_HTTPS_PROXY_PORT instead of AEM_HTTP_PROXY_PORT.
 
            ProxySelector proxySelector = ProxySelector.of(new InetSocketAddress(
                System.getenv().getOrDefault("AEM_PROXY_HOST", "proxy.tunnel"),
                Integer.parseInt(System.getenv().get("AEM_HTTP_PROXY_PORT"))));
 
            client = HttpClient.newBuilder().proxy(proxySelector).build();
            log.debug("Using HTTPClient with AEM_PROXY_HOST");
        } else {
            client = HttpClient.newBuilder().build();
            // If no proxy is set up (such as local dev)
            log.debug("Using HTTPClient without AEM_PROXY_HOST");
        }
 
        // Prepare the full URI to request, note this will have the
        // - Scheme (http/https)
        // - External host name
        // - External port
        // The external service URI, including the scheme/host/port, is defined in code, and NOT in Cloud Manager portForwards rules.
        URI uri = URI.create("https://test.securedummy.com:8076/v2/cred,");
 
        // Prepare the HttpRequest
        HttpRequest request = HttpRequest.newBuilder().uri(uri).timeout(Duration.ofSeconds(2)).build();
 
        // Send the HttpRequest using the configured HttpClient
        HttpResponse<String> response = null;
        try {
            // Request the URL
            response = client.send(request, HttpResponse.BodyHandlers.ofString());
 
            log.debug("HTTP response body: {} ", response.body());
 
            // Our simple example returns true is response is successful! (200 status code)
            return response.statusCode() == 200;
        } catch (IOException e) {
            return false;
        } catch (InterruptedException e) {
            return false;
        }
    }
}

 

 
 
 

So in AEMaaCs it makes use of AEM_PROXY_HOST to create ProxySelector which can make a call to non-standard port in AEMaaCs.

When creating HTTP/HTTPS connections to non-standard ports (not-80/443) from AEM, the connections must be made through special host and ports, provided via placeholders.

AEM provides two sets of special Java system variables that map to AEM’s HTTP/HTTPS proxies.

Variable name Use Java™ code OSGi configuration
AEM_PROXY_HOST Proxy host for both HTTP/HTTPS connections System.getenv().getOrDefault("AEM_PROXY_HOST", "proxy.tunnel") $[env:AEM_PROXY_HOST;default=proxy.tunnel]
AEM_HTTP_PROXY_PORT Proxy port for HTTPS connections (set fallback to 3128) System.getenv().getOrDefault("AEM_HTTP_PROXY_PORT", 3128) $[env:AEM_HTTP_PROXY_PORT;default=3128]
AEM_HTTPS_PROXY_PORT Proxy port for HTTPS connections (set fallback to 3128) System.getenv().getOrDefault("AEM_HTTPS_PROXY_PORT", 3128) $[env:AEM_HTTPS_PROXY_PORT;default=3128]

Thank you for reading.
Happy Coding!

3 Comments