Angular 2 & Slim PHP 框架:如何正确转义字符串以用于 GET 请求

Angular 2 & Slim PHP Framework: How to properly escape a string for use in a GET request

环境

我有一个使用 Angular2 构建的前端,它与使用 Slim PHP Framework v4.

构建的 API 进行通信

在 Angular 前端中,用户可以在表单中输入文本并提交,然后收到来自 API 的响应。

Angular 项目向 URL /api/{text} 提出请求。

据我所知,在 Slim v4 中无法访问通过 /api?text={text} 提供的参数,因此我无法使用 Angular 的 HttpParams 功能。因此,URL 直接传递给 Angular 的 HttpClient。即

let text = 'Some random text / with special characters \.';
let myObservable: Observable<MyResponseObject[]>;
myObservable = this.http.get<MyResponseObject[]>(
  'http://my.domain.name/api/' + text
).pipe(catchError(this.handleError));

问题

我读到某些字符被编码,然后在提交请求之前由 Angular 再次解码(即 \/.)。由于这个原因,上面例子中的text变量的值是无效的。

一种解决方案是手动创建正则表达式语句并在提交请求之前使用它对字符串进行编码,然后在 API.

中解码字符串

我想避免这种情况,所以我想知道以下两种情况中的一种是否可行:

  1. 是否有任何 Javascript、Typescript 或 Angular 编码字符串的功能,如所述,用于 URI 中?

  2. 有什么方法可以让我从 Slim 版本 4 中的 GET 请求访问以格式 ?text={text} 提供的参数的值?

编辑:

我还在 Angular 中使用自定义提供程序以 ?auth=[my_token_here] 格式将身份验证令牌附加为 URL 参数。令牌附加到 Angular 发送的每个请求。自定义提供程序使用以下代码附加参数:

intercept(req: HttpRequest<any>, next: HttpHandler) {
  return this.authService.user.pipe(take(1), exhaustMap(user => {
    if(!user) {
      return next.handle(req);
    }
    const modifiedReq = req.clone({
      params: new HttpParams().set('auth', user.token)
    });
    return next.handle(modifiedReq);
  }));
}

我已经弄明白了如何从 Slim API 中读取 'auth' 的值。但是,当我修改 get 请求以添加 text 变量作为参数时,该参数从未提交,Slim API 仍然只看到 auth 参数。修改后的代码如下:

myObservable = this.http.get<MyResponseObject[]>(
  'http://localhost:8080/ngrams/', {
  params: new HttpParams().set('text', text)
}).pipe(catchError(this.handleError));

所以这里没有错误,但是 'text' 参数从来没有附加到 URL (我在提交请求时检查浏览器的网络选项卡时只能看到 auth 参数) .

我是一个 Angular 菜鸟所以这个逻辑可能有缺陷,但上面的身份验证代码是从教程中复制的。我的想法是,在身份验证提供程序中分配 new HttpParams() 可能会覆盖我为获取请求设置的参数。

当我手动或使用Postman创建相同的请求时,所以我本地环境中的URL是http://localhost:8080/api/?text=some text goes here,然后我可以使用$req->getQueryParams()方法成功检索参数。

根据Slim 4 documentation

You can get the query parameters as an associative array on the Request object using getQueryParams().

这是一个例子:

$app->get('/api', function($request, $response, $args){
    $response->getBody()->write('<pre>' . print_r($request->getQueryParams(), 1) . '</pre>');
    return $response;
});

$app->run();

如果您访问 /api?text=special chars %3A%20 \ %2F %3F %25 %26 ^ %23,结果是:

Array
(
    [text] => special chars :  \ / ? % & ^ #
)

根据 Nima 的回答,使用 getQueryParams() 时 Slim API 正确读取了这些值。问题是首先没有发送参数。

问题是我的身份验证服务正在为 http 请求分配一个新的 HttpParams 对象,它应该在现有参数集中添加一个身份验证令牌。

这个问题已通过更新问题中提到的 intercept() 方法解决,因此 auth 令牌附加到请求的现有 params 属性:

intercept(req: HttpRequest<any>, next: HttpHandler) {
  return this.authService.user.pipe(take(1), exhaustMap(user => {
    if(!user) {
      return next.handle(req);
    }
    const modifiedReq = req.clone({
      params: req.params.set('auth', user.token)
    });
    return next.handle(modifiedReq);
  }));
}