Module: MLserver::Server

Defined in:
lib/MLserver/server.rb

Constant Summary collapse

@@valid_http_versions =
["HTTP/1.0", "HTTP/1.1"]

Class Method Summary collapse

Class Method Details

.handle_client(client) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/MLserver/server.rb', line 76

def self.handle_client(client)
  settings = MLserver.settings

  logger = MLserver.settings.logger
  handler = MLserver.settings.handler

  loop do
    r=RequestParser.parse_request(client)

    logger.log_traffic client.peeraddr[2], :incoming, "#{r.method} #{r.path} #{r.httpver}"

    if !@@use_http_versions.include?(r.httpver)
      client_ip = client.peeraddr[2]

      resp = MLserver::ErrorResponse.new(505)
      r.respond resp.response
      client.close

      Thread.exit
    end

    if r.httpver == "HTTP/1.1"
      if !r.headers[:Host]
        r.respond ErrorResponse.new(400).response
        client.close
        Thread.exit
      elsif settings.force_host
        if !settings.force_host.include?(r.headers[:Host])
          r.respond ErrorResponse.new(400).response
          client.close
          Thread.exit
        end
      end
    end

    if MLserver.settings.trim_urls && r.path != "/" && r.path[-1] == "/"
      r.respond RedirectResponse.new(r.path[0..-2], type: 301, httpver: "HTTP/1.0").response
      client.close
      Thread.exit
    end

    begin
      handler.run(r, client)
    rescue => e
      r.respond ErrorResponse.new(500).response
      logger.log "An error occured: #{e.message}", :error
      raise e
    end

    if r.httpver == "HTTP/1.0" || r.headers[:Connection] == "close"
      client.close
      Thread.exit
    end
  end
end

.startObject



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
# File 'lib/MLserver/server.rb', line 5

def self.start
  settings = MLserver.settings

  host = settings.host
  port = settings.port
  ssl_host = settings.ssl_host
  ssl_port = settings.ssl_port
  handler = settings.handler
  logger = settings.logger
  @@use_http_versions = @@valid_http_versions - (@@valid_http_versions - settings.use_http_versions)

  logger.log "MLserver #{MLserver.version}"

  http_server = TCPServer.new(host, port)
  logger.log "Listening on #{logger.format_ip_address host}:#{port}"

  if settings.ssl
    ssl_context = OpenSSL::SSL::SSLContext.new
    ssl_context.cert = OpenSSL::X509::Certificate.new(File.open(settings.ssl_cert).read)
    ssl_context.key = OpenSSL::PKey::RSA.new(File.open(settings.ssl_key).read)

    store = OpenSSL::X509::Store.new
    settings.ssl_additional_certs.each do |c|
      store.add_cert(OpenSSL::X509::Certificate.new(File.open(c).read))
    end

    ssl_context.cert_store = store

    tcp_server = TCPServer.new(ssl_host, ssl_port)

    ssl_server = OpenSSL::SSL::SSLServer.new(tcp_server, ssl_context)
    logger.log "Listening with SSL on #{logger.format_ip_address ssl_host}:#{ssl_port}"
  end

  if settings.ssl
    Thread.new do
      loop do
        begin
          client = ssl_server.accept
        rescue OpenSSL::SSL::SSLError => e
          logger.log "SSL error occured: #{e}", :error
          client.close if client
          next
        rescue Errno::ECONNRESET => e
          logger.log "SSL Connection reset: #{e}", :error
          client.close if client
          next
        end

        Thread.start(client) do |client|
          self.handle_client client
        end
      end
    end
  end

  loop do
    begin
      client = http_server.accept
    rescue OpenSSL::SSL::SSLError => e
      logger.log "SSL error occured: #{e}", :error
      client.close if client
      next
    end

    Thread.start(client) do |client|
      self.handle_client client
    end
  end
end