Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: getRemoteHost and getRemotePort for ALB #827

Merged
merged 4 commits into from
May 10, 2024
Merged

Conversation

mbfreder
Copy link
Contributor

@mbfreder mbfreder commented Apr 8, 2024

Issue #, if available: #816

Description of changes:
ALB host header information comes in a singleValueHeader object, instead of the multivalueHeaders that was checked.

  • Fixed the getRemoteHost and getRemotePort to return the correct values for ALB.
  • Added a test to validate.

By submitting this pull request

  • I confirm that my contribution is made under the terms of the Apache 2.0 license.
  • I confirm that I've made a best effort attempt to update all relevant documentation.

@mbfreder mbfreder requested a review from deki April 8, 2024 22:18
@mbfreder mbfreder self-assigned this Apr 8, 2024
@@ -441,6 +443,13 @@ public String getRemoteAddr() {

@Override
public String getRemoteHost() {
if (Objects.nonNull(request.getRequestContext().getElb())) {
String host_header = request.getHeaders().get(HttpHeaders.HOST);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please avoid underscores in variable names, use hostHeader instead.

@@ -471,6 +480,12 @@ public RequestDispatcher getRequestDispatcher(String s) {

@Override
public int getRemotePort() {
if (Objects.nonNull(request.getRequestContext().getElb())) {
String hostHeader = request.getHeaders().get(HttpHeaders.HOST);
String port = Arrays.asList(hostHeader.split(":")).get(1);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm currently seeing java.lang.ArrayIndexOutOfBoundsException: Index 1 out of bounds for length 1 when calling getRemotePort().

For a http Request on 80 the payload looks like this:

{
    "requestContext": {
        "elb": {
            "targetGroupArn": "arn:aws:elasticloadbalancing:eu-central-1:5952169XXXXX:targetgroup/sam-ap-MyTar-ZEEXXXXX/77425e11d8XXXX"
        }
    },
    "httpMethod": "GET",
    "path": "/",
    "queryStringParameters": {},
    "headers": {
        "accept": "*/*",
        "host": "sam-ap-MyLoa-jNFZXXXXX-000000000.eu-central-1.elb.amazonaws.com",
        "user-agent": "curl/8.4.0",
        "x-amzn-trace-id": "Root=1-661944f2-348171d959c3a5cb69d00000",
        "x-forwarded-for": "1.2.3.4",
        "x-forwarded-port": "80",
        "x-forwarded-proto": "http"
    },
    "body": "",
    "isBase64Encoded": false
}

@mbfreder mbfreder requested a review from deki April 29, 2024 06:51
Copy link
Collaborator

@deki deki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the Javadoc for jakarta.servlet.ServletRequest.getRemoteHost()

Returns the fully qualified name of the address returned by getRemoteAddr(). If the engine cannot or chooses not to resolve the hostname (to improve performance), this method returns the IP address.

it doesn't seem consistent. In my view we likely need to change getRemoteAddr() as well, wdyt?

getRemotePort() now looks similar but not identical to getServerPort(). Is that intended?

@@ -471,6 +480,11 @@ public RequestDispatcher getRequestDispatcher(String s) {

@Override
public int getRemotePort() {
if (Objects.nonNull(request.getRequestContext().getElb())) {
String hostHeader = request.getHeaders().get(PORT_HEADER_NAME);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable naming is misleading as it is no longer the host header.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated. Thanks.

Copy link
Contributor Author

@mbfreder mbfreder Apr 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're right. We need to update getRemoteAddr() to take into account the x-forwarded-for header. For getServerPort(), I'm a bit confused. Looking at the javadoc for both getServerPort() and getRemotePort(), I'm wondering if Returns the Internet Protocol (IP) source port of the client or last proxy that sent the request. and Returns the port number to which the request was sent don't mean the same thing. Is ALB considered as a client in this case?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make it even more interesting there is also getLocalPort().

ALB is the last proxy so that should be fine.

For comparison Tomcat sets serverPort based on scheme https://github.com/apache/tomcat/blob/main/java/org/apache/catalina/connector/CoyoteAdapter.java#L579.

@@ -471,6 +480,11 @@ public RequestDispatcher getRequestDispatcher(String s) {

@Override
public int getRemotePort() {
if (Objects.nonNull(request.getRequestContext().getElb())) {
String hostHeader = request.getHeaders().get(PORT_HEADER_NAME);
if (Objects.nonNull(hostHeader))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use brackets for the if statement

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated. Thanks

@mbfreder mbfreder requested a review from deki April 29, 2024 16:49
@deki deki merged commit ec98c39 into aws:main May 10, 2024
4 checks passed
@deki
Copy link
Collaborator

deki commented May 10, 2024

Merged this for now as it fixes #816 and should be included in next release. Additional improvements for ALB can be added as separate PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants