Skip to content

Fix #96: update SDK HTTP clients to match REST API cleanups#97

Merged
orpiske merged 2 commits intowanaku-ai:mainfrom
orpiske:ci-issue-96
Mar 19, 2026
Merged

Fix #96: update SDK HTTP clients to match REST API cleanups#97
orpiske merged 2 commits intowanaku-ai:mainfrom
orpiske:ci-issue-96

Conversation

@orpiske
Copy link
Contributor

@orpiske orpiske commented Mar 19, 2026

Summary

  • Update DiscoveryServiceHttpClient to match upstream REST API changes: remove /register and /deregister action paths, change deregister from POST to DELETE, rename /ping to /heartbeats
  • Update ServicesHttpClient to use RESTful paths and proper HTTP verbs across all API endpoints (tools, resources, forwards, namespaces, data stores)
  • Fix executeDelete to use actual HTTP DELETE instead of PUT
  • Update method signatures for updateTool, updateResource, updateForward (accept name + body) and removeForward (accept name instead of ForwardReference)

Test plan

  • Added DiscoveryServiceHttpClientTest with embedded HTTP server verifying correct paths and HTTP methods for register, deregister, and ping
  • Added ServicesHttpClientTest with embedded HTTP server verifying correct paths and HTTP methods for all tools, resources, forwards, namespaces, and data stores operations
  • All existing tests pass
  • Full mvn verify passes

References

Summary by Sourcery

Align service and discovery HTTP clients with updated REST API contracts and HTTP semantics.

Bug Fixes:

  • Correct DELETE operations in the services HTTP client to use the proper HTTP DELETE method instead of PUT.

Enhancements:

  • Update ServicesHttpClient endpoints to use RESTful resource paths and appropriate HTTP verbs for tools, resources, forwards, namespaces, and data stores.
  • Adjust DiscoveryServiceHttpClient registration, deregistration, and heartbeat endpoints to match the new base paths and HTTP methods.
  • Change update methods for tools, resources, and forwards to accept a resource name plus body instead of relying solely on the reference object.
  • Simplify forward removal to address forwards by name instead of passing a full ForwardReference.

Build:

  • Add JUnit Jupiter test dependency to the capabilities-services-client module.

Tests:

  • Add ServicesHttpClientTest to validate HTTP methods and paths for all service API operations against an embedded HTTP server.
  • Add DiscoveryServiceHttpClientTest to verify correct HTTP methods and paths for register, deregister, and heartbeat interactions with the discovery API.

- DiscoveryServiceHttpClient: remove /register and /deregister action
  paths, change deregister from POST to DELETE, rename /ping to
  /heartbeats
- ServicesHttpClient: remove action paths (/add, /list, /remove, etc.)
  from all API endpoints, use proper HTTP verbs (DELETE instead of PUT
  for removals, PUT for updates, GET for retrieval by name), update
  method signatures for updateTool, updateResource, updateForward
  (accept name parameter), and removeForward (accept name instead of
  ForwardReference)
- executeDelete now uses DELETE instead of PUT
- Add tests for both clients using embedded HTTP server with mock OIDC
@sourcery-ai
Copy link

sourcery-ai bot commented Mar 19, 2026

Reviewer's Guide

Aligns the Discovery and Services SDK HTTP clients with the upstream REST API by making their endpoints RESTful (paths and verbs), fixing DELETE semantics, updating a few method signatures, and adding focused HTTP-level tests using embedded servers to validate all paths and methods.

Sequence diagram for DiscoveryServiceHttpClient RESTful interactions

sequenceDiagram
    actor ClientApp
    participant DiscoveryServiceHttpClient
    participant DiscoveryAPI

    ClientApp->>DiscoveryServiceHttpClient: register(serviceTarget)
    DiscoveryServiceHttpClient->>DiscoveryAPI: POST serviceBasePath
    DiscoveryAPI-->>DiscoveryServiceHttpClient: 201 Created
    DiscoveryServiceHttpClient-->>ClientApp: HttpResponse

    ClientApp->>DiscoveryServiceHttpClient: deregister(serviceTarget)
    DiscoveryServiceHttpClient->>DiscoveryAPI: DELETE serviceBasePath
    DiscoveryAPI-->>DiscoveryServiceHttpClient: 200 OK
    DiscoveryServiceHttpClient-->>ClientApp: HttpResponse

    ClientApp->>DiscoveryServiceHttpClient: ping(id)
    DiscoveryServiceHttpClient->>DiscoveryAPI: GET serviceBasePath/heartbeats
    DiscoveryAPI-->>DiscoveryServiceHttpClient: 200 OK
    DiscoveryServiceHttpClient-->>ClientApp: HttpResponse
Loading

Sequence diagram for ServicesHttpClient RESTful tool lifecycle

