From d2320c2e2f721fb0a030e6183986b9267dcc4484 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Nov 2026 17:44:27 +0000 Subject: [PATCH 1/2] Initial plan From c952f51972207438c9497fd08a1d02d01fdae557 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Nov 2026 17:47:05 +0000 Subject: [PATCH 2/2] Add HTTP QUERY request helper Co-authored-by: asika32764 <1639206+asika32764@users.noreply.github.com> --- packages/http/src/HttpClient.php | 24 +++++++++++++++++-- packages/http/test/HttpClientTest.php | 34 +++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/packages/http/src/HttpClient.php b/packages/http/src/HttpClient.php index 99986e4db..a78b1aa16 100644 --- a/packages/http/src/HttpClient.php +++ b/packages/http/src/HttpClient.php @@ -43,6 +43,7 @@ * @method PromiseInterface|mixed getAsync(Stringable|string $url, array $options = []) * @method PromiseInterface|mixed postAsync(Stringable|string $url, mixed $body, array $options = []) * @method PromiseInterface|mixed putAsync(Stringable|string $url, mixed $body, array $options = []) + * @method PromiseInterface|mixed queryAsync(Stringable|string $url, mixed $body = null, array $options = []) * @method PromiseInterface|mixed deleteAsync(Stringable|string $url, mixed $body, array $options = []) * @method PromiseInterface|mixed patchAsync(Stringable|string $url, mixed $body, array $options = []) * @method PromiseInterface|mixed traceAsync(Stringable|string $url, array $options = []) @@ -53,6 +54,8 @@ * HttpClientOptions()) * @method HttpClientResponse mustPut(Stringable|string $url, mixed $body = null, HttpClientOptions $options = new * HttpClientOptions()) + * @method HttpClientResponse mustQuery(Stringable|string $url, mixed $body = null, HttpClientOptions $options = new + * HttpClientOptions()) * @method HttpClientResponse mustDelete(Stringable|string $url, mixed $body = null, HttpClientOptions $options = new * HttpClientOptions()) * @method HttpClientResponse mustPatch(Stringable|string $url, mixed $body = null, HttpClientOptions $options = new @@ -320,6 +323,23 @@ public function patch( return $this->request('PATCH', $url, $body, $options); } + /** + * Method to send the QUERY command to the server. + * + * @param Stringable|string $url Path to the resource. + * @param mixed $body The query content. + * @param array|HttpClientOptions $options The request options. + * + * @return HttpClientResponse + */ + public function query( + Stringable|string $url, + mixed $body = null, + array|HttpClientOptions $options = new HttpClientOptions(), + ): HttpClientResponse { + return $this->request('QUERY', $url, $body, $options); + } + public function connect( Stringable|string $url, array|HttpClientOptions $options = new HttpClientOptions(), @@ -657,9 +677,9 @@ public function __call(string $name, array $args) $ref = new ReflectionMethod($this, $method); if (count($ref->getParameters()) >= 3) { - $promise = $this->requestAsync($method, ...$args); + $promise = $this->requestAsync(strtoupper($method), ...$args); } else { - $promise = $this->requestAsync($method, $args[0] ?? '', null, $args[1] ?? []); + $promise = $this->requestAsync(strtoupper($method), $args[0] ?? '', null, $args[1] ?? []); } return $promise; diff --git a/packages/http/test/HttpClientTest.php b/packages/http/test/HttpClientTest.php index 2733755d4..2f00f52bb 100644 --- a/packages/http/test/HttpClientTest.php +++ b/packages/http/test/HttpClientTest.php @@ -247,6 +247,40 @@ public function postSendsFormDataBodyWithPostMethod(): void self::assertEquals(http_build_query($data), $this->transport->request->getBody()->__toString()); } + #[Test] + public function querySendsQueryMethodWithBodyAndOptions(): void + { + $url = 'http://example.com/?foo=bar'; + $body = ['filter' => ['status' => 'active']]; + $headers = ['X-Foo' => 'Bar']; + + $this->instance->query($url, $body, compact('headers')); + + self::assertSame('QUERY', $this->transport->request->getMethod()); + self::assertSame($url, $this->transport->request->getRequestTarget()); + self::assertSame('{"filter":{"status":"active"}}', (string) $this->transport->request->getBody()); + self::assertSame('Bar', $this->transport->request->getHeaderLine('X-Foo')); + } + + #[Test] + public function queryAsyncUsesUppercaseQueryMethod(): void + { + $client = new class ([], new MockTransport()) extends HttpClient { + public ?RequestInterface $request = null; + + public function sendAsyncRequest(RequestInterface $request): mixed + { + $this->request = $request; + + return null; + } + }; + + $client->queryAsync('http://example.com', ['filter' => 'active']); + + self::assertSame('QUERY', $client->request?->getMethod()); + } + #[Test] public function putSendsFormDataBodyWithPutMethod(): void {