Re: [whatwg/fetch] How should the ReadableStream from response.body work when it's multipart? (#1021)

Here's an example of what that TransformStream looks like (warning my Streams-fu is weak):
```
class MultipartParser {
  constructor(boundary) {
    this.boundary = boundary;
    this.onChunk = null;
    this.onClose = null;

    this.first = null;
    this.lastImage = null;
    this.lastImageLen = 0;
    this.nextType = ParseState.BOUNDARY;
    this.contentLength = -1;
  }

  addBinaryData(incoming_data) {
    this.data = incoming_data;
    this.checkForImages();
  }

  emitImage() {
    this.nextType = ParseState.BOUNDARY;
    if (this.lastImageLen > 0)
      this.onChunk(this.lastImage);
    this.lastImage = null;
    this.lastImageLen = 0;
  }

  checkForImages() {
    var dataIndex = 0;
    while (dataIndex < this.data.length) {
      var subdata = this.data.slice(dataIndex);
      switch (this.nextType) {
        case ParseState.DATA:
          var sum = subdata.length + this.lastImageLen;
          if (sum == this.contentLength) {
            this.lastImage = subdata;
            this.lastImageLen += subdata.length;
            this.emitImage();
            dataIndex += subdata.length;
            this.nextType = ParseState.BOUNDARY;
          } else if (sum > this.contentLength) {
            var remainingImage = this.contentLength - this.lastImage.length;
            this.lastImage.set(
                subdata.slice(0, remainingImage), this.lastImageLen);
            this.lastImageLen += remainingImage;
            this.emitImage();
            dataIndex += remainingImage;
            this.nextType = ParseState.BOUNDARY;
          } else {
            this.lastImage.set(subdata, this.lastImageLen);
            this.lastImageLen += subdata.length;
            dataIndex += subdata.length;
          }
          break;
        case ParseState.CONTENT_TYPE:
          if (subdata.length == 2 && subdata.toString() == "\r\n")
            this.nextType = ParseState.BOUNDARY;
          else
            this.nextType = ParseState.CONTENT_LEN;
          dataIndex += subdata.indexOf(10) + 1;
          break;
        case ParseState.CONTENT_LEN:
          var cl = new TextDecoder("utf-8").decode(
              subdata.slice(0, subdata.indexOf(10)));
          this.contentLength = parseInt(
              cl.toLowerCase().split("content-length:")[1].trim());
          this.nextType = ParseState.BLANK_LINE;
          this.lastImage = new Uint8Array(this.contentLength);
          this.lastImageLen = 0;
          dataIndex += subdata.indexOf(10) + 1;
          break;
        case ParseState.BOUNDARY:
          this.nextType = ParseState.CONTENT_TYPE;
          dataIndex += subdata.indexOf(10) + 1;
          break;
        case ParseState.BLANK_LINE:
          this.nextType = ParseState.DATA;
          dataIndex += subdata.indexOf(10) + 1;
          break;
      }
    }
  }
}

var parser;
class MultipartTransformStream {
  constructor(boundary) {
    parser = new MultipartParser(boundary);

    this.readable = new ReadableStream({
      start(controller) {
        parser.onChunk = chunk => controller.enqueue(chunk);
        parser.onClose = () => controller.close();
      }
    });

    this.writable = new WritableStream({
      write(incoming_data) {
        parser.addBinaryData(incoming_data);
      }
    });
  }
}
```

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/fetch/issues/1021#issuecomment-614920327

Received on Thursday, 16 April 2020 22:04:19 UTC