Skip to content

feat[Go]: implement GET /dify/retrieval/health (issue #15240)#15571

Closed
dripsmvcp wants to merge 2 commits into
infiniflow:mainfrom
dripsmvcp:feat/go-api-dify-health
Closed

feat[Go]: implement GET /dify/retrieval/health (issue #15240)#15571
dripsmvcp wants to merge 2 commits into
infiniflow:mainfrom
dripsmvcp:feat/go-api-dify-health

Conversation

@dripsmvcp

Copy link
Copy Markdown
Contributor

Summary

Port the Dify external-knowledge-base reachability probe to the Go API server. Listed in the Go-API port checklist of #15240.

Dify calls this endpoint to verify that the RAGFlow external-knowledge connector is reachable before the user configures any credentials, so it returns a constant success envelope and stays on the public route group.

What

  • internal/handler/dify.go — new DifyHandler.RetrievalHealth returning the same {"code":0, "message":"success", "data":true} envelope the Python endpoint emits.
  • internal/router/router.go — wire apiNoAuth.GET("/dify/retrieval/health", ...). Public by design, matching the undecorated Python route.
  • cmd/server_main.go — instantiate and inject DifyHandler.
  • internal/handler/dify_test.go — unit tests for the envelope shape and confirmation that the probe succeeds without an authenticated user.

Python source

api/apps/restful_apis/dify_retrieval_api.py:

@manager.route('/dify/retrieval/health', methods=['GET'])
async def retrieval_health_check():
    """Health check endpoint for Dify external knowledge base connectivity verification."""
    return get_json_result(data=True)

Test plan

  • go vet ./internal/handler ./internal/router clean
  • Unit tests cover the response envelope and the no-auth contract
  • CI runs go test ./internal/handler with cgo binding linked

Related

@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Jun 3, 2026
@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds an unauthenticated Dify retrieval health endpoint: implements DifyHandler.RetrievalHealth with tests, registers GET /api/v1/dify/retrieval/health in the router, and initializes the handler during server startup.

Changes

Dify Retrieval Health Check

Layer / File(s) Summary
Dify health endpoint handler
internal/handler/dify.go, internal/handler/dify_test.go
DifyHandler implements RetrievalHealth to handle GET /api/v1/dify/retrieval/health, returning HTTP 200 with JSON {code, "message":"success", "data": true}. Two unit tests validate the response structure and that the endpoint does not read user/auth context.
Router struct and handler registration
internal/router/router.go
Router gains a difyHandler field; NewRouter accepts and assigns it; Setup registers unauthenticated GET /api/v1/dify/retrieval/health routed to r.difyHandler.RetrievalHealth.
Server main handler initialization
cmd/server_main.go
startServer instantiates DifyHandler via handler.NewDifyHandler() and passes it into router.NewRouter(...), integrating the handler into startup.

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly Related PRs

  • infiniflow/ragflow#15311: Addresses the same Dify retrieval health-check endpoint routing change to GET /dify/retrieval/health.

Suggested Labels

💞 feature, 🐖api, size:M

Suggested Reviewers

  • Hz-186
  • yingfeng

Poem

🐰 I hopped a tiny health-check near,
Dify's heartbeat now rings clear,
Route is set and tests pursue,
Server starts and replies true—
A rabbit nods, munches a carrot.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: implementing a GET endpoint for Dify retrieval health checking, with the issue reference (#15240) providing full context.
Description check ✅ Passed The description provides comprehensive context including the problem being solved, a detailed 'What' section covering all changed files, Python source reference, test plan, and related issue. However, it does not follow the template structure with 'Type of change' checkboxes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
internal/handler/dify.go (1)

47-53: 💤 Low value

Optional: reuse the shared jsonResponse helper.

internal/handler/kb.go already exposes jsonResponse(c, code, data, message) for the standard envelope. Adopting it keeps the response shape consistent across handlers. Note the hardcoded lowercase "success" is intentional and must be preserved—common.CodeSuccess.Message() returns "Success" (capitalized), so pass the literal explicitly rather than deriving it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/handler/dify.go` around lines 47 - 53, Replace the direct c.JSON
response in RetrievalHealth with the shared jsonResponse helper: call
jsonResponse(c, common.CodeSuccess, true, "success") so the envelope is
consistent with other handlers; keep the literal lowercase "success" string (do
not use common.CodeSuccess.Message()). Ensure you update the RetrievalHealth
method to use jsonResponse rather than constructing gin.H directly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/handler/dify_test.go`:
- Around line 59-79: TestDifyRetrievalHealthDoesNotRequireAuth currently
attaches NewDifyHandler().RetrievalHealth to a bare gin.New() so it doesn't
exercise the AuthMiddleware; change the test to create the application's router
via Router.Setup (so AuthMiddleware is registered) and then register the dify
retrieval health route through the public/no-auth group used by your
Router.Setup to confirm the route bypasses auth, and also handle the
json.Unmarshal error instead of discarding it (fail the test if unmarshalling
the response body returns an error) so a malformed body doesn't mask failures.

In `@internal/handler/dify.go`:
- Around line 36-46: Update the Swagger/method comment in the RetrievalHealth
handler so the documented path matches the actual mounted route; change the
method comment and the `@Router` annotation that currently reference
"/v1/dify/retrieval/health" to the full mounted path
"/api/v1/dify/retrieval/health" (modify the comment block around the
RetrievalHealth function and its `@Router` tag) to ensure generated Swagger
reflects the real endpoint.

---

Nitpick comments:
In `@internal/handler/dify.go`:
- Around line 47-53: Replace the direct c.JSON response in RetrievalHealth with
the shared jsonResponse helper: call jsonResponse(c, common.CodeSuccess, true,
"success") so the envelope is consistent with other handlers; keep the literal
lowercase "success" string (do not use common.CodeSuccess.Message()). Ensure you
update the RetrievalHealth method to use jsonResponse rather than constructing
gin.H directly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f5af1182-54bb-4ca9-81fd-f1c59bb7360e

📥 Commits

Reviewing files that changed from the base of the PR and between 473d06d and 5c76c8e.

📒 Files selected for processing (4)
  • cmd/server_main.go
  • internal/handler/dify.go
  • internal/handler/dify_test.go
  • internal/router/router.go

Comment thread internal/handler/dify_test.go Outdated
Comment on lines +59 to +79
func TestDifyRetrievalHealthDoesNotRequireAuth(t *testing.T) {
// Public probe: must succeed even with no user attached to the context.
gin.SetMode(gin.TestMode)

r := gin.New()
r.GET("/api/v1/dify/retrieval/health", NewDifyHandler().RetrievalHealth)

resp := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/api/v1/dify/retrieval/health", nil)
r.ServeHTTP(resp, req)

if resp.Code != http.StatusOK {
t.Fatalf("status=%d body=%s", resp.Code, resp.Body.String())
}

var body map[string]interface{}
_ = json.Unmarshal(resp.Body.Bytes(), &body)
if code, _ := body["code"].(float64); int(code) != int(common.CodeSuccess) {
t.Errorf("unauthenticated probe should succeed, got code=%v", body["code"])
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

TestDifyRetrievalHealthDoesNotRequireAuth doesn't exercise the no-auth contract.

This test mounts the handler on a bare gin.New() router with no auth middleware, so it's functionally identical to TestDifyRetrievalHealthReturnsTrueEnvelope and proves nothing about authentication. To actually validate that the probe is public, the route should be reached through a router that has AuthMiddleware() applied (i.e., via Router.Setup) confirming the no-auth group bypasses it—otherwise this is a duplicate.

Also, the json.Unmarshal error is silently discarded at Line 75; on a malformed body the assertion would read a zeroed code and could mask a real failure.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/handler/dify_test.go` around lines 59 - 79,
TestDifyRetrievalHealthDoesNotRequireAuth currently attaches
NewDifyHandler().RetrievalHealth to a bare gin.New() so it doesn't exercise the
AuthMiddleware; change the test to create the application's router via
Router.Setup (so AuthMiddleware is registered) and then register the dify
retrieval health route through the public/no-auth group used by your
Router.Setup to confirm the route bypasses auth, and also handle the
json.Unmarshal error instead of discarding it (fail the test if unmarshalling
the response body returns an error) so a malformed body doesn't mask failures.

Comment thread internal/handler/dify.go Outdated
@dripsmvcp dripsmvcp force-pushed the feat/go-api-dify-health branch from 5c76c8e to 06aceaf Compare June 4, 2026 00:56
@dripsmvcp

Copy link
Copy Markdown
Contributor Author

@dosu

@dosubot

dosubot Bot commented Jun 4, 2026

Copy link
Copy Markdown

This PR looks well-scoped and correctly aligned with the Python implementation. A few observations:

Looks good:

  • The Python endpoint is intentionally minimal — no auth, no service calls, just a constant {"code": 0, "message": "success", "data": true} envelope [1]. Porting this to Go is straightforward.
  • Placing the route in the public (no-auth) group is correct — it matches the Python route which has no @apikey_required decorator.
  • This is the first Dify-related code in the Go server [2], so it establishes the pattern for future Dify endpoints.

Things to verify:

  1. DI pattern — Make sure DifyHandler is instantiated and injected in startServer() following the same pattern as other handlers (e.g., DatasetsHandler, ChatsHandler) in cmd/server_main.go [3].
  2. Route path — The Python route is /dify/retrieval/health. In the Go router, public routes currently live under different path prefixes (/api/v1/system/*, /api/v1/auth/*, etc.) [4]. Confirm the Go route matches the exact path Dify clients expect (i.e., no /api/v1 prefix wrapping it).
  3. Response format — The Go server likely has a shared response helper (similar to Python's get_json_result). Make sure the handler uses that rather than hand-rolling the JSON envelope, so the code/message/data shape stays consistent across all endpoints.
  4. [Feature] Implement API of RAGFlow server in Go #15240 compliance — The epic requires following patterns from PR Go: implement provider: CoHere and FishAudio #14790 and passing go vet [5]. Your test plan already covers go vet, which is good.

Overall this is a clean, minimal addition. The main risk is getting the route path exactly right so Dify's connector probe hits it without a prefix mismatch.

To reply, just mention @dosu.


Docs are dead. Just use Dosu.

Leave Feedback Ask Dosu about ragflow Share Dosu with your team

dripsmvcp added a commit to dripsmvcp/ragflow that referenced this pull request Jun 4, 2026
@dripsmvcp

Copy link
Copy Markdown
Contributor Author

@Hz-186 Would you check this PR too?

@Haruko386 Haruko386 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@dripsmvcp LGTM

@dosubot dosubot Bot added the lgtm This PR has been approved by a maintainer label Jun 4, 2026
@Haruko386 Haruko386 added the ci Continue Integration label Jun 4, 2026
@Haruko386 Haruko386 marked this pull request as draft June 4, 2026 09:14
@Haruko386 Haruko386 marked this pull request as ready for review June 4, 2026 09:14
@codecov

codecov Bot commented Jun 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.16%. Comparing base (794c1f4) to head (775194c).
⚠️ Report is 30 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main   #15571   +/-   ##
=======================================
  Coverage   93.16%   93.16%           
=======================================
  Files          10       10           
  Lines         717      717           
  Branches      118      118           
=======================================
  Hits          668      668           
  Misses         29       29           
  Partials       20       20           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

dripsmvcp added a commit to dripsmvcp/ragflow that referenced this pull request Jun 4, 2026
@dripsmvcp dripsmvcp force-pushed the feat/go-api-dify-health branch from ed1908e to 5dcff85 Compare June 4, 2026 10:24
dripsmvcp added a commit to dripsmvcp/ragflow that referenced this pull request Jun 4, 2026
@dripsmvcp dripsmvcp force-pushed the feat/go-api-dify-health branch from 5dcff85 to bf8f260 Compare June 4, 2026 11:55
@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. and removed size:M This PR changes 30-99 lines, ignoring generated files. labels Jun 4, 2026
@dripsmvcp dripsmvcp force-pushed the feat/go-api-dify-health branch from bf8f260 to 775194c Compare June 5, 2026 02:21
@dosubot dosubot Bot added size:M This PR changes 30-99 lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels Jun 5, 2026
@dripsmvcp

Copy link
Copy Markdown
Contributor Author

@Haruko386 Would you double check this review?

@JinHai-CN

Copy link
Copy Markdown
Contributor

@dripsmvcp Would you please fix the conflicts?

@dripsmvcp

Copy link
Copy Markdown
Contributor Author

Will do it @JinHai-CN

@dripsmvcp

Copy link
Copy Markdown
Contributor Author

Closing as superseded by #15704 ("Dify-compatible retrieval API endpoint"), which merged into main and already implements this exact endpoint:

main: apiNoAuth.GET("/dify/retrieval/health", r.difyRetrievalHandler.HealthCheck)

This PR's difyHandler.RetrievalHealth registers the same GET /api/v1/dify/retrieval/health route, so it can't be rebased onto current main without registering the route twice (gin panics on a duplicate path). Since #15704 is a superset (it also adds POST/GET /dify/retrieval), there's nothing here to salvage. Closing to avoid the duplicate; happy to reopen if needed.

@dripsmvcp dripsmvcp closed this Jun 8, 2026
@dripsmvcp dripsmvcp reopened this Jun 8, 2026
@dripsmvcp dripsmvcp closed this Jun 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci Continue Integration lgtm This PR has been approved by a maintainer size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants