Skip to content

Commit d0d1f4a

Browse files
committed
Add public static utilities to ParseUrl
First, I copied the IP address detection code from https://github.com/aws/aws-sdk-java-v2/blob/93f914840a071fb162693d1ebd753803281253cf/codegen/src/main/resources/software/amazon/awssdk/codegen/rules2/RuleUrl.java.resource#L58-L111 This should be much more performant than catching integer parsing errors. I also exposed this method and the method for normalizing a path as a public utility method. This will allow me to use the method directly in smithy-java.
1 parent 87133e4 commit d0d1f4a

File tree

1 file changed

+90
-34
lines changed
  • smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/language/syntax/expressions/functions

1 file changed

+90
-34
lines changed

smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/language/syntax/expressions/functions/ParseUrl.java

Lines changed: 90 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -99,41 +99,9 @@ public Value evaluate(List<Value> arguments) {
9999
return Value.emptyValue();
100100
}
101101

102-
boolean isIpAddr = false;
103-
String host = parsed.getHost();
104-
if (host.startsWith("[") && host.endsWith("]")) {
105-
isIpAddr = true;
106-
}
107-
String[] dottedParts = host.split("\\.");
108-
if (dottedParts.length == 4) {
109-
isIpAddr = true;
110-
for (String dottedPart : dottedParts) {
111-
try {
112-
int value = Integer.parseInt(dottedPart);
113-
if (value < 0 || value > 255) {
114-
isIpAddr = false;
115-
}
116-
} catch (NumberFormatException ex) {
117-
isIpAddr = false;
118-
}
119-
}
120-
}
121-
102+
boolean isIpAddr = isIpAddr(parsed.getHost());
122103
String path = parsed.getPath();
123-
String normalizedPath;
124-
if (StringUtils.isBlank(path)) {
125-
normalizedPath = "/";
126-
} else {
127-
StringBuilder builder = new StringBuilder();
128-
if (!path.startsWith("/")) {
129-
builder.append("/");
130-
}
131-
builder.append(path);
132-
if (!path.endsWith("/")) {
133-
builder.append("/");
134-
}
135-
normalizedPath = builder.toString();
136-
}
104+
String normalizedPath = normalizePath(path);
137105

138106
Map<Identifier, Value> values = new LinkedHashMap<>();
139107
values.put(SCHEME, Value.stringValue(parsed.getProtocol()));
@@ -152,4 +120,92 @@ public ParseUrl createFunction(FunctionNode functionNode) {
152120
return new ParseUrl(functionNode);
153121
}
154122
}
123+
124+
/**
125+
* Checks if a host is an IP address for use with endpoint rules.
126+
*
127+
* @param host Host to check.
128+
* @return true if it is an IP address.
129+
*/
130+
public static boolean isIpAddr(String host) {
131+
if (host == null || host.length() < 2) {
132+
return false;
133+
}
134+
135+
// Simple check for IPv6 (enclosed in square brackets)
136+
if (host.charAt(0) == '[' && host.charAt(host.length() - 1) == ']') {
137+
return true;
138+
}
139+
140+
int from = 0;
141+
int segments = 0;
142+
boolean done = false;
143+
while (!done) {
144+
int index = host.indexOf('.', from);
145+
if (index == -1) {
146+
if (segments != 3) {
147+
// E.g., 123.com
148+
return false;
149+
}
150+
index = host.length();
151+
done = true;
152+
} else if (segments == 3) {
153+
// E.g., 1.2.3.4.5
154+
return false;
155+
}
156+
int length = index - from;
157+
if (length == 1) {
158+
char ch0 = host.charAt(from);
159+
if (ch0 < '0' || ch0 > '9') {
160+
return false;
161+
}
162+
} else if (length == 2) {
163+
char ch0 = host.charAt(from);
164+
char ch1 = host.charAt(from + 1);
165+
if ((ch0 <= '0' || ch0 > '9') || (ch1 < '0' || ch1 > '9')) {
166+
return false;
167+
}
168+
} else if (length == 3) {
169+
char ch0 = host.charAt(from);
170+
char ch1 = host.charAt(from + 1);
171+
char ch2 = host.charAt(from + 2);
172+
if ((ch0 <= '0' || ch0 > '9')
173+
|| (ch1 < '0' || ch1 > '9')
174+
|| (ch2 < '0' || ch2 > '9')) {
175+
return false;
176+
}
177+
int value = ((ch0 - '0') * 100) + ((ch1 - '0') * 10) + (ch2 - '0');
178+
if (value > 255) {
179+
return false;
180+
}
181+
} else {
182+
return false;
183+
}
184+
from = index + 1;
185+
segments += 1;
186+
}
187+
return true;
188+
}
189+
190+
/**
191+
* Normalizes a path string according to the ParseURL function.
192+
*
193+
* @param path Path string to normalize.
194+
* @return the normalized path.
195+
*/
196+
public static String normalizePath(String path) {
197+
if (StringUtils.isBlank(path)) {
198+
return "/";
199+
} else {
200+
StringBuilder builder = new StringBuilder();
201+
if (!path.startsWith("/")) {
202+
builder.append("/");
203+
}
204+
builder.append(path);
205+
if (!path.endsWith("/")) {
206+
builder.append("/");
207+
}
208+
return builder.toString();
209+
}
210+
}
155211
}

0 commit comments

Comments
 (0)