Add HTTP QUERY Method Support (RFC 10008) - #3760
Conversation
* Fix: Goroutine leaks in SQL/Redis datasources by adding graceful shutdown * Fix: compilation error in db_test.go due to struct changes * Fix: Remove duplicate context import in db_test.go * fixed tests and linters * fix: handle silent failures in config details * fix: add nil-check for logger in getIntConfig and refine test * refactor: inline getIntConfig and remove helper as requested by reviewer * style: fix wsl lint errors by adding missing whitespace * refactor: update logging & remove redundant assignments as per review --------- Co-authored-by: coolwednesday <divi229moc@gmail.com> Co-authored-by: Divya Darshana <98943137+coolwednesday@users.noreply.github.com> Co-authored-by: Umang Mundhra <mundhraumang.02@gmail.com>
* update release version to v1.50.0 * V1.50.1 (gofr-dev#2709) * update release version to v1.50.2 * update release version to v1.51.0 * update release version to v1.52.0 * Release v1.53.0 (gofr-dev#2828) * build(deps): bump gofr.dev in /pkg/gofr/datasource/file/gcs Bumps [gofr.dev](https://github.com/gofr-dev/gofr) from 1.51.0 to 1.52.0. - [Release notes](https://github.com/gofr-dev/gofr/releases) - [Commits](gofr-dev/gofr@v1.51.0...v1.52.0) --- updated-dependencies: - dependency-name: gofr.dev dependency-version: 1.52.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump google.golang.org/api in /pkg/gofr/datasource/file/gcs Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.258.0 to 0.259.0. - [Release notes](https://github.com/googleapis/google-api-go-client/releases) - [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md) - [Commits](googleapis/google-api-go-client@v0.258.0...v0.259.0) --- updated-dependencies: - dependency-name: google.golang.org/api dependency-version: 0.259.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * Metrics in HttpService Options (gofr-dev#2812) * fixed doc formatting issue in http Communication page in documentation (gofr-dev#2827) * build(deps): bump gofr.dev in /pkg/gofr/datasource/pubsub/sqs Bumps [gofr.dev](https://github.com/gofr-dev/gofr) from 1.52.0 to 1.53.0. - [Release notes](https://github.com/gofr-dev/gofr/releases) - [Commits](gofr-dev/gofr@v1.52.0...v1.53.0) --- updated-dependencies: - dependency-name: gofr.dev dependency-version: 1.53.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump gofr.dev in /pkg/gofr/datasource/file/sftp Bumps [gofr.dev](https://github.com/gofr-dev/gofr) from 1.52.0 to 1.53.0. - [Release notes](https://github.com/gofr-dev/gofr/releases) - [Commits](gofr-dev/gofr@v1.52.0...v1.53.0) --- updated-dependencies: - dependency-name: gofr.dev dependency-version: 1.53.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump gofr.dev in /pkg/gofr/datasource/pubsub/eventhub Bumps [gofr.dev](https://github.com/gofr-dev/gofr) from 1.52.0 to 1.53.0. - [Release notes](https://github.com/gofr-dev/gofr/releases) - [Commits](gofr-dev/gofr@v1.52.0...v1.53.0) --- updated-dependencies: - dependency-name: gofr.dev dependency-version: 1.53.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump github.com/godror/godror Bumps [github.com/godror/godror](https://github.com/godror/godror) from 0.49.6 to 0.50.0. - [Changelog](https://github.com/godror/godror/blob/main/CHANGELOG.md) - [Commits](godror/godror@v0.49.6...v0.50.0) --- updated-dependencies: - dependency-name: github.com/godror/godror dependency-version: 0.50.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump gofr.dev in /pkg/gofr/datasource/file/s3 Bumps [gofr.dev](https://github.com/gofr-dev/gofr) from 1.52.0 to 1.53.0. - [Release notes](https://github.com/gofr-dev/gofr/releases) - [Commits](gofr-dev/gofr@v1.52.0...v1.53.0) --- updated-dependencies: - dependency-name: gofr.dev dependency-version: 1.53.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump golang.org/x/term from 0.38.0 to 0.39.0 Bumps [golang.org/x/term](https://github.com/golang/term) from 0.38.0 to 0.39.0. - [Commits](golang/term@v0.38.0...v0.39.0) --- updated-dependencies: - dependency-name: golang.org/x/term dependency-version: 0.39.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump gofr.dev in /pkg/gofr/datasource/dbresolver Bumps [gofr.dev](https://github.com/gofr-dev/gofr) from 1.52.0 to 1.53.0. - [Release notes](https://github.com/gofr-dev/gofr/releases) - [Commits](gofr-dev/gofr@v1.52.0...v1.53.0) --- updated-dependencies: - dependency-name: gofr.dev dependency-version: 1.53.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump gofr.dev in /examples/using-add-filestore Bumps [gofr.dev](https://github.com/gofr-dev/gofr) from 1.52.0 to 1.53.0. - [Release notes](https://github.com/gofr-dev/gofr/releases) - [Commits](gofr-dev/gofr@v1.52.0...v1.53.0) --- updated-dependencies: - dependency-name: gofr.dev dependency-version: 1.53.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump modernc.org/sqlite from 1.42.2 to 1.43.0 Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.42.2 to 1.43.0. - [Commits](https://gitlab.com/cznic/sqlite/compare/v1.42.2...v1.43.0) --- updated-dependencies: - dependency-name: modernc.org/sqlite dependency-version: 1.43.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump crate-ci/typos in the actions group Bumps the actions group with 1 update: [crate-ci/typos](https://github.com/crate-ci/typos). Updates `crate-ci/typos` from 1.41.0 to 1.42.0 - [Release notes](https://github.com/crate-ci/typos/releases) - [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md) - [Commits](crate-ci/typos@v1.41.0...v1.42.0) --- updated-dependencies: - dependency-name: crate-ci/typos dependency-version: 1.42.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump gofr.dev in /pkg/gofr/datasource/file/gcs Bumps [gofr.dev](https://github.com/gofr-dev/gofr) from 1.52.0 to 1.53.0. - [Release notes](https://github.com/gofr-dev/gofr/releases) - [Commits](gofr-dev/gofr@v1.52.0...v1.53.0) --- updated-dependencies: - dependency-name: gofr.dev dependency-version: 1.53.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump golang.org/x/text from 0.32.0 to 0.33.0 Bumps [golang.org/x/text](https://github.com/golang/text) from 0.32.0 to 0.33.0. - [Release notes](https://github.com/golang/text/releases) - [Commits](golang/text@v0.32.0...v0.33.0) --- updated-dependencies: - dependency-name: golang.org/x/text dependency-version: 0.33.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump gofr.dev in /pkg/gofr/datasource/file/azure Bumps [gofr.dev](https://github.com/gofr-dev/gofr) from 1.52.0 to 1.53.0. - [Release notes](https://github.com/gofr-dev/gofr/releases) - [Commits](gofr-dev/gofr@v1.52.0...v1.53.0) --- updated-dependencies: - dependency-name: gofr.dev dependency-version: 1.53.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump gofr.dev in /pkg/gofr/datasource/oracle Bumps [gofr.dev](https://github.com/gofr-dev/gofr) from 1.52.0 to 1.53.0. - [Release notes](https://github.com/gofr-dev/gofr/releases) - [Commits](gofr-dev/gofr@v1.52.0...v1.53.0) --- updated-dependencies: - dependency-name: gofr.dev dependency-version: 1.53.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump gofr.dev in /pkg/gofr/datasource/file/ftp Bumps [gofr.dev](https://github.com/gofr-dev/gofr) from 1.52.0 to 1.53.0. - [Release notes](https://github.com/gofr-dev/gofr/releases) - [Commits](gofr-dev/gofr@v1.52.0...v1.53.0) --- updated-dependencies: - dependency-name: gofr.dev dependency-version: 1.53.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * Fix/circuit breaker (gofr-dev#2829) * feat(http): implement server-side rate limiter middleware (gofr-dev#2563) * added version * version * version added * fixed linters * updated version * version-change * feat(sqs): add span links for pub/sub tracing Add distributed trace context propagation for AWS SQS: - Inject W3C traceparent into SQS message attributes on publish - Extract trace context and create span links on subscribe - Producer/consumer spans linked via OTel span links pattern This follows the OpenTelemetry messaging semantic conventions where consumer spans link to producer spans rather than using parent-child. Fixes gofr-dev#3015 * update with development and remove unwanted changes --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Umang01-hash <mundhraumang.02@gmail.com> Co-authored-by: coolwednesday <divi229moc@gmail.com> Co-authored-by: Divya Darshana <98943137+coolwednesday@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: DuskWarden <pawar96sameer@gmail.com> Co-authored-by: BITTU KUMAR <152794122+CSEBittuKr@users.noreply.github.com> Co-authored-by: Bhavishya Sharma <bhavishaya32@gmail.com> Co-authored-by: gizmo-rt <pawanrajmurarka@gmail.com> Co-authored-by: rohansood10 <rohansood10@users.noreply.github.com>
…p/httptrace/otelhttptrace (gofr-dev#3081)
…p/httptrace/otelhttptrace (gofr-dev#3047)
…6-07-02 chore(deps): consolidate minor dependency updates (2026-07-02)
…lone builds ahead of module tagging (gofr-dev#3655) * chore(datasource): bump gofr.dev to v1.57.0 across submodules Bumps gofr.dev v1.56.6 -> v1.57.0 in the 10 datasource submodules that import core (dbresolver, file/azure, file/ftp, file/gcs, file/s3, file/sftp, oracle, pubsub/eventhub, pubsub/nats, pubsub/sqs) plus the using-cloudsql and using-add-filestore examples, ahead of tagging the datasource module releases. go.mod/go.sum only; standalone (GOWORK=off) builds verified. Co-Authored-By: claude-flow <ruv@ruv.net> * test(eventhub): add mock expectations for consumer-group debug logs Connect() emits Debugf("Using default consumer group: %s") and Debug("Event Hub client initialization complete"), but the Connect()-calling tests never expected them, leaving them red under gomock. Test-only. Co-Authored-By: claude-flow <ruv@ruv.net> --------- Co-authored-by: claude-flow <ruv@ruv.net>
…ofr-dev#3752) Updates included: - github.com/aws/aws-sdk-go-v2/config: 1.32.28 -> 1.32.30 - github.com/aws/aws-sdk-go-v2/service/s3: 1.105.1 -> 1.105.2 - github.com/aws/aws-sdk-go-v2/service/sqs: 1.45.0 -> 1.45.1 - github.com/dgraph-io/badger/v4: 4.9.3 -> 4.9.4 - github.com/prometheus/client_golang: 1.23.2 -> 1.24.0 - github.com/surrealdb/surrealdb.go: 1.5.1 -> 1.6.0 - cloud.google.com/go/pubsub: 1.50.2 -> 1.51.0 - google.golang.org/grpc: 1.82.0 -> 1.82.1 - golang.org/x/crypto: 0.53.0 -> 0.54.0 - modernc.org/sqlite: 1.53.0 -> 1.54.0 Closes: gofr-dev#3732, gofr-dev#3733, gofr-dev#3734, gofr-dev#3735, gofr-dev#3736, gofr-dev#3737, gofr-dev#3738, gofr-dev#3739, gofr-dev#3740, gofr-dev#3741, gofr-dev#3742, gofr-dev#3743, gofr-dev#3744, gofr-dev#3745, gofr-dev#3746, gofr-dev#3747, gofr-dev#3748, gofr-dev#3749, gofr-dev#3750, gofr-dev#3751 Co-authored-by: claude-flow <ruv@ruv.net> Co-authored-by: Aryan Mehrotra <aryanmehrotra2000@gmail.com>
Add first-class support for the HTTP QUERY method both inbound and outbound. Inbound: app.QUERY registers a route for the QUERY method; the body is read via ctx.Bind like a POST. Outbound: add Query/QueryWithHeaders to the HTTP service client and thread them through every decorator (retry, auth, custom-header, file-token, rate-limiter, circuit-breaker). QUERY is safe and idempotent, so it is wrapped by the circuit-breaker and retry options like GET. The circuit-breaker doRequest switch gains a QUERY case and a default case that returns ErrUnsupportedMethod instead of silently returning a nil response. Closes gofr-dev#3756
Add hermetic integration tests exercising an outbound QUERY through a real circuit breaker against an httptest downstream: trip on repeated 503s (ErrCircuitOpen, no downstream hit) and request-driven recovery once the health probe reports UP. The breaker is constructed directly to avoid the background health-check goroutine, keeping the tests deterministic.
QUERY (RFC 10008) is safe and idempotent, so QUERY routes now join read-only handlers on the MCP tool surface. The tool schema advertises a required "body" object argument carrying the query payload; on invocation the body is sent as the QUERY request body (Content-Type application/json) while path params and any extra args map to the path and query string. Write handlers remain unexposed.
The test schedules a "* * * * *" job to validate AddJob but only expected the metric-registration calls. When the scheduler tick fired the job, job.run emitted runtime metrics (RecordHistogram/IncrementCounter) from a background goroutine with no matching expectation, so gomock called t.Fatalf after the test had completed — panic: "Fail in goroutine after TestCronTab_AddJob has completed". Allow the runtime metric emissions with AnyTimes so a late tick is tolerated.
…cations perf(logging,http): cut per-request allocations on the hot path
Umang01-hash
left a comment
There was a problem hiding this comment.
Nice work — clean and consistent. Ran it locally: QUERY /search returns 200 with the body bound and echoed, and metrics (method="QUERY"), logs (trace/span IDs) and traces all show up correctly. QUERY mirrors POST in every decorator, the circuit-breaker default case is a good catch, and no breaking change (the HTTP interface is sealed by its unexported method, so external code can't implement it anyway).
One thing to fix before merge: docs/advanced-guide/mcp/page.md still says only GET/HEAD/OPTIONS are exposed as agent tools and "an agent cannot mutate state." Since QUERY routes are now exposed too, please update that page to match — it's the one place the docs contradict the new behavior.
Minor (optional): the retry and rate_limiter QUERY tests only assert status 200, so they'd pass even if Query delegated to the wrong verb — the other decorators pin method=="QUERY", so it's covered overall, just noting for parity.
Approving — only the MCP docs update is worth doing before merge.
…fer Stop The merge resolution had kept only the name-specific runtime-metric expectations for TestCronTab_AddJob; restore development's generic-matcher expectations and defer c.Stop() alongside them so both branches' fixes are preserved.
…eat/http-query-method # Conflicts: # pkg/gofr/cron_test.go
Resolves conflicts from 189 files across: go.mod/go.sum (upstream deps), CI/docs/examples (upstream-only, taken as-is), and the 32 feature-touching files where both branches changed the same code. Key merges: - service/*.go: kept QUERY/QueryWithHeaders on all decorators + upstream named-constant refactors (apikey_auth, basic_auth, oauth) - http/router.go: kept QUERY route registration + upstream trie router (gofr-dev#3759) - gofr.go: kept App.QUERY() + upstream cron graceful-shutdown fix - rest.go / tools.go / mcp.go: kept QUERY MCP exposure - http_server.go: kept data-race fix + upstream logRouterChoice() - examples/http-server: kept SearchHandler / integration test + upstream WaitForHTTPServer readiness fix - circuit_breaker.go: kept ErrUnsupportedMethod default case + QUERY case
The upstream/development merge partially resolved router_test.go: it kept the `require` import but dropped the 7 static-file test functions that use it (Test_StaticFileServing_EndpointRoot, ...NonDirectoryDirName, etc.). This left `require` imported and unused → lint failure and `go vet` build failure on the whole `pkg/gofr/http` package on CI (gofr-dev#3760 pipeline). Our branch never modified this file, so upstream's version is the correct one. Verified with `go vet` clean and `go test -count=1 ./pkg/gofr/...` all packages green.
Objective / Issue
Closes #3756. Add first-class support for the HTTP QUERY method (RFC 10008) to gofr — both inbound route registration and the outbound HTTP service client.
QUERY is a safe, idempotent, cacheable method that carries the query in the request body. It bridges the gap between GET (no body, URL-length limits, query leaks into logs) and POST (has a body but is neither safe nor idempotent). It is well-suited to service-to-service search/query APIs.
What we found
apphad no way to register a QUERY route (GET/POST/PUT/PATCH/DELETEonly).httpClientinterface and every decorator (retry, auth, custom-header, file-token, rate-limiter, circuit-breaker) had no QUERY method. The circuit-breakerdoRequestswitch also had nodefaultcase — an unrecognized method silently returned a nil response.net/httphas nohttp.MethodQueryconstant yet, but it accepts arbitrary method strings on both server and client, so there is no stdlib blocker.How we fixed it
Inbound
App.QUERY(pattern, handler)registers the route (method string"QUERY"). The body is read via the existingctx.Bind(Content-Type driven), identical to POST.Outbound
Query/QueryWithHeaders(ctx, path, queryParams, body[, headers])to thehttpClientinterface andhttpService(delegates to the already method-agnosticcreateAndSendRequest).retryProvider,authProvider,customHeader,fileTokenDecorator,rateLimiter.QUERYcase todoRequestplus theQuery/QueryWithHeaderswrappers. Since QUERY is safe + idempotent, it is wrapped by the circuit-breaker and retry options like GET.defaultcase todoRequestreturning a newErrUnsupportedMethodinstead of silently returning nil.Query/QueryWithHeadersmethods to the generatedMockHTTP.Design decisions / alternatives not taken
http.MethodQueryconstant: not in Go's stdlib yet, so a package-levelmethodQuery = "QUERY"constant is used.Docs / Test / Playground
docs/advanced-guide/http-communication/page.mdwithQuery/QueryWithHeadersand a note on QUERY semantics.examples/http-servergains aSearchHandleron aQUERY /searchroute plus an integration test.Test plan
go build ./...go test ./pkg/gofr/... ./pkg/gofr/service/...passgofmtclean; lint clean for changed codeQUERY /search, sends a QUERY with a JSON body, asserts the handler binds and echoes it.httpService.Query/QueryWithHeaders(method, path, query params, body, Content-Type default, empty body).default-case returnsErrUnsupportedMethod.Risk & Rollback
Low risk — purely additive. New interface methods are implemented across all decorators and the mock; existing verbs are unchanged. The only behavioral change to existing code is the circuit-breaker
defaultcase, which converts a previously silent nil-response path into an explicit error. Rollback is a straight revert.