blob: 6d4ab45fdabfd1fba7b2fc95cd839057edb41ac2 [file] [log] [blame]
# frozen_string_literal: true
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# TODO: keep this only until this is fixed https://github.com/middleman/middleman/issues/2312
require 'webrick'
require 'middleman-core/builder'
Middleman::Util.module_eval do
module_function
def normalize_path(path)
return path unless path.is_a?(String)
# The tr call works around a bug in Ruby's Unicode handling
WEBrick::HTTPUtils.unescape(path).sub(%r{^/}, '').tr('', '')
end
end
Middleman::Rack.class_eval do
# https://github.com/middleman/middleman/blob/master/middleman-core/lib/middleman-core/rack.rb#L90
def process_request(env, req, res) # rubocop:disable Metrics/AbcSize
start_time = Time.now
request_path = WEBrick::HTTPUtils.unescape(env['PATH_INFO'].dup)
request_path.force_encoding('UTF-8') if request_path.respond_to? :force_encoding
request_path = ::Middleman::Util.full_path(request_path, @middleman)
full_request_path = File.join(env['SCRIPT_NAME'], request_path) # Path including rack mount
# Run before callbacks
@middleman.execute_callbacks(:before)
# Get the resource object for this path
resource = @middleman.sitemap.find_resource_by_destination_path(request_path.gsub(' ', '%20'))
# Return 404 if not in sitemap
return not_found(res, full_request_path) unless resource && !resource.ignored?
# If this path is a binary file, send it immediately
return send_file(resource, env) if resource.binary?
res['Content-Type'] = resource.content_type || 'text/plain'
begin
# Write out the contents of the page
res.write resource.render({}, rack: { request: req })
# Valid content is a 200 status
res.status = 200
rescue Middleman::TemplateRenderer::TemplateNotFound => e
res.write "Error: #{e.message}"
res.status = 500
end
# End the request
logger.debug "== Finishing Request: #{resource.destination_path} (#{(Time.now - start_time).round(2)}s)" # rubocop:disable Layout/LineLength
halt res.finish
end
end
Middleman::Builder.class_eval do
def output_resource(resource) # rubocop:disable Metrics/AbcSize
::Middleman::Util.instrument 'builder.output.resource', path: File.basename(resource.destination_path) do # rubocop:disable Layout/LineLength
output_file = @build_dir + resource.destination_path.gsub('%20', ' ')
begin
if resource.binary?
export_file!(output_file, resource.file_descriptor[:full_path])
else
response = @rack.get(::URI.encode_www_form_component(resource.request_path))
# If we get a response, save it to a tempfile.
if response.status == 200
export_file!(output_file, binary_encode(response.body))
else
trigger(:error, output_file, response.body)
return false
end
end
rescue StandardError => e
trigger(:error, output_file, "#{e}\n#{e.backtrace.join("\n")}")
return false
end
output_file
end
end
end
Middleman::Extensions::AssetHash.class_eval do
def manipulate_single_resource(resource) # rubocop:disable Metrics/AbcSize
return unless @exts.include?(resource.ext)
return if ignored_resource?(resource)
return if resource.ignored?
digest = if resource.binary?
::Digest::SHA1.file(resource.source_file).hexdigest[0..7]
else
# Render through the Rack interface so middleware and mounted apps get a shot
response = @rack_client.get(
::URI.encode_www_form_component(resource.destination_path),
'bypass_inline_url_rewriter_asset_hash' => 'true'
)
raise "#{resource.path} should be in the sitemap!" unless response.status == 200
::Digest::SHA1.hexdigest(response.body)[0..7]
end
path, basename, extension = split_path(resource.destination_path)
resource.destination_path = options.rename_proc.call(path, basename, digest, extension, options)
resource
end
end