sequenceDiagram
    actor SdkUser
    participant ServicesHttpClient
    participant ServicesAPI

    SdkUser->>ServicesHttpClient: addTool(toolReference)
    ServicesHttpClient->>ServicesAPI: POST /api/v1/tools
    ServicesAPI-->>ServicesHttpClient: WanakuResponse ToolReference
    ServicesHttpClient-->>SdkUser: WanakuResponse ToolReference

    SdkUser->>ServicesHttpClient: getToolByName(name)
    ServicesHttpClient->>ServicesAPI: GET /api/v1/tools/{name}
    ServicesAPI-->>ServicesHttpClient: WanakuResponse ToolReference
    ServicesHttpClient-->>SdkUser: WanakuResponse ToolReference

    SdkUser->>ServicesHttpClient: updateTool(name, toolReference)
    ServicesHttpClient->>ServicesAPI: PUT /api/v1/tools/{name}
    ServicesAPI-->>ServicesHttpClient: 204 NoContent
    ServicesHttpClient-->>SdkUser: void

    SdkUser->>ServicesHttpClient: removeTool(toolName)
    ServicesHttpClient->>ServicesAPI: DELETE /api/v1/tools/{toolName}
    ServicesAPI-->>ServicesHttpClient: 204 NoContent
    ServicesHttpClient-->>SdkUser: void
Loading

Updated class diagram for DiscoveryServiceHttpClient and ServicesHttpClient

classDiagram
    class DiscoveryServiceHttpClient {
        - String baseUrl
        - String serviceBasePath
        - HttpClient httpClient
        - ServiceAuthenticator serviceAuthenticator
        - Serializer serializer
        + HttpResponse register(ServiceTarget serviceTarget)
        + HttpResponse deregister(ServiceTarget serviceTarget)
        + HttpResponse ping(String id)
        - HttpResponse executePost(String operationPath, ServiceTarget serviceTarget)
        - HttpResponse executeDelete(String operationPath, ServiceTarget serviceTarget)
    }

    class ServicesHttpClient {
        - String baseUrl
        - HttpClient httpClient
        - ServiceAuthenticator serviceAuthenticator
        + WanakuResponse addTool(ToolReference toolReference)
        + WanakuResponse addToolWithPayload(ToolPayload toolPayload)
        + WanakuResponse listTools()
        + WanakuResponse getToolByName(String name)
        + void updateTool(String name, ToolReference toolReference)
        + void removeTool(String toolName)
        + WanakuResponse exposeResource(ResourceReference resourceReference)
        + WanakuResponse exposeResourceWithPayload(ResourcePayload resourcePayload)
        + WanakuResponse listResources()
        + void updateResource(String name, ResourceReference resourceReference)
        + void removeResource(String resourceName)
        + void addForward(ForwardReference forwardReference)
        + WanakuResponse listForwards()
        + void updateForward(String name, ForwardReference forwardReference)
        + void removeForward(String name)
        + WanakuResponse listNamespaces()
        + WanakuResponse addDataStore(DataStore dataStore)
        + WanakuResponse listDataStores()
        + WanakuResponse getDataStoreById(String id)
        + WanakuResponse getDataStoresByName(String name)
        + void removeDataStore(String id)
        + void removeDataStoresByName(String name)
        - void executeDelete(String path)
    }

    DiscoveryServiceHttpClient ..> ServiceTarget
    ServicesHttpClient ..> ToolReference
    ServicesHttpClient ..> ToolPayload
    ServicesHttpClient ..> ResourceReference
    ServicesHttpClient ..> ResourcePayload
    ServicesHttpClient ..> ForwardReference
    ServicesHttpClient ..> Namespace
    ServicesHttpClient ..> DataStore
    ServicesHttpClient ..> WanakuResponse
    DiscoveryServiceHttpClient ..> WanakuException
    ServicesHttpClient ..> WanakuException
Loading

File-Level Changes

Change Details Files
Fix DELETE semantics and RESTful paths/verbs in ServicesHttpClient.
  • Changed executeDelete to send an actual HTTP DELETE request instead of PUT with no body.
  • Reworked tools endpoints to use /api/v1/tools as a collection (POST, GET) and /api/v1/tools/{name} for item operations (GET, PUT, DELETE).
  • Reworked resources endpoints to use /api/v1/resources and /api/v1/resources/{name} with POST/GET/PUT/DELETE as appropriate.
  • Reworked forwards endpoints to use /api/v1/forwards and /api/v1/forwards/{name}, and switched removeForward to DELETE by name instead of PUT with a body.
  • Updated namespaces and data-store endpoints to use collection/item REST-style paths and consistent query parameters (e.g., /api/v1/data-store, /api/v1/data-store/{id}, /api/v1/data-store?name=...).
  • Adjusted public method signatures for updateTool, updateResource, updateForward to accept a name plus body, and changed removeForward to accept a name string.
