dscmall/laravel-filesystem-obs
A Laravel filesystem driver for Huawei Cloud OBS (Object Storage Service), letting you use OBS buckets through the familiar Storage facade. Drop-in Flysystem adapter supporting uploads, downloads, deletes and URLs alongside your existing disks.
Architecture fit. The package targets a real gap: Laravel's Storage facade is driver-based, and Huawei Cloud OBS is not a drop-in S3 replacement. While OBS exposes an S3-compatible subset, Laravel's built-in s3 driver (backed by aws-sdk-php) routinely breaks against OBS on request signing nuances, ACL/x-amz-* header translation, path-style vs. virtual-hosted addressing, and temporaryUrl() generation. A dedicated Flysystem adapter that wraps Huawei's official obs/esdk-obs-php SDK is therefore the architecturally correct shape for this integration — it plugs into the standard Storage::disk() contract, so application code stays framework-idiomatic and storage-agnostic at the call site. Fit is good if the adapter is a thin, faithful translation of the Flysystem v3 FilesystemAdapter interface.
Integration feasibility. Mechanically low-effort: composer require, register the service provider (or rely on package discovery), and add a disk entry in config/filesystems.php with driver => 'obs', key/secret, bucket, and region-specific endpoint. The real feasibility question is version alignment, not wiring. Laravel 9+ moved to Flysystem v3 (League\Flysystem\FilesystemAdapter), while Laravel 8 and earlier used v1/v2 (AdapterInterface). A 15-star package at a 0.315 maturity score is unlikely to carry a CI matrix across Laravel 8→12 and PHP 7.4→8.3. Expect to verify, not assume, support for the version pair you actually run.
Technical risk. Ranked:
| Risk | Severity | Why |
|---|---|---|
| Flysystem/Laravel version drift | High | Interface signature changes cause hard failures or silently missing methods (readStream, writeStream, listContents pagination) |
| Streaming vs. buffering | High | If the adapter buffers whole objects in memory rather than streaming, large uploads/downloads will exhaust PHP memory limits under load |
temporaryUrl() support |
Medium–High | Private buckets need presigned URLs; absence forces a workaround or public buckets (a security regression) |
| Multipart upload | Medium | Files >100 MB may time out or fail without chunked upload |
| Credential handling | Medium | IAM/STS temporary credentials and rotation; hard-coded long-lived AK/SK is a compliance finding |
| Bus factor / abandonment | High | Single maintainer, low stars, no visible governance — you may inherit the code |
| Error semantics | Medium | OBS SDK exceptions may not map to Laravel's UnableToReadFile/UnableToWriteFile, breaking Storage::exists()/@if-style guards |
| Security posture | Medium | Audit for debug logging of credentials, TLS verification, and pinned SDK versions |
Key questions for the maintainer or a spike.
temporaryUrl(), and does it honor custom/CDN domains?obs/esdk-obs-php version is pinned, and does it accept a PSR-18/PSR-3 client and logger?Stack fit. Clean fit for any Laravel app already on the Storage facade — no application-layer rewrite is required for basic put/get/delete/url. The integration boundary is exactly one config block plus one driver name. That containment is the main reason this is worth a spike rather than a rejection: the blast radius of failure is small and reversible.
Migration path. Three scenarios:
ObjectStorage interface (put/get/delete/temporaryUrl/exists) with an OBS-backed implementation. Application code depends on the interface, not Storage::disk('obs'). This costs roughly a day and converts a package-abandonment event into a contained swap.rclone (its S3 backend supports Huawei OBS as a provider) or Huawei's obsutil for bulk copy, then dual-write during cutover, then verify by checksum and object count before flipping the default disk. Keep the source bucket read-only for a rollback window.Compatibility. Verify the exact Laravel/PHP pair first; treat anything outside a tested combination as unsupported. Pin the package to an exact version ("dscmall/laravel-filesystem-obs": "x.y.z"), commit the lockfile, and pin the transitive obs/esdk-obs-php version. If the package is incompatible with your Flysystem major, the fallback is a ~200–400 line in-house adapter over the official SDK — feasible and probably preferable to fighting an unmaintained wrapper.
Sequencing.
listContents pagination, and a forced 403 to inspect error mapping.Maintenance. Expect to own this transitively. A 15-star package is a dependency you are effectively co-maintaining: budget for periodic forks, cherry-picked patches, and manual verification against new Laravel majors. Concretely, reserve a small recurring engineering allotment (order of one to two days per quarter) for compatibility review, plus an alert when the upstream repo goes quiet or the OBS SDK publishes a breaking version. Record the fork point and keep a diffable local branch.
Support. Huawei Cloud's OBS documentation and console are partially Chinese-first, and OBS-specific errors (signature mismatch, region/endpoint mismatch, AccessDenied from bucket policy vs. object ACL) are poorly covered by generic Laravel/S3 knowledge. On-call engineers will need a short decision tree mapping OBS error codes to causes. Escalation to Huawei support is the only path for platform-side incidents; the package maintainer will not be a viable escalation route.
Scaling. OBS itself scales horizontally without effort on our side; the constraint is PHP. Every synchronous Storage::put() occupies a PHP-FPM worker for the duration of the transfer. Above moderate volume, this dominates request latency. Mitigations, in order of preference: (a) direct-to-OBS browser uploads via presigned POST, bypassing PHP entirely; (b) queue-backed ingestion workers with retries and idempotency keys; (c) a CDN/custom domain in front of the bucket for reads, which also cuts egress cost. Confirm the adapter honors a custom domain before committing to (c).
Failure modes to instrument.
private where the app expects public, producing broken asset URLs. Test with a private bucket from day one rather than discovering it later.listContents results from unpaginated implementations — dangerous for any cleanup/retention job.Ramp-up. Low for application developers — the Storage facade is already familiar, and no new mental model is required. Moderate for platform/SRE — they must learn Huawei IAM, bucket policies, region endpoints, and OBS's error taxonomy. High for whoever becomes the package owner, since that person needs to read both the Flysystem adapter internals and the OBS SDK. Plan a half-day knowledge transfer, a written runbook covering the error decision tree and the fork/upgrade procedure, and a named backup owner. Do not let this become tribal knowledge held by one engineer.
How can I help you explore Laravel packages today?