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!

2 Comments

Avatar

Level 4

11/22/24

Hi @Nikhil-Kumar ,
I have a doubt,
Our backend api team  is implementing Authorization (Entra ID) for all the request it receives ,  Our AEM as Cloud service is using Vue.js as front end framework and through vue.js we are making API request, 
How can we handle the authorization from AEM side, should we handle it from AEM or from Vue.js . Please explain. 
thanks in advance

 

Avatar

Community Advisor

11/23/24

Thanks for writing on the advanced networking setup @Nikhil-Kumar. Depending on which HTTP client is being used, folks might run into the problem described here - https://cqdump.joerghoh.de/2023/07/13/aem-cs-dedicated-egress-ip/ so this is another useful resource to reference for implementation.