fix(lambda): return a downloadable GetFunction Code.Location#1718
Open
Jongsic wants to merge 1 commit into
Open
fix(lambda): return a downloadable GetFunction Code.Location#1718Jongsic wants to merge 1 commit into
Jongsic wants to merge 1 commit into
Conversation
GetFunction returned a fabricated real-AWS S3 URL for Code.Location that 404s, so clients (and browser UIs) cannot download the deployment package. Persist the uploaded zip in Floci's own S3 (awslambda-<region>-tasks) on every successful code deploy and return a path-style URL on the local endpoint (built from the request via UriInfo), matching AWS/LocalStack. Bytes are exact, so the download hashes to the stored CodeSha256. Centralized in extractZipCode so it covers ZipFile, S3-source, and the reactive S3-update listener; hot-reload is excluded by design. The stored object is overwritten on redeploy and removed on DeleteFunction.
Comment on lines
+558
to
+564
| if (s3Service != null) { | ||
| try { | ||
| s3Service.deleteObject(tasksBucketName(region), codeObjectKey(fn)); | ||
| } catch (Exception ignored) { | ||
| // best-effort cleanup | ||
| } | ||
| } |
There was a problem hiding this comment.
Silent catch in
deleteFunction cleanup violates the project's coding style. AGENTS.md states: "Never leave a catch block empty. If an exception is intentionally tolerated, log it with enough context to diagnose it later." The storeDeploymentPackage equivalent correctly uses LOG.warnv; the delete cleanup should do the same so failures are diagnosable.
Suggested change
| if (s3Service != null) { | |
| try { | |
| s3Service.deleteObject(tasksBucketName(region), codeObjectKey(fn)); | |
| } catch (Exception ignored) { | |
| // best-effort cleanup | |
| } | |
| } | |
| if (s3Service != null) { | |
| try { | |
| s3Service.deleteObject(tasksBucketName(region), codeObjectKey(fn)); | |
| } catch (Exception e) { | |
| // best-effort cleanup | |
| LOG.warnv("Could not delete deployment package for {0}: {1}", | |
| functionName, e.getMessage()); | |
| } | |
| } |
Context Used: AGENTS.md (source)
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
GetFunction(GET /2015-03-31/functions/{name}) returned a hardcoded, fabricated real-AWS URL forCode.Location:That URL points at real AWS S3, is not presigned, and 404s. Any client that follows
Code.Locationto download the deployment package — CLIs, tooling, and browser-only UIs — cannot fetch the code. Real AWS and LocalStack both return a working, downloadable URL.Root cause: Floci extracts the uploaded zip to a directory and discards the original bytes, so there was nothing to serve.
Fix: on every successful code deploy, persist the exact original zip bytes into Floci's own S3 under a per-region tasks bucket (
awslambda-<region>-tasks), keyed bysnapshots/<account>/<functionName>.GetFunctionnow builds a path-style URL on the local endpoint from the incoming request viaUriInfo, so it targets the same Floci the client is already talking to (mirrors LocalStack).RepositoryType: "S3"stays truthful.CodeSha256(sha256(originalZipBytes)). Re-zipping the extracted dir would break that.S3Service+S3Controller's path-styleGET /{bucket}/{key:.+}+ global CORS. No new endpoint, no new serving code.extractZipCode, so it coversZipFile,S3Bucket/S3Keysource, and the reactive S3-update listener with one change. Stored only after handler-file verification passes, so a rejected deploy leaves no orphan object.Lifecycle: the stable key means redeploys overwrite in place (no stale accumulation), and
DeleteFunctionbest-effort deletes the object.Scope / tradeoffs:
S3Bucket == "hot-reload") have no zip, so no object is stored —Code.Location404s for them, matching the "no downloadable package" reality.NoSuchBucket/NoSuchKey→ clean 404, same "can't download" state as before, just against the local endpoint).awslambda-<region>-tasksbucket becomes visible inListBuckets(same as LocalStack). Hiding service buckets is a separate follow-up, out of scope here.Type of change
fix:)feat:)feat!:orfix!:)AWS Compatibility
GetFunctionreturned a fabricated real-AWS S3 URL forCode.Locationthat 404s and is not presigned, so the deployment package could not be downloaded by any client following the URL.aws-cli/2.31.38(create-functionwith--zip-file, thenget-function), following the returnedCode.Locationwithcurl. Response is200 application/zipand the downloaded bytes' SHA-256 matches the function'sCodeSha256(byte-exact). Behavior mirrors LocalStack's path-styleCode.Location.Checklist
./mvnw testpasses locally