带主体的Angular HttpClient Get方法

Bru*_*uel 7 angular angular-httpclient

我正在改进现有的API,并且要求提供一种可以接受多个搜索条件并基于这些条件执行查询的单一get方法。

我正在使用Spring MVC。get方法签名:

@GetMapping("/subscribers")
public ResponseEntity<List<SubscriberDTO>> getAllSubscribers(Pageable pageable, @RequestBody List<SearchCriteria> lstSearchCriteria)
Run Code Online (Sandbox Code Playgroud)

该实现按预期在邮递员上进行了测试

现在我要去Angular实现前端,但是我找不到通过HttpClient Get方法发送正文的方法。

我有点卡住。我应该在标题上发送搜索条件吗?还是有更好的方法呢?

use*_*515 6

get 请求是否可以有主体一直存在争论。我认为这不是本主题的主题。如果您确实需要使用 body 发出 get 请求(例如服务器强制执行),您可以使用request方法:

request(method: string, url: string, options: {
        body?: any;
        headers?: HttpHeaders | {
            [header: string]: string | string[];
        };
       //.......
        
    }): Observable<ArrayBuffer>;
Run Code Online (Sandbox Code Playgroud)

  • 抱歉,我上次的评论搞砸了,记错了。如果我没记错的话,在使用此功能时,chrome 中的网络检查显然没有 GET 请求的正文。不太可能是网络问题。 (2认同)

Nun*_*usa 5

据我所知,您不能使用HttpClient获取发送正文。您至少可以使用该查询以使其成为惯用语。(或者,您可以尝试让Lets说您拥有符合条件的数组:

const criteria = [ {a: 25}, {b: 23} ];
http.get(url + '/?criteria='+ encodeURIComponent( JSON.stringify(criteria)));
Run Code Online (Sandbox Code Playgroud)

在GET请求中发送正文违反了某些RFC标准,即使可行,您也必须召唤一些神秘的恶魔。

  • 您介意添加对您的声明“违反某些 RFC 标准”的引用来支持它吗? (15认同)
  • RFC2616 第 4.3 节和第 5.1.1 节 - 尽管实际上它非常模糊,并且建议 Web 服务器在基于请求方法不允许时丢弃正文 - 我知道大多数 Web 服务器确实会丢弃 GET 请求上的 BODY 行。事实上,甚至有一些 apache 的 mods 可以逆转这种行为。 (3认同)

Ami*_*mir 5

在服务方法中,您可以使用如下所示的方法,该方法采用搜索查询的可选参数。您可以通过 Observe 发送您的搜索参数,如下所示。

getAllSubscribers(
    page?,
    itemsPerPage?,
    userParams?
  ): Observable<PaginatedResult<Subscribers[]>> {
    const paginatedResult: PaginatedResultSubscribers[]> = new PaginatedResult<
      Subscribers[]
    >();

    let params = new HttpParams();

    if (page != null && itemsPerPage != null) {
      params = params.append("pageNumber", page);
      params = params.append("pageSize", itemsPerPage);
    }

    if (userParams != null) {
      params = params.append("minAge", userParams.minAge);
      params = params.append("maxAge", userParams.maxAge);
        }

       return this.http
      .get<Subscribers[]>(this.baseUrl + "/subscribers", { observe: "response", params })
      .pipe(
        map(response => {
          paginatedResult.result = response.body;
          if (response.headers.get("Pagination") != null) {
            paginatedResult.pagination = JSON.parse(
              response.headers.get("Pagination")
            );
          }
          return paginatedResult;
        })
      );
  }
Run Code Online (Sandbox Code Playgroud)

基本思想是使用HttpParams。

  • 请记住,“HttpParams”是**不可变的**。我花了一段时间才弄清楚为什么 `params.append()` 不起作用。 (2认同)
  • @Odys-好点。您可以执行 new HttpParams().set(minAge", userParams.minAge).set("maxAge", userParams.maxAge) (2认同)

cbp*_*cbp 5

只是为了澄清这里的一些答案,首先,如上所述,Angular 不支持向主体提供 GET 请求,并且没有办法解决这个问题。造成这种情况的原因不是 Angular 的错,而是浏览器用于发出请求的 API XMLHttpRequest (XHR) 的错。XHR 不支持 GET 请求的正文。

当前的 HTTP 标准中没有任何内容表明带有 GET 请求的 Body 是无效的,只是它在语义上没有明确定义。

就 REST 而言,我认为,向主体提供 GET 请求比使用 POST 更可取。所以 XHR 不支持这一点有点烦人。

  • 当然 Angular 支持它,请参阅有关使用“请求”方法的信息。此外,就 REST 而言,使用 body 和 GET 可能会导致将来难以跟踪问题。您会想知道为什么应用程序在“没有任何变化”的情况下停止工作。可能需要付出一些努力才能意识到某些网络组件(例如代理或新的 Kubernetes 设置)不支持使用 body 获取。别问我怎么知道的。 (2认同)