laravel / laravel/cloud-cli

database-restore:create posts to the plural /restores path; the API endpoint is singular /restore

Open
#207 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
PHP
Stars
47
Forks
11
Avg merge
1d 12h
Merged PRs (30d)
20

Description

Description

POST /api/databases/clusters/{cluster}/restores returns HTTP 302 redirecting to the dashboard instead of a JSON response, so database-restore:create cannot create a restore even once the client-side problems are out of the way.

This is a different failure from #183. That one was the Form.php fatal, fixed by #187 and shipped. With that fix in place the command now reaches the API, and the API redirects it:

{"error":true,"message":"Laravel Cloud sent back a response we could not read: HTTP 200 from POST
https://cloud.laravel.com/api/databases/clusters/db-…/restores.
The body started with: <!DOCTYPE html> <html lang=\"en\"> <head> …"}
The redirect is specific to this one route

Same token, same headers, same cluster, in the same session:

Request Result
GET /api/databases/clusters/{id} 200 JSON
GET /api/databases/clusters/{id}/snapshots 200 JSON
POST /api/databases/clusters/{id}/snapshots 200 JSON, snapshot created successfully
POST /api/databases/clusters/{id}/restores 302 to https://cloud.laravel.com

So this is not authentication, not the token, not the Accept/Content-Type pair, and not POST in general. POST /snapshots works with exactly the same setup that makes POST /restores redirect. It looks like the restores route is falling through to a web-session redirect rather than being handled as a token-authenticated API route.

Reproduction
curl -i -X POST "https://cloud.laravel.com/api/databases/clusters/${CLUSTER}/restores" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Accept: application/vnd.api+json" \
  -H "Content-Type: application/vnd.api+json" \
  -d '{"name":"scratch-verify","database_snapshot_id":"'"${SNAPSHOT}"'"}'

Response:

HTTP/2 302
location: https://cloud.laravel.com
content-type: text/html; charset=utf-8
x-amzn-requestid: adc0a260-e499-4bf0-8234-fa2676dd1186
x-amzn-trace-id: Root=1-6a8d22d9-773df68f36f80dd4794da950;Parent=0021dc61b07a0ccf;Sampled=0

The payload shape matches App\Client\Requests\CreateDatabaseRestoreRequestData::toRequestData() (name, database_snapshot_id, restore_time) and the endpoint matches CreateDatabaseRestoreRequest::resolveEndpoint(), so the CLI's own request is being redirected the same way. Reproduced via curl and via the CLI itself.

No restore cluster is created, and the source cluster is unaffected.

Environment
  • laravel/cloud-cli v0.5.2, with #183 / #187 already in place
  • PHP 8.4 / macOS (darwin 25.5.0)
  • Cluster type laravel_mysql_84, region ap-southeast-2
  • Snapshot used: type: manual, status: available, created via POST /snapshots minutes earlier
Impact

Restoring a snapshot is the documented way to get a copy of a production database without exposing production itself (Laravel MySQL, "How to download a backup"): restore a snapshot to a new cluster, enable public access on the copy, dump from it, delete the copy.

With this route redirecting, that workflow cannot be scripted at all. The remaining option is enabling the public endpoint on the production cluster and dumping from that, which is exactly what the documented workflow exists to avoid. We are verifying that backups are restorable, and creating snapshots works while restoring them does not, so the half that actually matters cannot be exercised.

Request

Could you confirm whether POST /api/databases/clusters/{cluster}/restores is expected to accept API-token auth, and if so route it as an API endpoint rather than redirecting? Request ID adc0a260-e499-4bf0-8234-fa2676dd1186 should identify the call in your logs.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with CreateDatabaseRestoreRequest::resolveEndpoint() and CreateDatabaseRestoreRequestData::toRequestData(), then compare the restore request with the working POST /snapshots request. Reproduce the call with the provided curl command and request ID; done means POST /api/databases/clusters/{cluster}/restores accepts token authentication, returns JSON, and creates the restore without redirecting.

Written by the indexing model from the issue text.

Assessment

Tech stack
laravel, php
Domain
api, databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
40/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.