mirror of
git://f0xx.org/android_cast
synced 2026-07-29 05:17:39 +03:00
Add gzip-aware crash upload and OTA staging build/deploy tooling.
This restores the interrupted stash work on a dedicated feature branch, including backend decoding support, Dockerized build scripts, and staging channel artifacts for end-to-end OTA validation. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -109,6 +109,22 @@ curl -X POST http://127.0.0.1:8080/api/upload.php \
|
||||
-d @../sample_crash_java.json
|
||||
```
|
||||
|
||||
**Gzip ingest** (Android sends `Content-Encoding: gzip`; plain JSON still works):
|
||||
|
||||
```bash
|
||||
./scripts/test_gzip_upload.sh
|
||||
# BASE=https://apps.f0xx.org/app/androidcast_project/crashes ./scripts/test_gzip_upload.sh
|
||||
```
|
||||
|
||||
On the **BE nginx** upload `location`, enable gunzip so PHP receives plain JSON (see `nginx.vm.conf`):
|
||||
|
||||
```nginx
|
||||
gunzip on;
|
||||
gunzip_types application/json;
|
||||
```
|
||||
|
||||
PHP also decodes gzip if the header reaches FPM (`read_crash_upload_body()` in `bootstrap.php`). After deploy, sync `public/` + `src/` and reload nginx.
|
||||
|
||||
## Production (nginx + PHP-FPM)
|
||||
|
||||
**Deploy topology (FE/BE, ports, sshfs):** [docs/INFRA.md](../../../docs/INFRA.md).
|
||||
|
||||
@@ -17,11 +17,13 @@ server {
|
||||
}
|
||||
|
||||
location ~ ^/app/androidcast_project/crashes/api/upload\.php$ {
|
||||
gunzip on;
|
||||
gunzip_types application/json;
|
||||
alias /var/www/androidcast_crashes/public/api/upload.php;
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME /var/www/androidcast_crashes/public/api/upload.php;
|
||||
fastcgi_pass unix:/run/php-fpm/www.sock;
|
||||
client_max_body_size 4m;
|
||||
client_max_body_size 8m;
|
||||
}
|
||||
|
||||
location ~ ^/app/androidcast_project/crashes/.+\.php$ {
|
||||
|
||||
@@ -36,12 +36,15 @@ server {
|
||||
}
|
||||
|
||||
location = /app/androidcast_project/crashes/api/upload.php {
|
||||
# Decompress gzip uploads from Android before PHP (needs ngx_http_gunzip_module).
|
||||
gunzip on;
|
||||
gunzip_types application/json;
|
||||
include fastcgi_params;
|
||||
fastcgi_pass unix:/run/php-fpm.socket;
|
||||
fastcgi_param SCRIPT_FILENAME /var/www/localhost/htdocs/apps/app/androidcast_project/android_cast/examples/crash_reporter/backend/public/api/upload.php;
|
||||
fastcgi_param SCRIPT_NAME /app/androidcast_project/crashes/api/upload.php;
|
||||
fastcgi_param REQUEST_URI $request_uri;
|
||||
client_max_body_size 4m;
|
||||
client_max_body_size 8m;
|
||||
}
|
||||
|
||||
location ^~ /app/androidcast_project/crashes/ {
|
||||
|
||||
@@ -13,10 +13,13 @@
|
||||
declare(strict_types=1);
|
||||
require_once __DIR__ . '/../../src/bootstrap.php';
|
||||
|
||||
$raw = file_get_contents('php://input');
|
||||
if ($raw === false || $raw === '') {
|
||||
$raw = read_crash_upload_body();
|
||||
if ($raw === null) {
|
||||
json_out(['ok' => false, 'error' => 'empty body'], 400);
|
||||
}
|
||||
if ($raw === false) {
|
||||
json_out(['ok' => false, 'error' => 'invalid gzip body'], 400);
|
||||
}
|
||||
$data = json_decode($raw, true);
|
||||
if (!is_array($data)) {
|
||||
json_out(['ok' => false, 'error' => 'invalid json'], 400);
|
||||
|
||||
33
examples/crash_reporter/backend/scripts/test_gzip_upload.sh
Executable file
33
examples/crash_reporter/backend/scripts/test_gzip_upload.sh
Executable file
@@ -0,0 +1,33 @@
|
||||
#!/bin/sh
|
||||
# Smoke-test gzip crash upload (plain JSON still accepted).
|
||||
# Usage: BASE=http://127.0.0.1:8080/app/androidcast_project/crashes ./scripts/test_gzip_upload.sh
|
||||
set -eu
|
||||
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
SAMPLE="${ROOT}/../sample_crash_java.json"
|
||||
BASE="${BASE:-http://127.0.0.1:8080/app/androidcast_project/crashes}"
|
||||
URL="${BASE}/api/upload.php"
|
||||
RID="gzip-test-$(date +%s)"
|
||||
|
||||
if [ ! -f "$SAMPLE" ]; then
|
||||
echo "Missing $SAMPLE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BODY="$(mktemp)"
|
||||
jq --arg rid "$RID" '.report_id = $rid' "$SAMPLE" > "$BODY"
|
||||
GZIP="$(mktemp)"
|
||||
gzip -c -f "$BODY" > "$GZIP"
|
||||
|
||||
echo "POST plain JSON..."
|
||||
curl -sS -o /dev/null -w "plain:%{http_code}\n" -X POST "$URL" \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data-binary @"$BODY"
|
||||
|
||||
echo "POST gzip (Content-Encoding: gzip)..."
|
||||
curl -sS -w "\n%{http_code}\n" -X POST "$URL" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Content-Encoding: gzip' \
|
||||
--data-binary @"$GZIP"
|
||||
|
||||
rm -f "$BODY" "$GZIP"
|
||||
@@ -79,6 +79,25 @@ function json_out(array $data, int $code = 200): void {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw POST body for crash ingest. Supports plain JSON or Content-Encoding: gzip
|
||||
* (when nginx gunzip is off or the client talks to PHP directly).
|
||||
*
|
||||
* @return string|null decoded JSON text, null if empty, false if gzip decode failed
|
||||
*/
|
||||
function read_crash_upload_body(): string|false|null {
|
||||
$raw = file_get_contents('php://input');
|
||||
if ($raw === false || $raw === '') {
|
||||
return null;
|
||||
}
|
||||
$encoding = $_SERVER['HTTP_CONTENT_ENCODING'] ?? '';
|
||||
if ($encoding !== '' && stripos($encoding, 'gzip') !== false) {
|
||||
$decoded = @gzdecode($raw);
|
||||
return $decoded === false ? false : $decoded;
|
||||
}
|
||||
return $raw;
|
||||
}
|
||||
|
||||
/** Short lines for expandable list preview (not full report detail). */
|
||||
function report_brief_lines(array $row, bool $grouped): array {
|
||||
if ($grouped) {
|
||||
|
||||
Reference in New Issue
Block a user