yahns.git  about / heads / tags
sleepy, multi-threaded, non-blocking application server for Ruby
blob b6ca1a3ff787b6381bf8ae6f8d349de52cdef3bf 1798 bytes (raw)
$ git show maint:lib/yahns/max_body/wrapper.rb	# shows this blob on the CLI

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
 
# -*- encoding: binary -*-
# Copyright (C) 2013-2016 all contributors <yahns-public@yhbt.net>
# License: GPLv2 or later (https://www.gnu.org/licenses/gpl-2.0.txt)
# frozen_string_literal: true
#
# This is only used for chunked request bodies, which are rare
class Yahns::MaxBody::Wrapper # :nodoc:
  def initialize(rack_input, limit)
    @input = rack_input
    @limit = limit
    @rbuf = ''.dup
  end

  def each
    while line = gets
      yield line
    end
  end

  # chunked encoding means this method behaves more like readpartial,
  # since Rack does not support a method named "readpartial"
  def read(length = nil, rv = ''.dup)
    if length
      if length <= @rbuf.size
        length < 0 and raise ArgumentError, "negative length #{length} given"
        rv.replace(@rbuf.slice!(0, length))
      elsif @rbuf.empty?
        checked_read(length, rv) or return
      else
        rv.replace(@rbuf.slice!(0, @rbuf.size))
      end
      rv.empty? && length != 0 ? nil : rv
    else
      rv.replace(read_all)
    end
  end

  def gets
    sep = $/
    if sep.nil?
      rv = read_all
      return rv.empty? ? nil : rv
    end
    re = /\A(.*?#{Regexp.escape(sep)})/

    begin
      @rbuf.sub!(re, '') and return $1

      if tmp = checked_read(16384)
        @rbuf << tmp
        tmp.clear
      elsif @rbuf.empty? # EOF
        return nil
      else # EOF, return whatever is left
        return @rbuf.slice!(0, @rbuf.size)
      end
    end while true
  end

  def checked_read(length = 16384, buf = ''.dup)
    if @input.read(length, buf)
      throw :yahns_EFBIG if ((@limit -= buf.size) < 0)
      return buf
    end
  end

  def read_all
    rv = @rbuf.slice!(0, @rbuf.size)
    tmp = ''.dup
    while checked_read(16384, tmp)
      rv << tmp
    end
    tmp.clear
    rv
  end
end

git clone git://yhbt.net/yahns.git
git clone https://yhbt.net/yahns.git