You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add generic Do[T] function for compile-time pointer enforcement (#809)
* Skip shard routing tests on OpenSearch < 2.2.0 with security
OpenSearch < 2.2.0 with the security plugin throws
java.io.OptionalDataException on shard-routed requests due to
non-thread-safe HashSet/HashMap in User serialization. Fixed in 2.2.0
by opensearch-project/security#1970 (50a94b47).
Widen the existing 2.1.0-only skip to cover all versions below 2.2.0.
Signed-off-by: Sean Chittenden <sean.chittenden@crowdstrike.com>
* Add generic Do[T] function for compile-time pointer enforcement
Client.Do() accepts `any` for its dataPointer parameter, deferring
pointer validation to json.Unmarshal at runtime. Add a top-level
opensearch.Do[T]() function whose *T signature catches non-pointer
arguments at compile time. The generic wrapper is trivially inlined
by the compiler -- zero runtime overhead.
Mark Client.Do() with a Deprecated doc annotation to nudge callers
toward the safer alternative via staticcheck SA1019 and IDE tooling.
The method remains fully functional and will not be removed.
Convert the unexported `do` method in opensearchapi, plugins/security,
and plugins/ism to package-level generic functions, enforcing pointer
safety across all internal call sites.
Fixes: #808
Signed-off-by: Sean Chittenden <sean.chittenden@crowdstrike.com>
* Improve transport test assertions
Replace magic status codes with http.StatusOK constants, use t.Context()
instead of manual context.WithCancel, and prefer require.Len/require.Positive
over less specific assertions.
Signed-off-by: Sean Chittenden <sean.chittenden@crowdstrike.com>
* Use require.Error/require.NoError in ParseError test
Replace require.NotNil/require.Nil with the semantically correct error
assertion helpers.
Signed-off-by: Sean Chittenden <sean.chittenden@crowdstrike.com>
* Add NoBody marker type and handle nil-body error responses
Introduce opensearch.NoBody as a marker type for Do[T] calls that expect
no response body, replacing the separate doRequest() function with a
unified dispatch path through the generic function.
Guard Do[T] against typed-nil pointers that would otherwise widen into a
non-nil any interface and reach json.Unmarshal. When dataPointer is nil
and the error response has no body, return a quoted-status error instead
of the misleading ErrUnexpectedEmptyBody.
Signed-off-by: Sean Chittenden <sean.chittenden@crowdstrike.com>
---------
Signed-off-by: Sean Chittenden <sean.chittenden@crowdstrike.com>
Copy file name to clipboardExpand all lines: CHANGELOG.md
+4Lines changed: 4 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,6 +7,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
7
7
### Added
8
8
9
9
- Add `primary_terms_map` and `split_shards_metadata` fields to ClusterState index metadata for OpenSearch >=3.6.0 compatibility
10
+
- Add generic `opensearch.Do[T]()` function for compile-time pointer enforcement on response types, preventing a class of bugs where non-pointer values are silently passed to `Client.Do()` and fail at runtime during JSON unmarshaling. Includes `opensearch.NoBody` marker type for calls that expect no response body, unifying all internal dispatch through a single generic path ([#809](https://github.com/opensearch-project/opensearch-go/pull/809))
10
11
- Add `InsecureSkipVerify` config option to disable TLS certificate verification without constructing a custom `http.Transport`, preserving `DefaultTransport` connection pooling, HTTP/2, and timeout defaults ([#786](https://github.com/opensearch-project/opensearch-go/issues/786))
11
12
- Add `DisableResponseBuffering` config option to skip eager `io.ReadAll` buffering of response bodies in `Perform()`, reducing per-request allocations and TTFB for proxy and streaming use cases ([#786](https://github.com/opensearch-project/opensearch-go/issues/786))
12
13
- Add per-attempt `RequestTimeout` to bound individual HTTP round-trips, preventing indefinite hangs on stalled connections ([#786](https://github.com/opensearch-project/opensearch-go/issues/786))
@@ -153,13 +154,16 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
153
154
154
155
### Deprecated
155
156
157
+
- Mark `Client.Do()` with a `Deprecated` doc annotation in favor of `opensearch.Do[T]()` for compile-time pointer safety; `Client.Do()` remains fully functional and will not be removed, but `staticcheck` SA1019 will nudge cross-package callers toward the safer generic alternative
158
+
156
159
### Removed
157
160
158
161
### Fixed
159
162
160
163
- Fix bulk indexer HTML-escaping `_id` and `routing` values containing `<`, `>`, or `&` characters, causing OpenSearch to store escaped values (e.g., `\u003croot_account\u003e` stored instead of `<root_account>`), leading to duplicate documents, unreachable data on read-by-ID paths, and potential shard routing mismatches. Present since the `json.Marshal` migration in 2021 (commit `3da59092`). Replace `json.Marshal` with `json.NewEncoder` + `SetEscapeHTML(false)` in `opensearchutil.worker.writeMeta` and `opensearchutil.JSONReader`; replace per-worker `aux []byte` with `sync.Pool`-backed `*bytes.Buffer`; add table-driven test coverage for `writeMeta` edge cases and refactor remaining `TestBulkIndexer` subtests to table-driven `require`-based style ([#824](https://github.com/opensearch-project/opensearch-go/pull/824))
161
164
- Fix pool replacement orphaning resurrection goroutines during node discovery, causing connections to become permanently dead with no active health checker ([#786](https://github.com/opensearch-project/opensearch-go/pull/786))
162
165
- Extract `newMultiServerPoolFromClientWithLock` as single source of truth for Client-to-pool settings propagation ([#786](https://github.com/opensearch-project/opensearch-go/pull/786))
166
+
- Skip shard routing integration tests on OpenSearch < 2.2.0 with security plugin due to server-side `OptionalDataException` from non-thread-safe User serialization (opensearch-project/security#1970)
163
167
- Fix discovery pool wipe when all cluster nodes time out during `/_nodes/http` fan-out: parse `_nodes` metadata envelope and return `errDiscoveryEmpty` when `successful == 0`, preserving the existing connection pool for retry ([#821](https://github.com/opensearch-project/opensearch-go/pull/821))
164
168
- Fix flaky `TestDefaultHealthCheck_RetryAfterMaxRetry`: replace wall-clock `time.Sleep` + `atomic.Int64` synchronization with context cancellation (`ctx.Done()`), and widen `maxRetryClusterHealth` to 5s so the baseline HTTP round-trip cannot race past the retry interval ([#787](https://github.com/opensearch-project/opensearch-go/pull/787))
165
169
- Skip opensearchtransport integration tests on OpenSearch < 2.2.0 with security plugin due to server-side `OptionalDataException` from non-thread-safe User serialization (opensearch-project/security#1970)
When you need to call an API that `opensearchapi` doesn't cover — plugin endpoints, newly released server APIs, or internal custom endpoints — use `opensearch.Do()` to execute a request and automatically unmarshal the JSON response into a struct.
49
+
50
+
The `Client.Do()` method accepts `any` for its response parameter, which means passing a non-pointer compiles but fails at runtime during JSON unmarshaling. The generic `opensearch.Do[T]()` function catches this mistake at compile time. `Client.Do()` is marked with a `Deprecated` doc annotation to steer callers toward the safer alternative — it remains fully functional and will not be removed, but `staticcheck` SA1019 will flag cross-package usage as a nudge.
51
+
52
+
First, define a request type that satisfies `opensearch.Request`:
53
+
54
+
```go
55
+
// customReq wraps opensearch.BuildRequest to satisfy the opensearch.Request interface.
0 commit comments