@platformatic/rdkafka 4.0.1 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/bench/seed.sh +0 -0
- package/binding.gyp +8 -1
- package/ci/prepublish.js +0 -1
- package/config.d.ts +126 -10
- package/configure +0 -0
- package/deps/librdkafka/.semaphore/run-all-tests.yml +77 -0
- package/deps/librdkafka/.semaphore/semaphore-integration.yml +250 -0
- package/deps/librdkafka/.semaphore/semaphore.yml +67 -44
- package/deps/librdkafka/.semaphore/verify-linux-packages.yml +41 -0
- package/deps/librdkafka/CHANGELOG.md +471 -1
- package/deps/librdkafka/CONFIGURATION.md +29 -9
- package/deps/librdkafka/INTRODUCTION.md +909 -601
- package/deps/librdkafka/LICENSES.txt +592 -1
- package/deps/librdkafka/Makefile +2 -1
- package/deps/librdkafka/_mkltmpuuWEwa.c +13 -0
- package/deps/librdkafka/configure +0 -0
- package/deps/librdkafka/debian/rules +0 -0
- package/deps/librdkafka/dev-conf.sh +0 -0
- package/deps/librdkafka/examples/consumer.c +18 -8
- package/deps/librdkafka/examples/describe_consumer_groups.c +25 -6
- package/deps/librdkafka/examples/incremental_alter_configs.c +4 -5
- package/deps/librdkafka/examples/kafkatest_verifiable_client.cpp +26 -42
- package/deps/librdkafka/examples/openssl_engine_example.cpp +3 -4
- package/deps/librdkafka/examples/producer.cpp +2 -2
- package/deps/librdkafka/examples/user_scram.c +4 -5
- package/deps/librdkafka/examples/win_ssl_cert_store.cpp +4 -3
- package/deps/librdkafka/lds-gen.py +0 -0
- package/deps/librdkafka/mklove/Makefile.base +0 -0
- package/deps/librdkafka/packaging/RELEASE.md +8 -0
- package/deps/librdkafka/packaging/alpine/build-alpine.sh +0 -0
- package/deps/librdkafka/packaging/cp/README.md +4 -1
- package/deps/librdkafka/packaging/cp/check_features.c +12 -4
- package/deps/librdkafka/packaging/cp/verify-deb.sh +6 -6
- package/deps/librdkafka/packaging/cp/verify-packages.sh +52 -31
- package/deps/librdkafka/packaging/cp/verify-rpm.sh +6 -13
- package/deps/librdkafka/packaging/debian/rules +0 -0
- package/deps/librdkafka/packaging/get_version.py +0 -0
- package/deps/librdkafka/packaging/homebrew/brew-update-pr.sh +0 -0
- package/deps/librdkafka/packaging/mingw-w64/{travis-before-install.sh → export-variables.sh} +0 -7
- package/deps/librdkafka/packaging/mingw-w64/semaphoreci-build.sh +1 -1
- package/deps/librdkafka/packaging/nuget/artifact.py +0 -0
- package/deps/librdkafka/packaging/nuget/cleanup-s3.py +0 -0
- package/deps/librdkafka/packaging/nuget/nuget.sh +0 -0
- package/deps/librdkafka/packaging/nuget/packaging.py +0 -0
- package/deps/librdkafka/packaging/nuget/push-to-nuget.sh +0 -0
- package/deps/librdkafka/packaging/nuget/release.py +0 -0
- package/deps/librdkafka/packaging/nuget/requirements.txt +3 -3
- package/deps/librdkafka/packaging/rpm/mock-on-docker.sh +0 -0
- package/deps/librdkafka/packaging/rpm/tests/run-test.sh +0 -0
- package/deps/librdkafka/packaging/rpm/tests/test-on-docker.sh +0 -0
- package/deps/librdkafka/packaging/tools/build-configurations-checks.sh +3 -1
- package/deps/librdkafka/packaging/tools/build-deb-package.sh +0 -0
- package/deps/librdkafka/packaging/tools/build-debian.sh +0 -0
- package/deps/librdkafka/packaging/tools/build-manylinux.sh +0 -0
- package/deps/librdkafka/packaging/tools/build-release-artifacts.sh +0 -0
- package/deps/librdkafka/packaging/tools/distro-build.sh +0 -0
- package/deps/librdkafka/packaging/tools/gh-release-checksums.py +0 -0
- package/deps/librdkafka/packaging/tools/rdutcoverage.sh +0 -0
- package/deps/librdkafka/packaging/tools/run-in-docker.sh +28 -0
- package/deps/librdkafka/packaging/tools/run-integration-tests.sh +31 -0
- package/deps/librdkafka/packaging/tools/run-style-check.sh +4 -0
- package/deps/librdkafka/packaging/tools/style-format.sh +6 -5
- package/deps/librdkafka/packaging/tools/update_rpcs_max_versions.py +100 -0
- package/deps/librdkafka/service.yml +154 -0
- package/deps/librdkafka/src/generate_proto.sh +0 -0
- package/deps/librdkafka/src/rd.h +145 -2
- package/deps/librdkafka/src/rdaddr.h +6 -7
- package/deps/librdkafka/src/rdatomic.h +15 -11
- package/deps/librdkafka/src/rdavg.h +3 -2
- package/deps/librdkafka/src/rdbase64.c +33 -2
- package/deps/librdkafka/src/rdbase64.h +2 -0
- package/deps/librdkafka/src/rdendian.h +10 -9
- package/deps/librdkafka/src/rdhttp.c +418 -100
- package/deps/librdkafka/src/rdhttp.h +23 -5
- package/deps/librdkafka/src/rdkafka.c +299 -145
- package/deps/librdkafka/src/rdkafka.h +89 -6
- package/deps/librdkafka/src/rdkafka_admin.c +482 -105
- package/deps/librdkafka/src/rdkafka_admin.h +42 -0
- package/deps/librdkafka/src/rdkafka_broker.c +463 -312
- package/deps/librdkafka/src/rdkafka_broker.h +68 -10
- package/deps/librdkafka/src/rdkafka_buf.c +8 -5
- package/deps/librdkafka/src/rdkafka_buf.h +4 -3
- package/deps/librdkafka/src/rdkafka_cert.c +25 -1
- package/deps/librdkafka/src/rdkafka_cert.h +4 -3
- package/deps/librdkafka/src/rdkafka_cgrp.c +468 -143
- package/deps/librdkafka/src/rdkafka_cgrp.h +36 -2
- package/deps/librdkafka/src/rdkafka_conf.c +526 -102
- package/deps/librdkafka/src/rdkafka_conf.h +68 -4
- package/deps/librdkafka/src/rdkafka_feature.c +472 -35
- package/deps/librdkafka/src/rdkafka_feature.h +2 -0
- package/deps/librdkafka/src/rdkafka_fetcher.c +22 -2
- package/deps/librdkafka/src/rdkafka_fetcher.h +2 -2
- package/deps/librdkafka/src/rdkafka_int.h +84 -46
- package/deps/librdkafka/src/rdkafka_metadata.c +221 -136
- package/deps/librdkafka/src/rdkafka_metadata.h +15 -11
- package/deps/librdkafka/src/rdkafka_metadata_cache.c +279 -73
- package/deps/librdkafka/src/rdkafka_mock.c +795 -19
- package/deps/librdkafka/src/rdkafka_mock.h +119 -0
- package/deps/librdkafka/src/rdkafka_mock_cgrp.c +1298 -132
- package/deps/librdkafka/src/rdkafka_mock_handlers.c +345 -49
- package/deps/librdkafka/src/rdkafka_mock_int.h +180 -61
- package/deps/librdkafka/src/rdkafka_msg.c +35 -19
- package/deps/librdkafka/src/rdkafka_msg.h +3 -3
- package/deps/librdkafka/src/rdkafka_msgset_writer.c +14 -10
- package/deps/librdkafka/src/rdkafka_offset.c +33 -5
- package/deps/librdkafka/src/rdkafka_op.c +1 -1
- package/deps/librdkafka/src/rdkafka_op.h +45 -21
- package/deps/librdkafka/src/rdkafka_partition.c +118 -23
- package/deps/librdkafka/src/rdkafka_partition.h +16 -7
- package/deps/librdkafka/src/rdkafka_proto.h +4 -1
- package/deps/librdkafka/src/rdkafka_protocol.h +1 -0
- package/deps/librdkafka/src/rdkafka_queue.c +125 -48
- package/deps/librdkafka/src/rdkafka_queue.h +19 -0
- package/deps/librdkafka/src/rdkafka_range_assignor.c +1 -1
- package/deps/librdkafka/src/rdkafka_request.c +336 -64
- package/deps/librdkafka/src/rdkafka_request.h +24 -1
- package/deps/librdkafka/src/rdkafka_sasl.c +5 -3
- package/deps/librdkafka/src/rdkafka_sasl_oauthbearer.c +14 -10
- package/deps/librdkafka/src/rdkafka_sasl_oauthbearer_oidc.c +1166 -89
- package/deps/librdkafka/src/rdkafka_sasl_oauthbearer_oidc.h +13 -3
- package/deps/librdkafka/src/rdkafka_sasl_plain.c +3 -3
- package/deps/librdkafka/src/rdkafka_sasl_scram.c +4 -3
- package/deps/librdkafka/src/rdkafka_ssl.c +306 -81
- package/deps/librdkafka/src/rdkafka_ssl.h +22 -0
- package/deps/librdkafka/src/rdkafka_sticky_assignor.c +4 -0
- package/deps/librdkafka/src/rdkafka_telemetry.c +80 -23
- package/deps/librdkafka/src/rdkafka_telemetry_encode.c +5 -1
- package/deps/librdkafka/src/rdkafka_telemetry_encode.h +20 -20
- package/deps/librdkafka/src/rdkafka_topic.c +220 -137
- package/deps/librdkafka/src/rdkafka_topic.h +14 -8
- package/deps/librdkafka/src/rdkafka_transport.c +59 -47
- package/deps/librdkafka/src/rdkafka_transport.h +5 -0
- package/deps/librdkafka/src/rdkafka_txnmgr.c +6 -1
- package/deps/librdkafka/src/rdmap.c +6 -1
- package/deps/librdkafka/src/rdrand.c +11 -1
- package/deps/librdkafka/src/rdtime.h +48 -17
- package/deps/librdkafka/src/rdunittest.c +42 -25
- package/deps/librdkafka/src/rdunittest.h +2 -0
- package/deps/librdkafka/src/rdwin32.h +1 -1
- package/deps/librdkafka/src/regexp.c +47 -42
- package/deps/librdkafka/src/tinycthread_extra.c +45 -21
- package/deps/librdkafka/src/tinycthread_extra.h +7 -3
- package/deps/librdkafka/src-cpp/rdkafkacpp.h +28 -2
- package/deps/librdkafka/tests/0001-multiobj.c +4 -0
- package/deps/librdkafka/tests/0004-conf.c +103 -36
- package/deps/librdkafka/tests/0009-mock_cluster.c +1 -0
- package/deps/librdkafka/tests/0011-produce_batch.c +2 -1
- package/deps/librdkafka/tests/0016-client_swname.c +18 -3
- package/deps/librdkafka/tests/0017-compression.c +6 -8
- package/deps/librdkafka/tests/0018-cgrp_term.c +8 -3
- package/deps/librdkafka/tests/0021-rkt_destroy.c +1 -0
- package/deps/librdkafka/tests/0022-consume_batch.c +4 -1
- package/deps/librdkafka/tests/0026-consume_pause.c +12 -14
- package/deps/librdkafka/tests/0028-long_topicnames.c +1 -1
- package/deps/librdkafka/tests/0029-assign_offset.c +6 -8
- package/deps/librdkafka/tests/0030-offset_commit.c +2 -2
- package/deps/librdkafka/tests/0033-regex_subscribe.c +33 -17
- package/deps/librdkafka/tests/0034-offset_reset.c +25 -4
- package/deps/librdkafka/tests/0036-partial_fetch.c +1 -0
- package/deps/librdkafka/tests/0038-performance.c +1 -0
- package/deps/librdkafka/tests/0040-io_event.c +11 -5
- package/deps/librdkafka/tests/0041-fetch_max_bytes.c +1 -0
- package/deps/librdkafka/tests/0044-partition_cnt.c +3 -2
- package/deps/librdkafka/tests/0045-subscribe_update.c +284 -20
- package/deps/librdkafka/tests/0047-partial_buf_tmout.c +1 -0
- package/deps/librdkafka/tests/0048-partitioner.c +1 -1
- package/deps/librdkafka/tests/0050-subscribe_adds.c +1 -0
- package/deps/librdkafka/tests/0051-assign_adds.c +1 -0
- package/deps/librdkafka/tests/0052-msg_timestamps.c +22 -4
- package/deps/librdkafka/tests/0053-stats_cb.cpp +12 -20
- package/deps/librdkafka/tests/0055-producer_latency.c +176 -3
- package/deps/librdkafka/tests/0056-balanced_group_mt.c +6 -2
- package/deps/librdkafka/tests/0058-log.cpp +3 -3
- package/deps/librdkafka/tests/0059-bsearch.cpp +8 -4
- package/deps/librdkafka/tests/0061-consumer_lag.cpp +25 -5
- package/deps/librdkafka/tests/0067-empty_topic.cpp +3 -0
- package/deps/librdkafka/tests/0068-produce_timeout.c +21 -23
- package/deps/librdkafka/tests/0069-consumer_add_parts.c +3 -7
- package/deps/librdkafka/tests/0075-retry.c +38 -1
- package/deps/librdkafka/tests/0076-produce_retry.c +2 -0
- package/deps/librdkafka/tests/0077-compaction.c +8 -2
- package/deps/librdkafka/tests/0080-admin_ut.c +34 -4
- package/deps/librdkafka/tests/0081-admin.c +455 -155
- package/deps/librdkafka/tests/0082-fetch_max_bytes.cpp +4 -0
- package/deps/librdkafka/tests/0083-cb_event.c +8 -3
- package/deps/librdkafka/tests/0084-destroy_flags.c +14 -18
- package/deps/librdkafka/tests/0085-headers.cpp +4 -0
- package/deps/librdkafka/tests/0086-purge.c +40 -7
- package/deps/librdkafka/tests/0088-produce_metadata_timeout.c +1 -1
- package/deps/librdkafka/tests/0089-max_poll_interval.c +12 -7
- package/deps/librdkafka/tests/0090-idempotence.c +1 -2
- package/deps/librdkafka/tests/0091-max_poll_interval_timeout.c +5 -7
- package/deps/librdkafka/tests/0092-mixed_msgver.c +6 -0
- package/deps/librdkafka/tests/0093-holb.c +8 -5
- package/deps/librdkafka/tests/0094-idempotence_msg_timeout.c +1 -0
- package/deps/librdkafka/tests/0097-ssl_verify.cpp +262 -70
- package/deps/librdkafka/tests/0098-consumer-txn.cpp +16 -16
- package/deps/librdkafka/tests/0099-commit_metadata.c +1 -1
- package/deps/librdkafka/tests/0101-fetch-from-follower.cpp +1 -1
- package/deps/librdkafka/tests/0102-static_group_rebalance.c +317 -16
- package/deps/librdkafka/tests/0103-transactions.c +7 -7
- package/deps/librdkafka/tests/0104-fetch_from_follower_mock.c +1 -0
- package/deps/librdkafka/tests/0105-transactions_mock.c +18 -11
- package/deps/librdkafka/tests/0106-cgrp_sess_timeout.c +35 -14
- package/deps/librdkafka/tests/0107-topic_recreate.c +2 -2
- package/deps/librdkafka/tests/0109-auto_create_topics.cpp +86 -26
- package/deps/librdkafka/tests/0110-batch_size.cpp +1 -2
- package/deps/librdkafka/tests/0112-assign_unknown_part.c +3 -14
- package/deps/librdkafka/tests/0113-cooperative_rebalance.cpp +248 -104
- package/deps/librdkafka/tests/0114-sticky_partitioning.cpp +3 -3
- package/deps/librdkafka/tests/0115-producer_auth.cpp +4 -1
- package/deps/librdkafka/tests/0116-kafkaconsumer_close.cpp +7 -5
- package/deps/librdkafka/tests/0117-mock_errors.c +15 -5
- package/deps/librdkafka/tests/0118-commit_rebalance.c +41 -8
- package/deps/librdkafka/tests/0119-consumer_auth.cpp +20 -1
- package/deps/librdkafka/tests/0120-asymmetric_subscription.c +8 -3
- package/deps/librdkafka/tests/0125-immediate_flush.c +1 -1
- package/deps/librdkafka/tests/0126-oauthbearer_oidc.c +323 -8
- package/deps/librdkafka/tests/0129-fetch_aborted_msgs.c +1 -0
- package/deps/librdkafka/tests/0132-strategy_ordering.c +12 -4
- package/deps/librdkafka/tests/0133-ssl_keys.c +28 -6
- package/deps/librdkafka/tests/0137-barrier_batch_consume.c +24 -14
- package/deps/librdkafka/tests/0139-offset_validation_mock.c +510 -2
- package/deps/librdkafka/tests/0140-commit_metadata.cpp +1 -1
- package/deps/librdkafka/tests/0142-reauthentication.c +37 -17
- package/deps/librdkafka/tests/0143-exponential_backoff_mock.c +39 -40
- package/deps/librdkafka/tests/0146-metadata_mock.c +76 -15
- package/deps/librdkafka/tests/0147-consumer_group_consumer_mock.c +952 -0
- package/deps/librdkafka/tests/0148-offset_fetch_commit_error_mock.c +563 -0
- package/deps/librdkafka/tests/0149-broker-same-host-port.c +140 -0
- package/deps/librdkafka/tests/0150-telemetry_mock.c +9 -6
- package/deps/librdkafka/tests/0151-purge-brokers.c +566 -0
- package/deps/librdkafka/tests/0152-rebootstrap.c +59 -0
- package/deps/librdkafka/tests/0153-memberid.c +128 -0
- package/deps/librdkafka/tests/CMakeLists.txt +6 -0
- package/deps/librdkafka/tests/LibrdkafkaTestApp.py +34 -9
- package/deps/librdkafka/tests/autotest.sh +0 -0
- package/deps/librdkafka/tests/broker_version_tests.py +0 -0
- package/deps/librdkafka/tests/buildbox.sh +0 -0
- package/deps/librdkafka/tests/cleanup-checker-tests.sh +0 -0
- package/deps/librdkafka/tests/cluster_testing.py +0 -0
- package/deps/librdkafka/tests/delete-test-topics.sh +0 -0
- package/deps/librdkafka/tests/fixtures/oauthbearer/jwt_assertion_template.json +10 -0
- package/deps/librdkafka/tests/fixtures/ssl/client.keystore.intermediate.p12 +0 -0
- package/deps/librdkafka/tests/fixtures/ssl/client.keystore.p12 +0 -0
- package/deps/librdkafka/tests/fixtures/ssl/client2.certificate.intermediate.pem +72 -0
- package/deps/librdkafka/tests/fixtures/ssl/client2.certificate.pem +42 -101
- package/deps/librdkafka/tests/fixtures/ssl/client2.intermediate.key +46 -0
- package/deps/librdkafka/tests/fixtures/ssl/client2.key +41 -29
- package/deps/librdkafka/tests/fixtures/ssl/create_keys.sh +112 -37
- package/deps/librdkafka/tests/gen-ssl-certs.sh +0 -0
- package/deps/librdkafka/tests/interactive_broker_version.py +0 -0
- package/deps/librdkafka/tests/java/Makefile +2 -1
- package/deps/librdkafka/tests/java/run-class.sh +0 -0
- package/deps/librdkafka/tests/lz4_manual_test.sh +0 -0
- package/deps/librdkafka/tests/multi-broker-version-test.sh +0 -0
- package/deps/librdkafka/tests/parse-refcnt.sh +0 -0
- package/deps/librdkafka/tests/performance_plot.py +0 -0
- package/deps/librdkafka/tests/requirements.txt +1 -1
- package/deps/librdkafka/tests/run-all-tests.sh +79 -0
- package/deps/librdkafka/tests/run-consumer-tests.sh +0 -0
- package/deps/librdkafka/tests/run-producer-tests.sh +0 -0
- package/deps/librdkafka/tests/run-test-batches.py +157 -0
- package/deps/librdkafka/tests/run-test.sh +0 -0
- package/deps/librdkafka/tests/sasl_test.py +0 -0
- package/deps/librdkafka/tests/test.c +478 -18
- package/deps/librdkafka/tests/test.h +62 -13
- package/deps/librdkafka/tests/testcpp.cpp +6 -1
- package/deps/librdkafka/tests/testcpp.h +30 -2
- package/deps/librdkafka/tests/testshared.h +16 -2
- package/deps/librdkafka/tests/tools/stats/graph.py +0 -0
- package/deps/librdkafka/tests/tools/stats/to_csv.py +1 -1
- package/deps/librdkafka/tests/trivup/trivup-0.14.0.tar.gz +0 -0
- package/deps/librdkafka/tests/until-fail.sh +0 -0
- package/deps/librdkafka/tests/xxxx-metadata.cpp +1 -1
- package/deps/librdkafka/vcpkg.json +1 -1
- package/deps/librdkafka/win32/setup-msys2.ps1 +24 -8
- package/deps/librdkafka/win32/setup-vcpkg.ps1 +28 -6
- package/deps/librdkafka/win32/tests/tests.vcxproj +6 -0
- package/deps/librdkafka/win32/wingetopt.h +5 -4
- package/errors.d.ts +27 -1
- package/lib/error.js +29 -3
- package/make_docs.sh +0 -0
- package/package.json +11 -11
- package/run_docker.sh +0 -0
- package/src/callbacks.cc +6 -9
- package/src/callbacks.h +1 -5
- package/test/kafka-consumer-worker.js +10 -7
- package/test/kafka-consumer.spec.js +32 -21
- package/ci/update-version.js +0 -123
- package/deps/librdkafka/.semaphore/project.yml +0 -43
- package/deps/librdkafka/.semaphore/project_public.yml +0 -20
- package/deps/librdkafka/win32/install-openssl.ps1 +0 -33
|
@@ -40,6 +40,10 @@
|
|
|
40
40
|
#include <curl/curl.h>
|
|
41
41
|
#include "rdhttp.h"
|
|
42
42
|
|
|
43
|
+
#if WITH_SSL
|
|
44
|
+
#include "rdkafka_ssl.h"
|
|
45
|
+
#endif
|
|
46
|
+
|
|
43
47
|
/** Maximum response size, increase as necessary. */
|
|
44
48
|
#define RD_HTTP_RESPONSE_SIZE_MAX 1024 * 1024 * 500 /* 500kb */
|
|
45
49
|
|
|
@@ -128,8 +132,171 @@ rd_http_req_write_cb(char *ptr, size_t size, size_t nmemb, void *userdata) {
|
|
|
128
132
|
return nmemb;
|
|
129
133
|
}
|
|
130
134
|
|
|
131
|
-
|
|
135
|
+
#if WITH_SSL
|
|
136
|
+
/**
|
|
137
|
+
* @brief Callback function for setting up the SSL_CTX for HTTPS requests.
|
|
138
|
+
*
|
|
139
|
+
* This function sets the default CA paths for the SSL_CTX, and if that fails,
|
|
140
|
+
* it attempts to probe and set a default CA location. If `probe` is forced
|
|
141
|
+
* it skips the default CA paths and directly probes for CA certificates.
|
|
142
|
+
*
|
|
143
|
+
* On Windows, it attempts to load CA root certificates from the
|
|
144
|
+
* configured Windows certificate stores before falling back to the default.
|
|
145
|
+
*
|
|
146
|
+
* @return `CURLE_OK` on success, or `CURLE_SSL_CACERT_BADFILE` on failure.
|
|
147
|
+
*/
|
|
148
|
+
static CURLcode
|
|
149
|
+
rd_http_ssl_ctx_function(CURL *curl, void *sslctx, void *userptr) {
|
|
150
|
+
SSL_CTX *ctx = (SSL_CTX *)sslctx;
|
|
151
|
+
rd_kafka_t *rk = (rd_kafka_t *)userptr;
|
|
152
|
+
int r = -1;
|
|
153
|
+
rd_bool_t force_probe =
|
|
154
|
+
!rd_strcmp(rk->rk_conf.https.ca_location, "probe");
|
|
155
|
+
rd_bool_t use_probe = force_probe;
|
|
156
|
+
|
|
157
|
+
#if WITH_STATIC_LIB_libcrypto
|
|
158
|
+
/* We fallback to `probe` when statically linked. */
|
|
159
|
+
use_probe = rd_true;
|
|
160
|
+
#endif
|
|
161
|
+
|
|
162
|
+
#ifdef _WIN32
|
|
163
|
+
/* Attempt to load CA root certificates from the
|
|
164
|
+
* configured Windows certificate stores. */
|
|
165
|
+
r = rd_kafka_ssl_win_load_cert_stores(rk, "https", ctx,
|
|
166
|
+
rk->rk_conf.ssl.ca_cert_stores);
|
|
167
|
+
if (r == 0) {
|
|
168
|
+
rd_kafka_log(rk, LOG_NOTICE, "CERTSTORE",
|
|
169
|
+
"No CA certificates loaded for `https` from "
|
|
170
|
+
"Windows certificate stores: "
|
|
171
|
+
"falling back to default OpenSSL CA paths");
|
|
172
|
+
r = -1;
|
|
173
|
+
} else if (r == -1)
|
|
174
|
+
rd_kafka_log(rk, LOG_NOTICE, "CERTSTORE",
|
|
175
|
+
"Failed to load CA certificates for `https` from "
|
|
176
|
+
"Windows certificate stores: "
|
|
177
|
+
"falling back to default OpenSSL CA paths");
|
|
178
|
+
|
|
179
|
+
if (r != -1) {
|
|
180
|
+
rd_kafka_dbg(rk, SECURITY, "SSL",
|
|
181
|
+
"Successfully loaded CA certificates for `https` "
|
|
182
|
+
"from Windows certificate stores");
|
|
183
|
+
return CURLE_OK; /* Success, CA certs loaded on Windows */
|
|
184
|
+
}
|
|
185
|
+
#endif
|
|
186
|
+
|
|
187
|
+
if (!force_probe) {
|
|
188
|
+
/* Previous default behavior: use predefined paths set when
|
|
189
|
+
* building OpenSSL. */
|
|
190
|
+
char errstr[512];
|
|
191
|
+
r = SSL_CTX_set_default_verify_paths(ctx);
|
|
192
|
+
if (r == 1) {
|
|
193
|
+
rd_kafka_dbg(rk, SECURITY, "SSL",
|
|
194
|
+
"SSL_CTX_set_default_verify_paths() "
|
|
195
|
+
"for `https` "
|
|
196
|
+
"succeeded");
|
|
197
|
+
return CURLE_OK; /* Success */
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/* Read error and clear the error stack. */
|
|
201
|
+
rd_kafka_ssl_error0(rk, NULL, "https", errstr, sizeof(errstr));
|
|
202
|
+
rd_kafka_dbg(rk, SECURITY, "SSL",
|
|
203
|
+
"SSL_CTX_set_default_verify_paths() "
|
|
204
|
+
"for `https` "
|
|
205
|
+
"failed: %s",
|
|
206
|
+
errstr);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (use_probe) {
|
|
210
|
+
/* We asked for probing or we're using
|
|
211
|
+
* a statically linked version of OpenSSL. */
|
|
212
|
+
|
|
213
|
+
r = rd_kafka_ssl_probe_and_set_default_ca_location(rk, "https",
|
|
214
|
+
ctx);
|
|
215
|
+
if (r == 0)
|
|
216
|
+
return CURLE_OK;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return CURLE_SSL_CACERT_BADFILE;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
static void rd_http_ssl_configure(rd_kafka_t *rk, CURL *hreq_curl) {
|
|
223
|
+
rd_bool_t force_probe =
|
|
224
|
+
!rd_strcmp(rk->rk_conf.https.ca_location, "probe");
|
|
225
|
+
|
|
226
|
+
if (!force_probe && rk->rk_conf.https.ca_location) {
|
|
227
|
+
rd_bool_t is_dir;
|
|
228
|
+
rd_kafka_dbg(rk, SECURITY, "SSL",
|
|
229
|
+
"Setting `https` CA certs from "
|
|
230
|
+
"configured location: %s",
|
|
231
|
+
rk->rk_conf.https.ca_location);
|
|
232
|
+
if (rd_file_stat(rk->rk_conf.https.ca_location, &is_dir)) {
|
|
233
|
+
if (is_dir) {
|
|
234
|
+
curl_easy_setopt(hreq_curl, CURLOPT_CAPATH,
|
|
235
|
+
rk->rk_conf.https.ca_location);
|
|
236
|
+
curl_easy_setopt(hreq_curl, CURLOPT_CAINFO,
|
|
237
|
+
NULL);
|
|
238
|
+
} else {
|
|
239
|
+
curl_easy_setopt(hreq_curl, CURLOPT_CAPATH,
|
|
240
|
+
NULL);
|
|
241
|
+
curl_easy_setopt(hreq_curl, CURLOPT_CAINFO,
|
|
242
|
+
rk->rk_conf.https.ca_location);
|
|
243
|
+
}
|
|
244
|
+
} else {
|
|
245
|
+
/* Path doesn't exist, don't set any trusted
|
|
246
|
+
* certificate. */
|
|
247
|
+
curl_easy_setopt(hreq_curl, CURLOPT_CAINFO, NULL);
|
|
248
|
+
curl_easy_setopt(hreq_curl, CURLOPT_CAPATH, NULL);
|
|
249
|
+
}
|
|
250
|
+
} else if (!force_probe && rk->rk_conf.https.ca_pem) {
|
|
251
|
+
#if CURL_AT_LEAST_VERSION(7, 77, 0)
|
|
252
|
+
struct curl_blob ca_blob = {
|
|
253
|
+
.data = rk->rk_conf.https.ca_pem,
|
|
254
|
+
.len = strlen(rk->rk_conf.https.ca_pem),
|
|
255
|
+
.flags = CURL_BLOB_COPY};
|
|
256
|
+
rd_kafka_dbg(rk, SECURITY, "SSL",
|
|
257
|
+
"Setting `https` CA certs from "
|
|
258
|
+
"configured PEM string");
|
|
259
|
+
curl_easy_setopt(hreq_curl, CURLOPT_CAINFO_BLOB, &ca_blob);
|
|
260
|
+
#endif
|
|
261
|
+
/* Only the blob should be set, no default paths. */
|
|
262
|
+
curl_easy_setopt(hreq_curl, CURLOPT_CAINFO, NULL);
|
|
263
|
+
curl_easy_setopt(hreq_curl, CURLOPT_CAPATH, NULL);
|
|
264
|
+
} else {
|
|
265
|
+
curl_easy_setopt(hreq_curl, CURLOPT_SSL_CTX_FUNCTION,
|
|
266
|
+
rd_http_ssl_ctx_function);
|
|
267
|
+
curl_easy_setopt(hreq_curl, CURLOPT_SSL_CTX_DATA, rk);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
#endif
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* @brief Check if the error returned from HTTP(S) is temporary or not.
|
|
274
|
+
*
|
|
275
|
+
* @returns If the \p error_code is temporary, return rd_true,
|
|
276
|
+
* otherwise return rd_false.
|
|
277
|
+
*
|
|
278
|
+
* @locality Any thread.
|
|
279
|
+
* @locks None.
|
|
280
|
+
* @locks_acquired None.
|
|
281
|
+
*/
|
|
282
|
+
static rd_bool_t rd_http_is_failure_temporary(int error_code) {
|
|
283
|
+
switch (error_code) {
|
|
284
|
+
case 408: /**< Request timeout */
|
|
285
|
+
case 425: /**< Too early */
|
|
286
|
+
case 429: /**< Too many requests */
|
|
287
|
+
case 500: /**< Internal server error */
|
|
288
|
+
case 502: /**< Bad gateway */
|
|
289
|
+
case 503: /**< Service unavailable */
|
|
290
|
+
case 504: /**< Gateway timeout */
|
|
291
|
+
return rd_true;
|
|
292
|
+
|
|
293
|
+
default:
|
|
294
|
+
return rd_false;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
132
297
|
|
|
298
|
+
rd_http_error_t *
|
|
299
|
+
rd_http_req_init(rd_kafka_t *rk, rd_http_req_t *hreq, const char *url) {
|
|
133
300
|
memset(hreq, 0, sizeof(*hreq));
|
|
134
301
|
|
|
135
302
|
hreq->hreq_curl = curl_easy_init();
|
|
@@ -139,8 +306,15 @@ rd_http_error_t *rd_http_req_init(rd_http_req_t *hreq, const char *url) {
|
|
|
139
306
|
hreq->hreq_buf = rd_buf_new(1, 1024);
|
|
140
307
|
|
|
141
308
|
curl_easy_setopt(hreq->hreq_curl, CURLOPT_URL, url);
|
|
309
|
+
#if CURL_AT_LEAST_VERSION(7, 85, 0)
|
|
310
|
+
curl_easy_setopt(hreq->hreq_curl, CURLOPT_PROTOCOLS_STR, "http,https");
|
|
311
|
+
#else
|
|
312
|
+
/* As of 06/10/2025 Debian 10 and CentOS Stream 9 ship with
|
|
313
|
+
* older CURL versions, remove this condition once they're not supported
|
|
314
|
+
* anymore. */
|
|
142
315
|
curl_easy_setopt(hreq->hreq_curl, CURLOPT_PROTOCOLS,
|
|
143
316
|
CURLPROTO_HTTP | CURLPROTO_HTTPS);
|
|
317
|
+
#endif
|
|
144
318
|
curl_easy_setopt(hreq->hreq_curl, CURLOPT_MAXREDIRS, 16);
|
|
145
319
|
curl_easy_setopt(hreq->hreq_curl, CURLOPT_TIMEOUT, 30);
|
|
146
320
|
curl_easy_setopt(hreq->hreq_curl, CURLOPT_ERRORBUFFER,
|
|
@@ -150,6 +324,10 @@ rd_http_error_t *rd_http_req_init(rd_http_req_t *hreq, const char *url) {
|
|
|
150
324
|
rd_http_req_write_cb);
|
|
151
325
|
curl_easy_setopt(hreq->hreq_curl, CURLOPT_WRITEDATA, (void *)hreq);
|
|
152
326
|
|
|
327
|
+
#if WITH_SSL
|
|
328
|
+
rd_http_ssl_configure(rk, hreq->hreq_curl);
|
|
329
|
+
#endif
|
|
330
|
+
|
|
153
331
|
return NULL;
|
|
154
332
|
}
|
|
155
333
|
|
|
@@ -191,35 +369,113 @@ const char *rd_http_req_get_content_type(rd_http_req_t *hreq) {
|
|
|
191
369
|
|
|
192
370
|
/**
|
|
193
371
|
* @brief Perform a blocking HTTP(S) request to \p url.
|
|
372
|
+
* Retries the request \p retries times with linear backoff.
|
|
373
|
+
* Interval of \p retry_ms milliseconds is used between retries.
|
|
194
374
|
*
|
|
195
|
-
*
|
|
196
|
-
*
|
|
375
|
+
* @param url The URL to perform the request to.
|
|
376
|
+
* @param headers_array Array of HTTP(S) headers to set, each element
|
|
377
|
+
* is a string in the form "key: value"
|
|
378
|
+
* @param headers_array_cnt Number of elements in \p headers_array.
|
|
379
|
+
* @param timeout_s Timeout in seconds for the request, 0 means default
|
|
380
|
+
* `rd_http_req_init()` timeout.
|
|
381
|
+
* @param retries Number of retries to perform on failure.
|
|
382
|
+
* @param retry_ms Milliseconds to wait between retries.
|
|
383
|
+
* @param rbufp (out) Pointer to a buffer that will be filled with the response.
|
|
384
|
+
* @param content_type (out, optional) Pointer to a string that will be filled
|
|
385
|
+
* with the content type of the response, if not NULL.
|
|
386
|
+
* @param response_code (out, optional) Pointer to an integer that will be
|
|
387
|
+
* filled with the HTTP response code, if not NULL.
|
|
197
388
|
*
|
|
198
|
-
* Returns NULL on success (HTTP response code < 400), or an error
|
|
199
|
-
* object on transport or HTTP error
|
|
200
|
-
*
|
|
201
|
-
*
|
|
389
|
+
* @return Returns NULL on success (HTTP response code < 400), or an error
|
|
390
|
+
* object on transport or HTTP error.
|
|
391
|
+
*
|
|
392
|
+
* @remark Returned error object, when non-NULL, must be destroyed
|
|
393
|
+
* by calling rd_http_error_destroy().
|
|
394
|
+
*
|
|
395
|
+
* @locality Any thread.
|
|
396
|
+
* @locks None.
|
|
397
|
+
* @locks_acquired None.
|
|
202
398
|
*/
|
|
203
|
-
rd_http_error_t *rd_http_get(
|
|
399
|
+
rd_http_error_t *rd_http_get(rd_kafka_t *rk,
|
|
400
|
+
const char *url,
|
|
401
|
+
char **headers_array,
|
|
402
|
+
size_t headers_array_cnt,
|
|
403
|
+
int timeout_s,
|
|
404
|
+
int retries,
|
|
405
|
+
int retry_ms,
|
|
406
|
+
rd_buf_t **rbufp,
|
|
407
|
+
char **content_type,
|
|
408
|
+
int *response_code) {
|
|
204
409
|
rd_http_req_t hreq;
|
|
205
|
-
rd_http_error_t *herr;
|
|
410
|
+
rd_http_error_t *herr = NULL;
|
|
411
|
+
struct curl_slist *headers = NULL;
|
|
412
|
+
char *header;
|
|
413
|
+
int i;
|
|
414
|
+
size_t len, j;
|
|
206
415
|
|
|
207
416
|
*rbufp = NULL;
|
|
417
|
+
if (content_type)
|
|
418
|
+
*content_type = NULL;
|
|
419
|
+
if (response_code)
|
|
420
|
+
*response_code = -1;
|
|
208
421
|
|
|
209
|
-
herr = rd_http_req_init(&hreq, url);
|
|
422
|
+
herr = rd_http_req_init(rk, &hreq, url);
|
|
210
423
|
if (unlikely(herr != NULL))
|
|
211
424
|
return herr;
|
|
212
425
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
426
|
+
for (j = 0; j < headers_array_cnt; j++) {
|
|
427
|
+
header = headers_array[j];
|
|
428
|
+
if (header && *header)
|
|
429
|
+
headers = curl_slist_append(headers, header);
|
|
430
|
+
}
|
|
431
|
+
curl_easy_setopt(hreq.hreq_curl, CURLOPT_HTTPHEADER, headers);
|
|
432
|
+
if (timeout_s > 0)
|
|
433
|
+
curl_easy_setopt(hreq.hreq_curl, CURLOPT_TIMEOUT, timeout_s);
|
|
434
|
+
|
|
435
|
+
for (i = 0; i <= retries; i++) {
|
|
436
|
+
if (rd_kafka_terminating(rk)) {
|
|
437
|
+
herr = rd_http_error_new(-1, "Terminating");
|
|
438
|
+
goto done;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
herr = rd_http_req_perform_sync(&hreq);
|
|
442
|
+
len = rd_buf_len(hreq.hreq_buf);
|
|
443
|
+
|
|
444
|
+
if (!herr) {
|
|
445
|
+
if (len > 0)
|
|
446
|
+
break; /* Success */
|
|
447
|
+
/* Empty response */
|
|
448
|
+
goto done;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/* Retry if HTTP(S) request returns temporary error and there
|
|
452
|
+
* are remaining retries, else fail. */
|
|
453
|
+
if (i == retries || !rd_http_is_failure_temporary(herr->code)) {
|
|
454
|
+
goto done;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/* Retry */
|
|
458
|
+
rd_http_error_destroy(herr);
|
|
459
|
+
rd_usleep(retry_ms * 1000 * (i + 1), &rk->rk_terminate);
|
|
217
460
|
}
|
|
218
461
|
|
|
219
462
|
*rbufp = hreq.hreq_buf;
|
|
220
463
|
hreq.hreq_buf = NULL;
|
|
221
464
|
|
|
222
|
-
|
|
465
|
+
if (content_type) {
|
|
466
|
+
const char *ct = rd_http_req_get_content_type(&hreq);
|
|
467
|
+
if (ct && *ct)
|
|
468
|
+
*content_type = rd_strdup(ct);
|
|
469
|
+
else
|
|
470
|
+
*content_type = NULL;
|
|
471
|
+
}
|
|
472
|
+
if (response_code)
|
|
473
|
+
*response_code = hreq.hreq_code;
|
|
474
|
+
|
|
475
|
+
done:
|
|
476
|
+
RD_IF_FREE(headers, curl_slist_free_all);
|
|
477
|
+
rd_http_req_destroy(&hreq);
|
|
478
|
+
return herr;
|
|
223
479
|
}
|
|
224
480
|
|
|
225
481
|
|
|
@@ -257,31 +513,6 @@ rd_http_error_t *rd_http_parse_json(rd_http_req_t *hreq, cJSON **jsonp) {
|
|
|
257
513
|
}
|
|
258
514
|
|
|
259
515
|
|
|
260
|
-
/**
|
|
261
|
-
* @brief Check if the error returned from HTTP(S) is temporary or not.
|
|
262
|
-
*
|
|
263
|
-
* @returns If the \p error_code is temporary, return rd_true,
|
|
264
|
-
* otherwise return rd_false.
|
|
265
|
-
*
|
|
266
|
-
* @locality Any thread.
|
|
267
|
-
*/
|
|
268
|
-
static rd_bool_t rd_http_is_failure_temporary(int error_code) {
|
|
269
|
-
switch (error_code) {
|
|
270
|
-
case 408: /**< Request timeout */
|
|
271
|
-
case 425: /**< Too early */
|
|
272
|
-
case 429: /**< Too many requests */
|
|
273
|
-
case 500: /**< Internal server error */
|
|
274
|
-
case 502: /**< Bad gateway */
|
|
275
|
-
case 503: /**< Service unavailable */
|
|
276
|
-
case 504: /**< Gateway timeout */
|
|
277
|
-
return rd_true;
|
|
278
|
-
|
|
279
|
-
default:
|
|
280
|
-
return rd_false;
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
|
|
285
516
|
/**
|
|
286
517
|
* @brief Perform a blocking HTTP(S) request to \p url with
|
|
287
518
|
* HTTP(S) headers and data with \p timeout_s.
|
|
@@ -310,7 +541,7 @@ rd_http_error_t *rd_http_post_expect_json(rd_kafka_t *rk,
|
|
|
310
541
|
size_t len;
|
|
311
542
|
const char *content_type;
|
|
312
543
|
|
|
313
|
-
herr = rd_http_req_init(&hreq, url);
|
|
544
|
+
herr = rd_http_req_init(rk, &hreq, url);
|
|
314
545
|
if (unlikely(herr != NULL))
|
|
315
546
|
return herr;
|
|
316
547
|
|
|
@@ -368,6 +599,39 @@ rd_http_error_t *rd_http_post_expect_json(rd_kafka_t *rk,
|
|
|
368
599
|
return herr;
|
|
369
600
|
}
|
|
370
601
|
|
|
602
|
+
/**
|
|
603
|
+
* @brief Append \p params to \p url, taking care of existing query parameters
|
|
604
|
+
* and hash fragments. \p params must be already URL encoded.
|
|
605
|
+
*
|
|
606
|
+
* @returns A newly allocated string with the appended parameters or NULL
|
|
607
|
+
* on error.
|
|
608
|
+
*/
|
|
609
|
+
char *rd_http_get_params_append(const char *url, const char *params) {
|
|
610
|
+
char *new_url;
|
|
611
|
+
CURLU *u = curl_url();
|
|
612
|
+
CURLUcode rc = curl_url_set(u, CURLUPART_URL, url, 0);
|
|
613
|
+
if (rc != CURLUE_OK)
|
|
614
|
+
goto err;
|
|
615
|
+
|
|
616
|
+
rc = curl_url_set(u, CURLUPART_QUERY, params, CURLU_APPENDQUERY);
|
|
617
|
+
if (rc != CURLUE_OK)
|
|
618
|
+
goto err;
|
|
619
|
+
|
|
620
|
+
rc = curl_url_set(u, CURLUPART_FRAGMENT, NULL,
|
|
621
|
+
0); // remove hash fragment
|
|
622
|
+
if (rc != CURLUE_OK)
|
|
623
|
+
goto err;
|
|
624
|
+
|
|
625
|
+
rc = curl_url_get(u, CURLUPART_URL, &new_url, 0);
|
|
626
|
+
if (rc != CURLUE_OK)
|
|
627
|
+
goto err;
|
|
628
|
+
|
|
629
|
+
curl_url_cleanup(u);
|
|
630
|
+
return new_url;
|
|
631
|
+
err:
|
|
632
|
+
curl_url_cleanup(u);
|
|
633
|
+
return NULL;
|
|
634
|
+
}
|
|
371
635
|
|
|
372
636
|
/**
|
|
373
637
|
* @brief Same as rd_http_get() but requires a JSON response.
|
|
@@ -375,66 +639,51 @@ rd_http_error_t *rd_http_post_expect_json(rd_kafka_t *rk,
|
|
|
375
639
|
*
|
|
376
640
|
* Same error semantics as rd_http_get().
|
|
377
641
|
*/
|
|
378
|
-
rd_http_error_t *rd_http_get_json(
|
|
379
|
-
|
|
642
|
+
rd_http_error_t *rd_http_get_json(rd_kafka_t *rk,
|
|
643
|
+
const char *url,
|
|
644
|
+
char **headers_array,
|
|
645
|
+
size_t headers_array_cnt,
|
|
646
|
+
int timeout_s,
|
|
647
|
+
int retries,
|
|
648
|
+
int retry_ms,
|
|
649
|
+
cJSON **jsonp) {
|
|
380
650
|
rd_http_error_t *herr;
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
char
|
|
385
|
-
|
|
651
|
+
int response_code;
|
|
652
|
+
char *content_type;
|
|
653
|
+
rd_buf_t *rbuf;
|
|
654
|
+
char **headers_array_new =
|
|
655
|
+
rd_calloc(headers_array_cnt + 1, sizeof(*headers_array_new));
|
|
656
|
+
rd_http_req_t hreq;
|
|
386
657
|
|
|
387
658
|
*jsonp = NULL;
|
|
388
659
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
660
|
+
memcpy(headers_array_new, headers_array,
|
|
661
|
+
headers_array_cnt * sizeof(*headers_array_new));
|
|
662
|
+
headers_array_new[headers_array_cnt++] = "Accept: application/json";
|
|
392
663
|
|
|
393
|
-
|
|
664
|
+
herr = rd_http_get(rk, url, headers_array_new, headers_array_cnt,
|
|
665
|
+
timeout_s, retries, retry_ms, &rbuf, &content_type,
|
|
666
|
+
&response_code);
|
|
667
|
+
rd_free(headers_array_new);
|
|
394
668
|
|
|
395
|
-
herr
|
|
396
|
-
len = rd_buf_len(hreq.hreq_buf);
|
|
397
|
-
if (herr && len == 0) {
|
|
398
|
-
rd_http_req_destroy(&hreq);
|
|
669
|
+
if (unlikely(herr != NULL))
|
|
399
670
|
return herr;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
if (len == 0) {
|
|
403
|
-
/* Empty response: create empty JSON object */
|
|
404
|
-
*jsonp = cJSON_CreateObject();
|
|
405
|
-
rd_http_req_destroy(&hreq);
|
|
406
|
-
return NULL;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
content_type = rd_http_req_get_content_type(&hreq);
|
|
410
671
|
|
|
411
672
|
if (!content_type || rd_strncasecmp(content_type, "application/json",
|
|
412
673
|
strlen("application/json"))) {
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
674
|
+
herr = rd_http_error_new(response_code,
|
|
675
|
+
"Response is not JSON encoded: %s",
|
|
676
|
+
content_type ? content_type : "(n/a)");
|
|
677
|
+
RD_IF_FREE(rbuf, rd_buf_destroy_free);
|
|
678
|
+
RD_IF_FREE(content_type, rd_free);
|
|
418
679
|
return herr;
|
|
419
680
|
}
|
|
420
681
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
/* Parse JSON */
|
|
428
|
-
end = NULL;
|
|
429
|
-
*jsonp = cJSON_ParseWithOpts(raw_json, &end, 0);
|
|
430
|
-
if (!*jsonp && !herr)
|
|
431
|
-
herr = rd_http_error_new(hreq.hreq_code,
|
|
432
|
-
"Failed to parse JSON response "
|
|
433
|
-
"at %" PRIusz "/%" PRIusz,
|
|
434
|
-
(size_t)(end - raw_json), len);
|
|
435
|
-
|
|
436
|
-
rd_free(raw_json);
|
|
437
|
-
rd_http_req_destroy(&hreq);
|
|
682
|
+
hreq.hreq_buf = rbuf;
|
|
683
|
+
hreq.hreq_code = response_code;
|
|
684
|
+
herr = rd_http_parse_json(&hreq, jsonp);
|
|
685
|
+
RD_IF_FREE(rbuf, rd_buf_destroy_free);
|
|
686
|
+
RD_IF_FREE(content_type, rd_free);
|
|
438
687
|
|
|
439
688
|
return herr;
|
|
440
689
|
}
|
|
@@ -445,35 +694,28 @@ void rd_http_global_init(void) {
|
|
|
445
694
|
}
|
|
446
695
|
|
|
447
696
|
|
|
448
|
-
|
|
449
|
-
* @brief Unittest. Requires a (local) webserver to be set with env var
|
|
450
|
-
* RD_UT_HTTP_URL=http://localhost:1234/some-path
|
|
451
|
-
*
|
|
452
|
-
* This server must return a JSON object or array containing at least one
|
|
453
|
-
* object on the main URL with a 2xx response code,
|
|
454
|
-
* and 4xx response on $RD_UT_HTTP_URL/error (with whatever type of body).
|
|
455
|
-
*/
|
|
456
|
-
|
|
457
|
-
int unittest_http(void) {
|
|
697
|
+
int unittest_http_get(void) {
|
|
458
698
|
const char *base_url = rd_getenv("RD_UT_HTTP_URL", NULL);
|
|
459
699
|
char *error_url;
|
|
460
700
|
size_t error_url_size;
|
|
461
701
|
cJSON *json, *jval;
|
|
462
702
|
rd_http_error_t *herr;
|
|
463
703
|
rd_bool_t empty;
|
|
704
|
+
rd_kafka_t *rk;
|
|
464
705
|
|
|
465
706
|
if (!base_url || !*base_url)
|
|
466
707
|
RD_UT_SKIP("RD_UT_HTTP_URL environment variable not set");
|
|
467
708
|
|
|
468
709
|
RD_UT_BEGIN();
|
|
469
710
|
|
|
711
|
+
rk = rd_calloc(1, sizeof(*rk));
|
|
470
712
|
error_url_size = strlen(base_url) + strlen("/error") + 1;
|
|
471
713
|
error_url = rd_alloca(error_url_size);
|
|
472
714
|
rd_snprintf(error_url, error_url_size, "%s/error", base_url);
|
|
473
715
|
|
|
474
716
|
/* Try the base url first, parse its JSON and extract a key-value. */
|
|
475
717
|
json = NULL;
|
|
476
|
-
herr = rd_http_get_json(base_url, &json);
|
|
718
|
+
herr = rd_http_get_json(rk, base_url, NULL, 0, 5, 1, 1000, &json);
|
|
477
719
|
RD_UT_ASSERT(!herr, "Expected get_json(%s) to succeed, got: %s",
|
|
478
720
|
base_url, herr->errstr);
|
|
479
721
|
|
|
@@ -493,7 +735,7 @@ int unittest_http(void) {
|
|
|
493
735
|
|
|
494
736
|
/* Try the error URL, verify error code. */
|
|
495
737
|
json = NULL;
|
|
496
|
-
herr = rd_http_get_json(error_url, &json);
|
|
738
|
+
herr = rd_http_get_json(rk, error_url, NULL, 0, 5, 1, 1000, &json);
|
|
497
739
|
RD_UT_ASSERT(herr != NULL, "Expected get_json(%s) to fail", error_url);
|
|
498
740
|
RD_UT_ASSERT(herr->code >= 400,
|
|
499
741
|
"Expected get_json(%s) error code >= "
|
|
@@ -507,6 +749,82 @@ int unittest_http(void) {
|
|
|
507
749
|
if (json)
|
|
508
750
|
cJSON_Delete(json);
|
|
509
751
|
rd_http_error_destroy(herr);
|
|
752
|
+
rd_free(rk);
|
|
510
753
|
|
|
511
754
|
RD_UT_PASS();
|
|
512
755
|
}
|
|
756
|
+
|
|
757
|
+
int unittest_http_get_params_append(void) {
|
|
758
|
+
rd_kafka_t *rk;
|
|
759
|
+
char *res;
|
|
760
|
+
RD_UT_BEGIN();
|
|
761
|
+
char *tests[] = {"http://localhost:1234",
|
|
762
|
+
"",
|
|
763
|
+
"http://localhost:1234/",
|
|
764
|
+
|
|
765
|
+
"http://localhost:1234/",
|
|
766
|
+
"a=1",
|
|
767
|
+
"http://localhost:1234/?a=1",
|
|
768
|
+
|
|
769
|
+
"https://localhost:1234/",
|
|
770
|
+
"a=1&b=2",
|
|
771
|
+
"https://localhost:1234/?a=1&b=2",
|
|
772
|
+
|
|
773
|
+
"http://mydomain.com/?a=1",
|
|
774
|
+
"c=hi",
|
|
775
|
+
"http://mydomain.com/?a=1&c=hi",
|
|
776
|
+
|
|
777
|
+
"https://mydomain.com/?",
|
|
778
|
+
"c=hi",
|
|
779
|
+
"https://mydomain.com/?c=hi",
|
|
780
|
+
|
|
781
|
+
"http://localhost:1234/path?a=1&b=2#&c=3",
|
|
782
|
+
"c=hi",
|
|
783
|
+
"http://localhost:1234/path?a=1&b=2&c=hi",
|
|
784
|
+
|
|
785
|
+
"http://localhost:1234#?c=3",
|
|
786
|
+
"a=1",
|
|
787
|
+
"http://localhost:1234/?a=1",
|
|
788
|
+
|
|
789
|
+
"https://otherdomain.io/path?a=1&#c=3",
|
|
790
|
+
"b=2",
|
|
791
|
+
"https://otherdomain.io/path?a=1&b=2",
|
|
792
|
+
NULL};
|
|
793
|
+
|
|
794
|
+
|
|
795
|
+
res = rd_http_get_params_append("", "");
|
|
796
|
+
RD_UT_ASSERT(!res, "Expected NULL result, got: \"%s\"", res);
|
|
797
|
+
res = rd_http_get_params_append("", "a=2&b=3");
|
|
798
|
+
RD_UT_ASSERT(!res, "Expected NULL result, got: \"%s\"", res);
|
|
799
|
+
|
|
800
|
+
char **test = tests;
|
|
801
|
+
rk = rd_calloc(1, sizeof(*rk));
|
|
802
|
+
while (test[0]) {
|
|
803
|
+
res = rd_http_get_params_append(test[0], test[1]);
|
|
804
|
+
RD_UT_ASSERT(!strcmp(res, test[2]),
|
|
805
|
+
"Expected \"%s\", got: \"%s\"", test[2], res);
|
|
806
|
+
rd_free(res);
|
|
807
|
+
test += 3;
|
|
808
|
+
}
|
|
809
|
+
rd_free(rk);
|
|
810
|
+
|
|
811
|
+
RD_UT_PASS();
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
/**
|
|
815
|
+
* @brief Unittest. Requires a (local) webserver to be set with env var
|
|
816
|
+
* RD_UT_HTTP_URL=http://localhost:1234/some-path
|
|
817
|
+
*
|
|
818
|
+
* This server must return a JSON object or array containing at least one
|
|
819
|
+
* object on the main URL with a 2xx response code,
|
|
820
|
+
* and 4xx response on $RD_UT_HTTP_URL/error (with whatever type of body).
|
|
821
|
+
*/
|
|
822
|
+
|
|
823
|
+
int unittest_http(void) {
|
|
824
|
+
int fails = 0;
|
|
825
|
+
|
|
826
|
+
fails += unittest_http_get();
|
|
827
|
+
fails += unittest_http_get_params_append();
|
|
828
|
+
|
|
829
|
+
return fails;
|
|
830
|
+
}
|