- Laravel Version: 9.52.4
- PHP Version: 8.2.3
- Database Driver & Version:
Description:
$this->getHttpClient()
->withUrlParameters([
'node' => $this->node->cluster,
'server' => $this->server->vmid
])
->delete('/api2/json/nodes/{node}/qemu/{server}', [
'destroy-unreferenced-disks' => true, 'purge' => true, 'skiplock' => true,
])
->json();
The Laravel HTTP Client doesn't appear to add the payload in the second argument to the delete
method as query parameters to the request. Though, I am not completely sure that this is the case from my superficial analysis (I can't seem to make sense of the Http Client's code nor am I getting enough information from the dd
method on the Http Client to properly determine the issue).
When I send the request to the API service (Proxmox Virtual Environment), I receive a HTTP error 501. Here's the contents of the dd
method on the Http Client. Information like the base_uri
and any confidential information was redacted and filled with placeholder data.
array:13 [ // vendor/laravel/framework/src/Illuminate/Http/Client/PendingRequest.php:1102
"connect_timeout" => 5
"http_errors" => false
"timeout" => 15
"verify" => false
"base_uri" => "https://redacted.com:8006/"
"laravel_data" => array:3 [
"destroy-unreferenced-disks" => true
"purge" => true
"skiplock" => true
]
"on_stats" => Closure($transferStats)^ {#5048
class: "Illuminate\Http\Client\PendingRequest"
this: Illuminate\Http\Client\PendingRequest {#5019 …}
}
"synchronous" => true
"handler" => GuzzleHttp\HandlerStack^ {#5033
-handler: Closure(RequestInterface $request, array $options): PromiseInterface^ {#5039
returnType: "GuzzleHttp\Promise\PromiseInterface"
class: "GuzzleHttp\Handler\Proxy"
use: {
$default: Closure(RequestInterface $request, array $options): PromiseInterface^ {#5026 …}
$streaming: GuzzleHttp\Handler\StreamHandler {#5036 …}
}
}
-stack: array:7 [
0 => array:2 [
0 => Closure(callable $handler): callable^ {#5040
returnType: "callable"
class: "GuzzleHttp\Middleware"
use: {
$bodySummarizer: null
}
}
1 => "http_errors"
]
1 => array:2 [
0 => Closure(callable $handler): RedirectMiddleware^ {#5041
returnType: "GuzzleHttp\RedirectMiddleware"
class: "GuzzleHttp\Middleware"
}
1 => "allow_redirects"
]
2 => array:2 [
0 => Closure(callable $handler): callable^ {#5042
returnType: "callable"
class: "GuzzleHttp\Middleware"
}
1 => "cookies"
]
3 => array:2 [
0 => Closure(callable $handler): PrepareBodyMiddleware^ {#5043
returnType: "GuzzleHttp\PrepareBodyMiddleware"
class: "GuzzleHttp\Middleware"
}
1 => "prepare_body"
]
4 => array:2 [
0 => Closure($handler)^ {#5045
class: "Illuminate\Http\Client\PendingRequest"
this: Illuminate\Http\Client\PendingRequest {#5019 …}
}
1 => ""
]
5 => array:2 [
0 => Closure($handler)^ {#5046
class: "Illuminate\Http\Client\PendingRequest"
this: Illuminate\Http\Client\PendingRequest {#5019 …}
}
1 => ""
]
6 => array:2 [
0 => Closure($handler)^ {#5047
class: "Illuminate\Http\Client\PendingRequest"
this: Illuminate\Http\Client\PendingRequest {#5019 …}
}
1 => ""
]
]
-cached: Closure($request, array $options)^ {#5060
class: "GuzzleHttp\Middleware"
use: {
$handler: GuzzleHttp\RedirectMiddleware {#5059 …}
$bodySummarizer: null
}
}
}
"cookies" => GuzzleHttp\Cookie\CookieJar^ {#5049
-cookies: []
-strictMode: false
}
"allow_redirects" => array:5 [
"max" => 5
"protocols" => array:2 [
0 => "http"
1 => "https"
]
"strict" => false
"referer" => false
"track_redirects" => false
]
"decode_content" => true
"idn_conversion" => false
]
Although MDN specifies that a DELETE
request may have a body, it seems like many (from my limited search) prefer to use query parameters over using a body.
A workaround I am using is:
$this->getHttpClient(options: [
'query' => [
'destroy-unreferenced-disks' => true,
'purge' => true,
]
])
->withUrlParameters([
'node' => $this->node->cluster,
'server' => $this->server->vmid
])
->delete('/api2/json/nodes/{node}/qemu/{server}')
->json();
I don't feel like this is an ideal workaround and would love to use the expressive syntax of Laravel.
Here are links to the code containing the mentioned snippets.
Steps To Reproduce:
A reproduction is possible by running
$httpClient = Http::withOptions([
'verify' => false,
'base_uri' => "https://YOUR_DOMAIN/",
'timeout' => 15,
'connect_timeout' => 5,
'headers' => [
'Authorization' => 'DUMMY AUTHORiZATION HEADER',
'Accept' => 'application/json',
'Content-Type' => 'application/json',
'User-Agent' => null,
],
]);
$httpClient->delete('/route', [
'query-parameter' => 'test'
]);
If you want a complete reproduction, please install my app using my documentation. It uses Docker containers and the installation process is mostly copy-paste with few interventions to add your desired configuration.
Since my app interacts with an external service, you need to also create a VM, dedicated server, or bare metal that's running (Proxmox Virtual Environment). If you have my app APP_ENV
to production
, make sure you generate trusted TLS certificates on the Proxmox Virtual Environment server.
You can then add the Proxmox node to my app using these documentation.