Angular HttpClient行为原始HTML

9

我正在使用Angular 5 HttpClient,尝试从提供json数据和HTML的页面(Spotify auth)获取HTML响应。

当我使用curl时,我得到了预期的HTML和json负载。但是,无论我用HttpClient尝试什么,我只能得到json,这在这种情况下没有帮助。我想要获取HTML。我已经验证我的标头在命令行curl和HttpClient之间完全相同。

curl -vvv https://accounts.spotify.com/authorize/?client_id=xxxxxxxxxxxxxxx81ad8fc&response_type=code&redirect_uri=http://reaver.xxxxxx.com:4200/callback&state=34fFs29kd09

    <!DOCTYPE html>
<html ng-app="accounts" ng-csp>
  <head>
    <meta charset="utf-8">
    <title ng-bind="(title && (title | localize) + ' - ') + 'Spotify'">Spotify</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <base href="/">
    <link href="https://d2d1dxiu3v1f2i.cloudfront.net/a4a5157/css/index.css" media="screen" rel="stylesheet">

    <script async defer src="https://www.google.com/recaptcha/api.js"></script>
    <script async defer src="https://d2d1dxiu3v1f2i.cloudfront.net/a4a5157/js/index.js" sp-bootstrap></script>
    <meta ng-non-bindable sp-bootstrap-data='{"client":{"name":"Playlist Reaver"},"country":"US","useCaptcha":false,"locales":["*"],"BON":["0","0",-795429514]}'>
  </head>
  <body ng-view></body>
</html>

这个负载的这部分是我能从HttpClient获得的全部内容。
{"client":{"name":"Playlist Reaver"},"country":"US","useCaptcha":false,"locales":["*"],"BON":["0","0",-795429514]}

通常我会说很好,但我真的需要访问HTML。

如何从包含JSON数据和HTML的响应中获取原始HTML?

我的get调用看起来像这样:

return this.http.get(this.apiGeneric, { params: params, observe: 'response'});

额外信息:我的http标头似乎没有被添加。我已经进行了如下更改,但在http请求标头中没有看到XFF标头。

  // function returns Observable UserResponse object
  getUrl() {
    this.httpHeaders = new HttpHeaders();
    //.set('Content-Type'
    this.httpHeaders.set('Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8');
    this.httpHeaders.set('XFF', 'testing123');

    let params = new HttpParams();
    const params = new HttpParams()
      .set('client_id', this.clientId)
      .set('response_type', 'code')
      .set('redirect_uri', this.redirectUri)

    console.log(params);
    return this.http.get(this.apiGeneric, { headers: this.httpHeaders, params: params, observe: 'response' });
    }

1
你尝试设置适当的接受类型了吗? - jonrsharpe
请尝试使用 { params: params, observe: 'response', responseType: 'text'}。 - David
感谢 @jonrsharpe。我实际上已经这样做了:this.httpHeaders.set('Accept', 'text/html');Chrome开发者模式捕获到这个被发送的头部信息为:Accept: application/json, text/plain, / - Ahack
@david 谢谢。一旦我得到了正确的 API 标头并收到了 HTML 和其他有效载荷,那么我就会遇到 JSON 解码错误,而 responseType 帮助关闭了 JSON 解码。一切都准备好了,谢谢! - Ahack
1个回答

3

好的,我找到了问题所在。这可能是我对生成标题的理解有误,但我发现:

this.httpHeaders = new HttpHeaders();
this.httpHeaders.set('Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8');

(.set和.add)都会导致httpHeaders为空

更改如何构建标头解决了我的问题,并且content-type标头(以及一些客户测试标头)被插入,我得到了完整的HTML输出。如果其他人遇到这个问题,以下是解决问题的正确方法:

const headers = new HttpHeaders({
    Accept:'text/html',
    XFF:'testing123'
  });

const params = new HttpParams()
  .set('client_id', this.clientId)
  .set('response_type', 'code')
  .set('redirect_uri', this.redirectUri)

console.log(headers.get('Accept'));
console.log(this.apiGeneric);
return this.http.get(this.apiGeneric, { headers: headers, params:params });
}

证据:XFF标头和接受标头是我们设置的内容:
Accept:text/html
Accept-Encoding:gzip, deflate, br
Accept-Language:en-US,en;q=0.9
Connection:keep-alive
Host:accounts.spotify.com
Origin:http://evil.com/
Referer:http://192.168.1.29:4200/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36
XFF:testing123

2
HttpHeaders 对象是不可变的.set.add 方法会返回一个新的对象,其中包含了额外的头信息。因此,可以通过链式调用或者设置 this.httpHeaders = this.httpHeaders.set(...); 来实现。 - jonrsharpe
@jonrsharpe 谢谢。那当然是我的误解。现在我完全明白了。再次感谢! - Ahack

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接