Problem
HttpRequestEvent::rebuildQueryString() re-parses and re-encodes rawQueryString on every API Gateway v2 request, and there's no way to get the original back:
if ($this->isFormatV2()) {
$queryString = $this->event['rawQueryString'] ?? '';
// We re-parse the query string to make sure it is URL-encoded
return http_build_query(self::queryStringToArray($queryString), '', '&', \PHP_QUERY_RFC3986);
}
An unencoded URL in a query value gets split on its own &:
in: location=https://zoom.us/w/1?tk=AAA&pwd=SECRET
out: location => 'https://zoom.us/w/1?tk=AAA'
pwd => 'SECRET'
Re-encoding then bakes the split in and turns the ? into %3F, so an app can't tell "this was split" apart from "this was always properly encoded". This isn't hypothetical, it silently truncated live customer links for us (ActiveCampaign has no urlencode modifier, so a merge tag holding a URL lands in the query string raw).
I get why the normalisation is there and I'm not proposing changing it. Just asking to keep the original reachable.
No userland workaround
getQueryString(), getUri() and getQueryParameters() all derive from the normalised property. rawQueryString sits at the event top level, so it's not in getRequestContext() either. The only way in is subclassing the handler to read $event->toArray()['rawQueryString'], which forces a serverless.yml handler swap that's easy to lose on a deploy.
(v1/ALB is worse, not a fallback: AWS has already split those into queryStringParameters.)
Proposed change
Add an accessor:
public function getRawQueryString(): string
{
return $this->event['rawQueryString'] ?? '';
}
and surface it as a server var in Psr7Bridge::convertRequest():
'BREF_RAW_QUERY_STRING' => $event->getRawQueryString(),
That covers Octane without touching laravel-bridge: OctaneHandler calls SymfonyRequestBridge::convertRequest(), which wraps Psr7Bridge::convertRequest() and then server->add()s its own LAMBDA_* vars on top, so anything already in the PSR-7 server array reaches $request->server in Laravel.
Additive, no behaviour change, no config.
One thing for review: on v1/ALB there's no rawQueryString in the event at all. Empty string, or leave the var unset so an app can tell "not available" apart from "genuinely empty"? Note Psr7Bridge filters $server on !== null, so '' survives but null drops out.
Happy to send a PR if you're open to it, just let me know which way you'd want that to go.
Environment
- Bref 3.0.9 (checked against
master), PHP 8.5
- API Gateway HTTP API (payload format 2.0)
- Octane, via
brefphp/laravel-bridge
Problem
HttpRequestEvent::rebuildQueryString()re-parses and re-encodesrawQueryStringon every API Gateway v2 request, and there's no way to get the original back:An unencoded URL in a query value gets split on its own
&:Re-encoding then bakes the split in and turns the
?into%3F, so an app can't tell "this was split" apart from "this was always properly encoded". This isn't hypothetical, it silently truncated live customer links for us (ActiveCampaign has no urlencode modifier, so a merge tag holding a URL lands in the query string raw).I get why the normalisation is there and I'm not proposing changing it. Just asking to keep the original reachable.
No userland workaround
getQueryString(),getUri()andgetQueryParameters()all derive from the normalised property.rawQueryStringsits at the event top level, so it's not ingetRequestContext()either. The only way in is subclassing the handler to read$event->toArray()['rawQueryString'], which forces aserverless.ymlhandler swap that's easy to lose on a deploy.(v1/ALB is worse, not a fallback: AWS has already split those into
queryStringParameters.)Proposed change
Add an accessor:
and surface it as a server var in
Psr7Bridge::convertRequest():That covers Octane without touching laravel-bridge:
OctaneHandlercallsSymfonyRequestBridge::convertRequest(), which wrapsPsr7Bridge::convertRequest()and thenserver->add()s its ownLAMBDA_*vars on top, so anything already in the PSR-7 server array reaches$request->serverin Laravel.Additive, no behaviour change, no config.
One thing for review: on v1/ALB there's no
rawQueryStringin the event at all. Empty string, or leave the var unset so an app can tell "not available" apart from "genuinely empty"? NotePsr7Bridgefilters$serveron!== null, so''survives butnulldrops out.Happy to send a PR if you're open to it, just let me know which way you'd want that to go.
Environment
master), PHP 8.5brefphp/laravel-bridge