gnodet-bot commented on code in PR #29521: URL: https://github.com/apache/camel/pull/29521#discussion_r4519163662
########## dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/ChaosHttpFeed.java: ########## @@ -0,0 +1,356 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.dsl.jbang.core.common; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.concurrent.ThreadLocalRandom; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.camel.cli.connector.RepeatedSend; +import org.apache.camel.dsl.jbang.core.commands.ai.HttpEndpoints; +import org.apache.camel.util.json.JsonObject; + +/** + * The feed of a chaos experiment for a route that serves HTTP (CAMEL-26793): such a route starts from platform-http or + * the REST DSL, which has no producer, so it is fed with HTTP requests to the integration's own server (localhost and + * the port of its HTTP server, as the status has them). The experiment sends them while it waits for the verdict, and + * its traffic counts the status codes the clients got. + */ +public final class ChaosHttpFeed { + + /** Where the requests go: the method and the URL on the integration's own server. */ + public record Target(String method, String url) { + + @Override + public String toString() { + return method + " " + url; + } + } + + // a path to call, with an optional method: /orders/42, PUT /orders/42 + private static final Pattern PATH + = Pattern.compile("(?:(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\s+)?(/\\S*)", Pattern.CASE_INSENSITIVE); + + private ChaosHttpFeed() { + } + + /** Whether the feed is a path to call, such as /orders/42 or PUT /orders/42, rather than a route or endpoint. */ + public static boolean isPath(String feed) { + return feed != null && PATH.matcher(feed.strip()).matches(); + } + + /** Whether the route starts from an input that is fed over the HTTP server of Camel: platform-http or rest. */ + static boolean servedByCamel(String from) { + return from != null && (from.startsWith("platform-http:") || from.startsWith("rest:")); + } + + // an HTTP server with its own address in the URI: netty-http:http://0.0.0.0:9000/hooks + private static final Pattern OWN_ADDRESS = Pattern.compile( + "(?:netty-http|undertow|jetty|vertx-http):(?://)?(https?)://([^/:?]+)(:\\d+)?([^?]*)(?:\\?.*)?"); + private static final Set<String> LOCAL_HOSTS = Set.of("localhost", "127.0.0.1", "0.0.0.0", "::1", "[::1]"); + + /** + * The URL to call for a route that starts from an HTTP server with its own address on this machine (netty-http, + * undertow, jetty), or null: the host it listens on is called as localhost. + */ + static String ownAddress(String from) { + Matcher m = from != null ? OWN_ADDRESS.matcher(from) : null; + if (m == null || !m.matches() || !LOCAL_HOSTS.contains(m.group(2))) { + return null; + } + String path = m.group(4).isEmpty() ? "/" : m.group(4); + return m.group(1) + "://localhost" + (m.group(3) != null ? m.group(3) : "") + path; + } + + /** + * Where the requests of the feed go: for a path to call, or for a route that starts from platform-http or rest (by + * its id or endpoint); null when the feed is for another route. + * + * @throws IllegalArgumentException when the feed is for HTTP but cannot be sent, with the reason + */ + public static Target target(JsonObject status, JsonObject route, String feed) { + Matcher m = PATH.matcher(feed.strip()); + String method; + String path; + String routeId = null; + if (m.matches()) { + method = m.group(1); + path = m.group(2); + } else if (route != null && ownAddress(route.getString("from")) != null) { + // its own server on this machine: no port to look up + String from = route.getString("from"); + String m0 = method(from); + return new Target(m0 != null ? m0 : "POST", ownAddress(from)); Review Comment: 💡 **Redundant call:** `ownAddress()` is called twice with the same argument. The guard on line 105 already confirms the result is non-null — but that result is discarded and `ownAddress()` is recomputed identically on line 109. Store the result of the first call in a local variable and reuse it: ```suggestion } else if (route != null) { // its own server on this machine: no port to look up String from = route.getString("from"); String addr = ownAddress(from); if (addr == null) return null; String m0 = method(from); return new Target(m0 != null ? m0 : "POST", addr); ``` -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
