Обработка многочастного тела ответа в Angular - PullRequest
0 голосов
/ 08 марта 2019

Я получаю многочастное тело ответа в Angular, но приложение не обрабатывает ответ правильно.Оказывается, что HttpClient в Angular не может правильно анализировать многочастные тела ответа (см. эту проблему на GitHub ).

HttpClient просто возвращает необработанный многочастичный ответ внутри телаобъект HttpResponse, в то время как я хотел бы, чтобы блок application/json из многочастного ответа был доступен внутри моего HttpResponse объекта.

Как правильно обрабатывать многочастный ответ внутри Angular?

1 Ответ

1 голос
/ 08 марта 2019

Я сделал быстрое и грязное решение, вдохновленное этим другим постом о stackoverflow, и создал класс перехватчика http, который показывает, как можно выполнить анализ многочастных ответов. Перехватчик возвращает первую часть 'application / json' в качестве тела ответа из составного ответа (multipart/mixed, multipart/form-data или multipart/related). Посредством карты дополнительные парсеры для других типов контента могут быть легко добавлены в класс.

Я поделюсь этим кодом, это может послужить вдохновением для других:

import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

@Injectable({
  providedIn: 'root',
})

export class MultipartInterceptService implements HttpInterceptor {

  private parserMap = {
    'application/json': JSON.parse,
  };

  private parseMultipart(multipart: string, boundary: string): any {
    const dataArray: string[] = multipart.split(`--${boundary}`);
    dataArray.shift();
    dataArray.forEach((dataBlock) => {
      const rows = dataBlock.split(/\r?\n/).splice(1, 4);
      if (rows.length < 1) {
        return;
      }
      const headers = rows.splice(0, 2);
      const body = rows.join('');
      if (headers.length > 1) {
        const pattern = /Content-Type: ([a-z\/+]+)/g;
        const match = pattern.exec(headers[0]);
        if (match === null) {
          throw Error('Unable to find Content-Type header value');
        }
        const contentType = match[1];
        if (this.parserMap.hasOwnProperty(contentType) === true) {
          return this.parserMap[contentType](body);
        }
      }
    });
    return false;
  }

  private parseResponse(response: HttpResponse<any>): HttpResponse<any> {
    const contentTypeHeaderValue = response.headers.get('Content-Type');
    const body = response.body;
    const contentTypeArray = contentTypeHeaderValue.split(';');
    const contentType = contentTypeArray[0];
    switch (contentType) {
      case 'multipart/related':
      case 'multipart/mixed':
      case 'multipart/form-data':
        const boundary = contentTypeArray[1].split('boundary=')[1];
        const parsed = this.parseMultipart(body, boundary);
        if (parsed === false) {
          throw Error('Unable to parse multipart response');
        }
        return response.clone({ body: parsed });
      default:
        return response;
    }
  }

  // intercept request and add parse custom response
  public intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(request)
      .pipe(
        map((response: HttpResponse<any>) => {
          if (response instanceof HttpResponse) {
            return this.parseResponse(response);
          }
        }),
      );
  }
}

Код считывает границу из заголовка ответа Content-Type и разбивает тело ответа на блоки, используя эту границу. Затем он пытается проанализировать каждую часть и возвращает первый успешно проанализированный блок application/json из ответа.

Вам понадобится собственный синтаксический анализатор или измените логику, если вы заинтересованы в возврате другого блока кода или если вы хотите объединить несколько блоков кода в окончательном ответе. Это потребует некоторой настройки кода.

ПРИМЕЧАНИЕ: Этот код является экспериментальным и ограниченным образом проверен, так что пока он не готов к работе, будьте осторожны при его использовании.

...