today_ai_weather/app/controllers/sitemaps_controller.rb
songtianlun fe5c0d5113
Some checks failed
Docker Dev / docker (push) Has been cancelled
CI / scan_ruby (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / test (push) Has been cancelled
Docker Main / docker (push) Has been cancelled
fix: update sitemap retrieval logic
- Change from using `get_object` to `head_object` to check if the
  sitemap file exists before attempting to retrieve it.
- Implement a presigned URL for accessing the sitemap, which is valid
  for 15 minutes.
- Set cache headers to allow for 1 hour of caching.
- Improved logging for better error tracking and debugging.

This change enhances the efficiency of sitemap retrieval by reducing
unnecessary data transfer and provides a more secure way to access
the sitemaps through presigned URLs. It also improves error handling
by logging specific errors related to missing sitemaps.
2025-02-24 17:42:55 +08:00

127 lines
3.4 KiB
Ruby
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

class SitemapsController < ApplicationController
include SitemapsHelper
before_action :set_bucket_name
def index
@sitemaps = list_sitemaps
respond_to do |format|
format.html
format.xml { render_sitemap_index }
end
rescue Aws::S3::Errors::ServiceError => e
Rails.logger.error "S3 Error: #{e.message}"
render status: :internal_server_error
end
def show
path = params[:path]
key = "sitemaps/#{path}"
Rails.logger.info "Requesting sitemap: #{path}"
begin
# 检查文件是否存在
s3_client.head_object(
bucket: @bucket_name,
key: key
)
# 生成预签名URL设置15分钟有效期
signer = Aws::S3::Presigner.new(client: s3_client)
url = signer.presigned_url(
:get_object,
bucket: @bucket_name,
key: key,
expires_in: 15 * 60, # 15 minutes
# response_content_type: 'application/xml', # 确保正确的内容类型
response_content_disposition: "inline" # 在浏览器中直接显示
)
# 设置缓存头
response.headers["Cache-Control"] = "public, max-age=3600" # 1小时缓存
# 重定向到预签名URL
redirect_to url, allow_other_host: true, status: :found
rescue Aws::S3::Errors::NotFound
Rails.logger.error "Sitemap not found: #{path}"
render status: :not_found
rescue Aws::S3::Errors::ServiceError => e
Rails.logger.error "S3 Error: #{e.message}"
render status: :internal_server_error
end
end
# def show
# path = params[:path]
# Rails.logger.info "Sitemap: #{path}"
# begin
# response = s3_client.get_object(
# bucket: @bucket_name,
# key: "sitemaps/#{path}"
# )
# expires_in 12.hours, public: true
# content_type = response.content_type || "application/xml"
# send_data(
# response.body.read,
# filename: path,
# type: content_type,
# disposition: "inline"
# )
# rescue Aws::S3::Errors::NoSuchKey
# render status: :not_found
# rescue Aws::S3::Errors::ServiceError => e
# Rails.logger.error "S3 Error: #{e.message}"
# render status: :internal_server_error
# end
# end
private
def set_bucket_name
@bucket_name = Rails.env.production? ?
ENV.fetch("AWS_BUCKET", Rails.application.credentials.dig(:minio, :bucket)) :
ENV.fetch("AWS_DEV_BUCKET", Rails.application.credentials.dig(:minio_dev, :bucket))
end
def s3_client
@s3_client ||= Aws::S3::Client.new
end
def list_sitemaps
response = s3_client.list_objects_v2(
bucket: @bucket_name,
prefix: "sitemaps/"
)
response.contents.map do |object|
{
key: object.key.sub("sitemaps/", ""),
last_modified: object.last_modified,
size: object.size,
url: sitemap_url(object.key.sub("sitemaps/", ""))
}
end.reject { |obj| obj[:key].empty? }
end
def render_sitemap_index
base_url = "#{request.protocol}#{request.host_with_port}"
builder = Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml|
xml.sitemapindex(xmlns: "http://www.sitemaps.org/schemas/sitemap/0.9") do
@sitemaps.each do |sitemap|
xml.sitemap do
xml.loc "#{base_url}/sitemaps/#{sitemap[:key]}"
xml.lastmod sitemap[:last_modified].iso8601
end
end
end
end
render xml: builder.to_xml
end
end