fix(link): send QR create options as multipart/form-data#135
Closed
jaredwray wants to merge 1 commit into
Closed
Conversation
The Hyphen API's `POST .../link/codes/:code/qrs/` endpoint consumes `multipart/form-data` (the logo is an uploaded file, and each text field is validated as a multipart field). `createQrCode` was sending a JSON body, so any request that included custom options (title, backgroundColor, color, size) failed the multipart body-schema validation and was rejected with HTTP 400; only the no-options call slipped through. Build the request as `FormData`, appending only the options that were provided and uploading the logo as a file, and drop the JSON content-type header so fetch sets `multipart/form-data` with its generated boundary. Update the request-body unit test to assert on the multipart body, add a no-options case, and re-enable the custom-options integration test (resolves #133). https://claude.ai/code/session_011Cn9uaUZa7n8MsPgBP79Dd
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.
Problem
Custom options on QR codes don't work between the SDK and the API. Calling
link.createQrCode(code, { title, backgroundColor, color, size })is rejected by the Hyphen API with HTTP 400 (tracked as #133). A plaincreateQrCode(code)with no options works, which masked the bug.Root cause
The API endpoint
POST /organizations/:organizationId/link/codes/:codeId/qrs/consumesmultipart/form-data:qr.schema.tsdeclaresconsumes: ['multipart/form-data']; the body schema validates each text field as a multipart field ({ value }) and thelogoas an uploaded file (isFile: true).app.tsregisters@fastify/multipartwithattachFieldsToBody: true, and the route handler reads each field viarawPayload[key].value/rawPayload[key]._buf.The SDK's
createQrCode, however, sent a JSON body withcontent-type: application/json. When custom options are present, the JSON string values fail the multipart body-schema validation → HTTP 400. With no options the body is empty, so it slips through — which is why only the custom-options path was broken.Fix (SDK only)
createQrCodenow builds aFormDatabody:title,backgroundColor,color,size);logoas a file (base64 is decoded to bytes and sent as aBlob);content-typeheader sofetchsetsmultipart/form-datawith its generated boundary (@cacheable/netpassesFormDatastraight through tofetch).The apix side is correct as designed (the
logois intentionally a file upload with a 1MB limit), so no API change is needed — the SDK simply now conforms to the documented contract.Tests
FormData(field values, thelogoBlob contents, and thatcontent-typeis left unset).should create a QR code with custom optionsintegration test (resolves Flaky/failing test:should create a QR code with custom optionsreturns HTTP 400 #133).Verification
biome checkclean;tsc --noEmitclean.createQrCodeunit tests pass and cover the method 100% without network.api.hyphen.aiis not in the network egress allowlist (every live call returns403 Host not in allowlist). They should pass in CI where egress and credentials are configured.https://claude.ai/code/session_011Cn9uaUZa7n8MsPgBP79Dd
Generated by Claude Code