Skip to content

update http - #384

Open
zhaohai666 wants to merge 3 commits into
apache:masterfrom
zhaohai666:update-connect-http
Open

update http#384
zhaohai666 wants to merge 3 commits into
apache:masterfrom
zhaohai666:update-connect-http

Conversation

@zhaohai666

Copy link
Copy Markdown
Contributor

The http protocol supports Basic, Api Key and OAuth2 authentication.

@RockteMQ-AI

Copy link
Copy Markdown

⚠️ Merge conflict detected

This PR has conflicts with the base branch and cannot be merged. Please rebase or merge the base branch into your branch and resolve the conflicts:

git fetch origin
git checkout update-connect-http
git rebase origin/main
# resolve conflicts, then:
git push --force-with-lease

This is a one-time reminder. Feel free to @mention me for a re-review after conflicts are resolved.


Automated notification by github-manager-bot

@RockteMQ-AI RockteMQ-AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Summary

This PR modifies 25 file(s) with 2415 lines of diff. Changes look reasonable.


Automated review by github-manager-bot

Additional notes (not anchored to a changed line)

  • [INFO] connectors/rocketmq-connect-http/README.md:1 — Large diff (2415 lines). Consider breaking into smaller, focused PRs for easier review. (line outside diff)

@RockteMQ-AI RockteMQ-AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Summary

PR received and logged for review. This PR requires detailed code review by a maintainer.

Diff size: 2415 lines
Author: zhaohai666 (CONTRIBUTOR)


Automated review by RockteMQ-AI

@RockteMQ-AI RockteMQ-AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Summary

Review of PR #384: update http

Findings: 16 issue(s) identified (4 critical).
CLA: unknown

Please address the inline comments above.


Automated review by github-manager-bot

oauth2ClientSecret = CheckUtils.checkNullReturnDefault(config.getString(HttpConstant.OAUTH2_CLIENTSECRET_CONSTANT));
oauth2HttpMethod = CheckUtils.checkNullReturnDefault(config.getString(HttpConstant.OAUTH2_HTTP_METHOD_CONSTANT));
proxyType = CheckUtils.checkNullReturnDefault(config.getString(HttpConstant.PROXY_TYPE_CONSTANT));
proxyHost = CheckUtils.checkNullReturnDefault(config.getString(HttpConstant.PROXY_HOST_CONSTANT));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

scheduledExecutorService is never initialized. The field is declared but only set via setScheduledExecutorService(), which is never called internally. In start(), scheduledExecutorService.scheduleAtFixedRate(...) will throw NullPointerException, preventing the task from starting entirely.

if (httpCallback.isFailed()) {
throw new RetriableException(httpCallback.getMsg());
}
} catch (Exception e) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The catch(Exception e) block wraps RetriableException (thrown at lines 97 and 100) in a new RuntimeException. This prevents the connector framework from recognizing retriable failures and retrying them. RetriableException should be caught separately and re-thrown unwrapped, or the catch block should not catch it.

public void init(ClientConfig config) {
try {
SSLContextBuilder sslContextBuilder = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
@Override

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

SSL/TLS verification is completely disabled: TrustStrategy.isTrusted always returns true (line 77) and NoopHostnameVerifier.verify always returns true (line 253). This makes all HTTPS connections vulnerable to man-in-the-middle attacks. This should at minimum be opt-in via a configuration flag, not the unconditional default.

package org.apache.rocketmq.connect.http.sink.auth;

import com.google.common.collect.Maps;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Uses com.sun.org.apache.xercesinternal.impl.dv.util.Base64, an internal JDK class not part of the public API. It may not exist in non-Oracle JDKs or future JDK versions, causing ClassNotFoundException at runtime. Should use java.util.Base64.getEncoder().encodeToString() instead.

HttpClientContext.create(), this.socksProxyConfig, httpCallback, MDC.get(LOG_SIFT_TAG));
Future<String> submit = executorServicePool.submit(httpRequestCallable);
String result = submit.get();
log.info("ApacheHttpClientImpl | execute| success | result : {}", result);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

execute() calls submit.get() which blocks indefinitely with no timeout. This makes the countDownLatch-based 30-second timeout in put() non-functional: if any HTTP request hangs and no 'timeout' config is set, submit.get() blocks forever and the latch await is never reached. Use submit.get(timeout, TimeUnit) or Future.cancel() on timeout.

private static final Logger log = LoggerFactory.getLogger(ApacheHttpClientImpl.class);

private static ExecutorService executorServicePool = new ThreadPoolExecutor(200, 2000, 600, TimeUnit.SECONDS,
new LinkedBlockingDeque<Runnable>(1000), new DefaultThreadFactory("ApacheHttpClientRequestThread"));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

executorServicePool is a static field shared across all connector instances but is never shut down in close(). This causes a thread leak (200 core threads) when connectors are stopped or recreated. The pool should be an instance field and shut down in close(), or use a shared lifecycle-managed pool.

PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(reg,
new FakeDnsResolver());
connManager.setMaxTotal(400);
connManager.setDefaultMaxPerRoute(500);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Connection pool configuration is illogical: setMaxTotal(400) is less than setDefaultMaxPerRoute(500). Since per-route connections cannot exceed the total, the effective per-route limit is capped at 400. These values should be consistent, with maxTotal >= defaultMaxPerRoute.

headerMap.put(entry.getKey(), (String) entry.getValue());
}
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

validate() always checks authType against AuthTypeEnum and throws if no match is found. But authType is marked optional (NO) in the README parameter table. If authType is not configured (null), the stream filter matches no enum and validation throws, contradicting the documented contract.

clientConfig.setTimeout(timeout);
clientConfig.setOauth2HttpMethod(oauth2HttpMethod);
clientConfig.setOauth2Endpoint(oauth2Endpoint);
clientConfig.setBasicUser(basicUser);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

In addHeaderMap, the else branch casts entry.getValue() to String without verifying the actual type. If the JSON header value is an Integer, Boolean, or JSONArray (not a JSONObject), this throws ClassCastException. Should use String.valueOf(entry.getValue()) or check all possible types.

http://${runtime-ip}:${runtime-port}/connectors/${rocketmq-http-sink-connector-name}
?config={"source-rocketmq":"${runtime-ip}:${runtime-port}","source-cluster":"${broker-cluster}","connector-class":"org.apache.rocketmq.connect.http.sink.HttpSinkConnector","connect-topicname" : "${connect-topicname}","url":"${url}"}
?config={"source-rocketmq":"${runtime-ip}:${runtime-port}","source-cluster":"${broker-cluster}","connector-class":"HttpSinkConnector",
"urlPattern":"${urlPattern}","method":"${method}","queryStringParameters":"${queryStringParameters}","headerParameters":"${headerParameters}","bodys":"${bodys}","authType":"${authType}","basicUser":"${basicUser}","basicPassword":"${basicPassword}",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The JSON config example has duplicate keys: proxyPort appears 3 times and proxyUser appears 2 times across lines 18-19. Duplicate JSON keys cause undefined behavior in parsers (only the last value is typically kept). These should be deduplicated to match the parameter table.

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