capabilities-services-client/src/main/java/ai/wanaku/capabilities/sdk/services/ServicesHttpClient.java
Align DiscoveryServiceHttpClient with new discovery API semantics and paths.
  • Added executeDelete helper that issues DELETE with a JSON ServiceTarget body and shared auth/headers.
  • Changed register to POST to the discovery base path instead of /register.
  • Changed deregister to use DELETE to the discovery base path instead of POST to /deregister.
  • Updated ping to call the /heartbeats sub-path instead of /ping.
capabilities-discovery/src/main/java/ai/wanaku/capabilities/sdk/discovery/DiscoveryServiceHttpClient.java
Add embedded-HTTP-server tests to verify all client paths and methods and wire in test dependencies.
  • Added JUnit 5 test dependency to the services-client module POM.
  • Introduced ServicesHttpClientTest that spins up a local HttpServer, stubs OIDC/token endpoints, and asserts on HTTP method and path for all tools, resources, forwards, namespaces, and data-store operations.
  • Introduced DiscoveryServiceHttpClientTest that spins up a local HttpServer and asserts that register, deregister, and ping use the expected methods and paths (/api/v1/management/discovery and /heartbeats).
capabilities-services-client/pom.xml
capabilities-services-client/src/test/java/ai/wanaku/capabilities/sdk/services/ServicesHttpClientTest.java
capabilities-discovery/src/test/java/ai/wanaku/capabilities/sdk/discovery/DiscoveryServiceHttpClientTest.java

Assessment against linked issues

Issue Objective Addressed Explanation
#96 Update ServicesHttpClient to use the new RESTful paths and HTTP verbs for Tools, Resources, Forwards, Namespaces, and DataStores, including refactoring executeDelete to use the DELETE verb and adjusting method signatures where necessary.
#96 Update DiscoveryServiceHttpClient to match the new discovery API: register at the base path with POST (no /register), deregister with DELETE at the base path (no /deregister), and rename the ping endpoint to /heartbeats.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • The various get*ByName, update*, and remove* methods in ServicesHttpClient build URLs by simple string concatenation (e.g., "/api/v1/tools/" + name and query params like "?name=" + name); consider URL-encoding these dynamic segments/parameters to avoid issues with special characters in names and IDs.
  • DiscoveryServiceHttpClient.executePost and executeDelete are nearly identical aside from the HTTP method; consider extracting a shared private helper that takes the verb as a parameter to reduce duplication and keep behavior changes (headers, serialization, error handling) in one place.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The various `get*ByName`, `update*`, and `remove*` methods in `ServicesHttpClient` build URLs by simple string concatenation (e.g., `"/api/v1/tools/" + name` and query params like `"?name=" + name`); consider URL-encoding these dynamic segments/parameters to avoid issues with special characters in names and IDs.
- `DiscoveryServiceHttpClient.executePost` and `executeDelete` are nearly identical aside from the HTTP method; consider extracting a shared private helper that takes the verb as a parameter to reduce duplication and keep behavior changes (headers, serialization, error handling) in one place.

## Individual Comments

### Comment 1
<location path="capabilities-discovery/src/test/java/ai/wanaku/capabilities/sdk/discovery/DiscoveryServiceHttpClientTest.java" line_range="60-62" />
<code_context>
+        });
+
+        // Discovery API endpoint
+        server.createContext("/api/v1/management/discovery", exchange -> {
+            String body = new String(exchange.getRequestBody().readAllBytes());
+            requests.add(new RequestRecord(
+                    exchange.getRequestMethod(), exchange.getRequestURI().getPath(), body));
+
</code_context>
<issue_to_address>
**suggestion (testing):** Consider asserting on the serialized request body for register/deregister

Since the server is already capturing the request body, consider extending the tests to assert on `requests.getFirst().body()` as well, verifying key `ServiceTarget` fields (e.g., `serviceName`, host, port). This would better validate the new `executeDelete` JSON payload and help catch regressions where the DELETE is sent without a body or with incorrect serialization.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +60 to +62
server.createContext("/api/v1/management/discovery", exchange -> {
String body = new String(exchange.getRequestBody().readAllBytes());
requests.add(new RequestRecord(
Copy link

Choose a reason for hiding this comment

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

suggestion (testing): Consider asserting on the serialized request body for register/deregister

Since the server is already capturing the request body, consider extending the tests to assert on requests.getFirst().body() as well, verifying key ServiceTarget fields (e.g., serviceName, host, port). This would better validate the new executeDelete JSON payload and help catch regressions where the DELETE is sent without a body or with incorrect serialization.

- Merge duplicate executePost/executeDelete into unified executeRequest in DiscoveryServiceHttpClient
- Add URL encoding for dynamic path segments and query params in ServicesHttpClient
- Add request body assertions in discovery client tests
@orpiske orpiske merged commit dacce4e into wanaku-ai:main Mar 19, 2026
5 checks passed
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.

Update SDK HTTP clients to match REST API cleanups from wanaku#636

1 participant