annotate net/http/server/chunked_stream.rb @ 0:1eef88068f9f tip

initial commit of maze game source
author ferencd
date Sun, 15 Sep 2019 11:46:47 +0200
parents
children
rev   line source
ferencd@0 1 require 'net/http/server/stream'
ferencd@0 2
ferencd@0 3 require 'net/protocol'
ferencd@0 4 require 'stringio'
ferencd@0 5
ferencd@0 6 module Net
ferencd@0 7 class HTTP < Protocol
ferencd@0 8 module Server
ferencd@0 9 #
ferencd@0 10 # Handles reading and writing to Chunked Transfer-Encoded streams.
ferencd@0 11 #
ferencd@0 12 # @since 0.2.0
ferencd@0 13 #
ferencd@0 14 class ChunkedStream < Stream
ferencd@0 15
ferencd@0 16 #
ferencd@0 17 # Initializes the chuked stream.
ferencd@0 18 #
ferencd@0 19 # @param [#read, #write, #flush] socket
ferencd@0 20 # The socket to read from and write to.
ferencd@0 21 #
ferencd@0 22 def initialize(socket)
ferencd@0 23 super(socket)
ferencd@0 24
ferencd@0 25 @buffer = ''
ferencd@0 26 end
ferencd@0 27
ferencd@0 28 #
ferencd@0 29 # Reads a chunk from the stream.
ferencd@0 30 #
ferencd@0 31 # @param [Integer] length
ferencd@0 32 #
ferencd@0 33 # @param [#<<] buffer
ferencd@0 34 # The optional buffer to append the data to.
ferencd@0 35 #
ferencd@0 36 # @return [String, nil]
ferencd@0 37 # A chunk from the stream.
ferencd@0 38 #
ferencd@0 39 # @raise [ArgumentError]
ferencd@0 40 # The buffer did not respond to `#<<`.
ferencd@0 41 #
ferencd@0 42 # @since 0.2.0
ferencd@0 43 #
ferencd@0 44 def read(length=4096,buffer='')
ferencd@0 45 unless buffer.respond_to?(:<<)
ferencd@0 46 raise(ArgumentError,"buffer must respond to #<<")
ferencd@0 47 end
ferencd@0 48
ferencd@0 49 until @buffer.length >= length
ferencd@0 50 length_line = @socket.readline("\r\n").chomp
ferencd@0 51 chunk_length = length_line.split(';',2).first.to_i(16)
ferencd@0 52
ferencd@0 53 # read the chunk
ferencd@0 54 @buffer << @socket.read(chunk_length)
ferencd@0 55
ferencd@0 56 # chomp the terminating CRLF
ferencd@0 57 @socket.read(2)
ferencd@0 58
ferencd@0 59 # end-of-stream
ferencd@0 60 break if chunk_length == 0
ferencd@0 61 end
ferencd@0 62
ferencd@0 63 # clear the buffer before appending
ferencd@0 64 buffer.replace('')
ferencd@0 65
ferencd@0 66 unless @buffer.empty?
ferencd@0 67 # empty a slice of the buffer
ferencd@0 68 buffer << @buffer.slice!(0,length)
ferencd@0 69 return buffer
ferencd@0 70 end
ferencd@0 71 end
ferencd@0 72
ferencd@0 73 #
ferencd@0 74 # Writes data to the chunked stream.
ferencd@0 75 #
ferencd@0 76 # @param [String] data
ferencd@0 77 # The data to write to the stream.
ferencd@0 78 #
ferencd@0 79 # @return [Integer]
ferencd@0 80 # The length of the data written.
ferencd@0 81 #
ferencd@0 82 # @since 0.2.0
ferencd@0 83 #
ferencd@0 84 def write(data)
ferencd@0 85 length = data.length
ferencd@0 86
ferencd@0 87 # do not write empty chunks
ferencd@0 88 unless length == 0
ferencd@0 89 # write the chunk length
ferencd@0 90 @socket.write("%X\r\n" % length)
ferencd@0 91
ferencd@0 92 # write the data
ferencd@0 93 @socket.write(data)
ferencd@0 94 @socket.write("\r\n")
ferencd@0 95 @socket.flush
ferencd@0 96 end
ferencd@0 97
ferencd@0 98 return length
ferencd@0 99 end
ferencd@0 100
ferencd@0 101 #
ferencd@0 102 # Closes the chunked stream.
ferencd@0 103 #
ferencd@0 104 # @since 0.2.0
ferencd@0 105 #
ferencd@0 106 def close
ferencd@0 107 # last chunk
ferencd@0 108 @socket.write("0\r\n\r\n")
ferencd@0 109 @socket.flush
ferencd@0 110 end
ferencd@0 111
ferencd@0 112 end
ferencd@0 113 end
ferencd@0 114 end
ferencd@0 115 end