Class: Rack::WASI::IncomingHandler

Inherits:
Object
  • Object
show all
Defined in:
lib/rack/wasi/incoming_handler.rb

Overview

wasi:http/proxy-like handler implementation for Rack apps

Instance Method Summary collapse

Constructor Details

#initialize(app, base_url: "http://localhost:3000", skip_data_uri_uploads: false) ⇒ IncomingHandler

Returns a new instance of IncomingHandler.



128
129
130
131
132
133
134
# File 'lib/rack/wasi/incoming_handler.rb', line 128

def initialize(app, base_url: "http://localhost:3000", skip_data_uri_uploads: false)
  @app = app

  @app = Rack::DataUriUploads.new(@app) unless skip_data_uri_uploads

  @base_url = base_url
end

Instance Method Details

#handle(req, res) ⇒ Object

Takes Wasi request, converts it to Rack request, calls the Rack app, and write Rack response back to the Wasi response.

Parameters:

  • req (Rack::WASI::HTTP::IncomingRequest)
  • res (Rack::WASI::HTTP::ResponseOutparam)


141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/rack/wasi/incoming_handler.rb', line 141

def handle(req, res)
  uri = URI.join(base_url, req.path_with_query || "")
  headers = req.headers.each.with_object({}) do |(key, value), headers|
    headers["HTTP_#{key.upcase.gsub("-", "_")}"] = value
    headers
  end

  http_method = req.method.upcase
  headers[:method] = http_method

  body = req.consume
  headers[:input] = StringIO.new(body) if body

  request = Rack::MockRequest.env_for(uri.to_s, headers)
  begin
    response = Rack::Response[*@app.call(request)]
    response_status, response_headers, bodyiter = *response.finish

    out_response = OutgoingResponse.new(headers: response_headers, status_code: response_status)

    body = ""
    body_is_set = false

    bodyiter.each do |part|
      body += part
      body_is_set = true
    end

    # Serve images as base64 from Ruby and decode back in JS
    # FIXME: extract into a separate middleware and add a header to indicate the transformation
    if response_headers["Content-Type"]&.start_with?("image/")
      body = Base64.strict_encode64(body)
    end

    out_response.write(body) if body_is_set
    res.set(Result.new(out_response, nil))
  rescue Exception => e
    res.set(Result.new(e.message, 503))
  end
end