英文:
How to replace some encoded character in a query string before Laravel create a Request instance?
问题
When the query string separator &
is encoded with its corresponding value %26
, the request cannot extract the query parameters correctly.
On my web application, I do not encode this character and I have no controls on how it's structured before hitting my API.
I did a debug trace of the Request object in the controller method and this URL my.api.com/api/productcategory/catalogue?sort_by%5bcountry.name_en%5d=asc&sort_by%5bproductbrand.name%5d=asc&sort_by%5bproduct.name%5d=asc&sort_by%5bvintage.vintage%5d=asc&per_page=25&page=1&lang=en
returns the correct following query parameters:
query: Symfony\Component\HttpFoundation\ParameterBag {#60 ▼
#parameters: array:4 [▼
"sort_by" => array:4 [▶]
"per_page" => "25"
"page" => "1"
"lang" => "en"
]
}
On the other hand, when the &
is encoded as in this URL my.api.com/api/productcategory/catalogue?sort_by%5bcountry.name_en%5d=asc%26sort_by%5bproductbrand.name%5d=asc%26sort_by%5bproduct.name%5d=asc%26sort_by%5bvintage.vintage%5d=asc%26per_page=25%26page=1%26lang=en
, the query parameter are wrongly extracted like this:
query: Symfony\Component\HttpFoundation\ParameterBag {#60 ▼
#parameters: array:1 [▼
"sort_by" => array:1 [▼
"country.name_en" => "asc&sort_by[productbrand.name]=asc&sort_by[product.name]=asc&sort_by[vintage.vintage]=asc&per_page=25&page=1&lang=en"
]
]
}
Is there a way to intercept the query and do a str_replace('%26', '&', $theQuery)
before it gets process by the Request object?
I'm Using Laravel 6.2 with PHP 7.2 on Ubuntu 22.04
英文:
When the query string separator &
is encoded with its corresponding value %26
, the request cannot extract the query parameters correctly.
On my web application, I do not encode this character and I have no controls on how it's structured before hitting my API.
I did a debug trace of the Request object in the controller method and this URL my.api.com/api/productcategory/catalogue?sort_by%5bcountry.name_en%5d=asc&sort_by%5bproductbrand.name%5d=asc&sort_by%5bproduct.name%5d=asc&sort_by%5bvintage.vintage%5d=asc&per_page=25&page=1&lang=en
returns the correct following query parameters:
query: Symfony\Component\HttpFoundation\ParameterBag {#60 ▼
#parameters: array:4 [▼
"sort_by" => array:4 [▶]
"per_page" => "25"
"page" => "1"
"lang" => "en"
]
}
On the other hand, when the &
is encoded as in this URL my.api.com/api/productcategory/catalogue?sort_by%5bcountry.name_en%5d=asc%26sort_by%5bproductbrand.name%5d=asc%26sort_by%5bproduct.name%5d=asc%26sort_by%5bvintage.vintage%5d=asc%26per_page=25%26page=1%26lang=en
, the query parameter are wrongly extracted like this:
query: Symfony\Component\HttpFoundation\ParameterBag {#60 ▼
#parameters: array:1 [▼
"sort_by" => array:1 [▼
"country.name_en" => "asc&sort_by[productbrand.name]=asc&sort_by[product.name]=asc&sort_by[vintage.vintage]=asc&per_page=25&page=1&lang=en"
]
]
}
Is there a way to intercept the query and do a str_replace('%26', '&', $theQuery)
before it gets process by the Request object?
I'm Using Laravel 6.2 with PHP 7.2 on Ubuntu 22.04
答案1
得分: 1
根据Andrew的建议,以下是使用中间件的解决方案,其中它被用于每个API路由。
class URLMonitorMiddleware
{
public function handle(Request $request, Closure $next): Response
{
// 解析完整URL并返回其组成部分
$parsedUrl = parse_url($request->fullUrl());
// 不一定总是有查询字符串...!
if (isset($parsedUrl['query'])) {
// 解码查询字符串
$decodedQuery = urldecode($parsedUrl['query']);
// 将查询字符串解析为变量
parse_str($decodedQuery, $query);
// 用查询设置替换当前参数。
$request->replace($query);
}
return $next($request);
}
}
英文:
As per Andrew suggestion, here is the solution using a Middleware, where it is called for each API routes.
class URLMonitorMiddleware
{
public function handle(Request $request, Closure $next): Response
{
// Parse the full URL and return its components
$parsedUrl = parse_url($request->fullUrl());
// There may not always be a query string...!
if (isset($parsedUrl['query'])) {
// Decode the query
$decodedQuery = urldecode($parsedUrl['query']);
// Parses the query into variables
parse_str($decodedQuery, $query);
// Replaces the current parameters with the query set.
$request->replace($query);
}
return $next($request);
}
}
答案2
得分: -1
I think you are looking for middleware in this situation. It allows you to manage requests before they enter the application. You can manipulate the request object. Middleware can be applied to every single route globally or selectively used on certain routes only.
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class BeforeMiddleware
{
public function handle(Request $request, Closure $next): Response
{
// Perform action
return $next($request);
}
}
When dealing with the request object, Laravel has built-in methods for overwriting attributes. You can access specific attributes with:
$data = $request->all();
// $data['sort_by']
But in your case, you can access the URL and modify it with:
$request->fullUrl()
英文:
I think you are looking for middleware in this situation. It allows you to manage requests before they enter the application. You can manipulate the request object. Middleware can be applied to every single route globally or selectively used on certain routes only.
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class BeforeMiddleware
{
public function handle(Request $request, Closure $next): Response
{
// Perform action
return $next($request);
}
}
When dealing with the request object, Laravel has built in methods for overwriting attributes. You can access specific attributes with:
$data = $request->all();
// $data['sort_by']
But in your case you can access the url and modify it with:
$request->fullUrl()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论