JavaScript를 통해 HTTP 통신~HTTPStreaming 편 배우기~

10667 단어 JavaScript

개시하다


본고는Chunked transfer encoding(WebSocket을 사용하지 않는 PUSH 통신의 한 공식)을 통해HTTPStreaming의 견본 프로그램을 보여 준다.
  • 서버 측면에 Ruby로 작성된 CGI 프로그램
  • 클라이언트 측은 허브 자바스크립트 기반fetchAPI를 사용하는 프로그램
  • HTTPStreaming을 통해 서버 측에서 시간을 들여 처리하더라도 실행이 끝날 때까지 기다리지 않고 매번 클라이언트에 처리 결과를 알릴 수 있다
  • Chunked transfer encording에 따른 HTTPStreaming


    WebSocket을 사용하지 않는 PUSH 통신 방식백문이 불여일견이라서 HTTP Streaming 모드 테스트 데모 사이트를 소개했다.이 사이트는 PHP/jQuery에서 이루어졌습니다.

    서버에서 응답 통신 방법

  • Transfer-encoding:chunked를 응답 첫 부분으로 보내기
  • 서버에서 PUSH에 알리는 블록(chunk)에 chunk의 크기와 chunk의 내용을 보내기
  • 구체적으로 다음과 같다.
  • Content-Type: text/plain
    Transfer-Encoding: chunked
    
    1
    a
    2
    aa
    3
    aaa
    4
    aaaa
    5
    aaaaa
    6
    aaaaaa
    7
    aaaaaaa
    8
    aaaaaaaa
    9
    aaa
    aaaaaa
    a
    aaaaaaaaaa
    b
    aaaaaaaaaaa
    c
    aaaaaaaaaaaa
    d
    aaaaaaaaaaaaa
    e
    aaaaaaaaaaaaaa
    0
    [CRLF]
    
  • chunk의 사이즈는 16진수로 발송됩니다.
  • 통신 종료 시 공행 0을 발송합니다.
  • chunk의 크기가 chunk와 일치하지 않으면 클라이언트에 오류가 발생
  • 이 Chunked transfer encoding은 HTTP/1.1의 4.1절
    구문을 사용합니다.아래와 같다.
  • chunked-body   = *chunk
                     last-chunk
                     trailer-part
                     CRLF
    chunk          = chunk-size [ chunk-ext ] CRLF
                     chunk-data CRLF
    chunk-size     = 1*HEXDIG
    last-chunk     = 1*("0") [ chunk-ext ] CRLF
    chunk-data     = 1*OCTET ; a sequence of chunk-size octets
    

    고객은 어떻게 받아들일까요

  • Ruby CGI 프로그램을 통해 서버 측면 통과
  • 클라이언트는 JavaScript에서fetchAPI를 사용한 실현을 나타낸다
  • 1초 간격으로 chunk를 보내는 프로그램
  • streaming.cgi
    #!/usr/bin/ruby                                                                                                         
    
    puts "Content-Type: text/plain"
    puts "Transfer-encoding: chunked"
    puts "\n"
    
    15.times{|n|
      if(n > 0) then
        puts n.to_s(16) # 16進数
        puts 'a' * n
        STDOUT.flush
      end
      sleep 1
    }
    
    puts "0"
    puts               # 空行
    
  • 클라이언트가 ReadStream에서 응답 통신을 받은 결과
  • 매번 발송할 때마다 초당 발송된chunk를 화면에 출력
  • index.js
    function startStream(){
        const url = "./streaming.cgi"
        fetch(url)
            .then((res)=>{
                if(res.ok){
                    const reader = res.body.getReader();
                    let received = 0;
                    const txt = new TextDecoder();
    
                    reader.read().then(function processText({done, value}){
                        if(done){
                            console.log("Stream Complete")
                            return;
                        }
                        received += value.length;
                        const chunk = txt.decode(value);
    
                        let listItem = document.createElement('li');
                        listItem.textContent = 'Read ' + received + ' bytes. Current chunk = ' + chunk;
                        document.getElementById("result").appendChild(listItem);
    
                        return reader.read().then(processText);
                    })
    
                }else{
                    console.log(res);
                }
            })
            .catch((err)=>{
                console.log(err);
            })
    }
    
    <html>
        <head>
            <meta http-equiv="content-type" content="text/html; charset=UTF-8">
            <title>HTTP streaming Test</title>
            <script src="./index.js"></script>
            <style></style>
        </head>
        <body>
            <h1>HTTP streaming Test</h1>
    
            <button onclick="startStream()">Streaming開始</button>
            <ul id="result"></ul>
        </body>
    </html>
    

    실행 결과



    참조 정보 요약

  • tsujimotter의 노트북
  • HTTP Streaming 모드에서 HTTP 서버로 데이터를 밀어내는 방법
  • HTTP Streaming 모드 테스트
  • WEBRick에서 HTTP streaming(Chunked transfer encoding)
  • HTTP/1.1의 Transfer-Encoding을 써 보았습니다:chunked를 제공하는 도구
  • 좋은 웹페이지 즐겨찾기