From 5feaee4922a88ae9e1309888cb56d5ed846698dd Mon Sep 17 00:00:00 2001 From: songtianlun Date: Sun, 26 Jan 2025 00:07:44 +0800 Subject: [PATCH] feat: add sitemap functionality - Create SitemapsController to serve sitemaps - Configure AWS S3 storage for sitemaps - Update routes to include sitemap paths - Add SitemapsHelper module - Configure SitemapGenerator with AWS adapter - Update storage configurations for AWS This feature adds sitemap functionality to the application, enabling search engines to discover and index its content more efficiently. It includes configuration for AWS S3 storage to host the sitemaps and updates the application's routes to serve them. --- app/controllers/sitemaps_controller.rb | 33 ++++++++++++++++++++ app/helpers/sitemaps_helper.rb | 2 ++ app/workers/refresh_sitemap_worker.rb | 21 ++++++++++++- config/initializers/aws.rb | 19 +++++++++++ config/routes.rb | 2 ++ config/sitemap.rb | 8 +++++ config/storage.yml | 10 +++--- test/controllers/sitemaps_controller_test.rb | 7 +++++ 8 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 app/controllers/sitemaps_controller.rb create mode 100644 app/helpers/sitemaps_helper.rb create mode 100644 config/initializers/aws.rb create mode 100644 test/controllers/sitemaps_controller_test.rb diff --git a/app/controllers/sitemaps_controller.rb b/app/controllers/sitemaps_controller.rb new file mode 100644 index 0000000..b6fa991 --- /dev/null +++ b/app/controllers/sitemaps_controller.rb @@ -0,0 +1,33 @@ +class SitemapsController < ApplicationController + def show + path = params[:path] + bucket_name = + Rails.env.production? ? + ENV.fetch("AWS_BUCKET", Rails.application.credentials.dig(:aws, :bucket)) : + ENV.fetch("AWS_DEV_BUCKET", Rails.application.credentials.dig(:aws_dev, :bucket)) + Rails.logger.info "Sitemap: #{path}" + + begin + s3_client = Aws::S3::Client.new + 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 +end diff --git a/app/helpers/sitemaps_helper.rb b/app/helpers/sitemaps_helper.rb new file mode 100644 index 0000000..509e433 --- /dev/null +++ b/app/helpers/sitemaps_helper.rb @@ -0,0 +1,2 @@ +module SitemapsHelper +end diff --git a/app/workers/refresh_sitemap_worker.rb b/app/workers/refresh_sitemap_worker.rb index e34ee67..6b768dd 100644 --- a/app/workers/refresh_sitemap_worker.rb +++ b/app/workers/refresh_sitemap_worker.rb @@ -5,6 +5,25 @@ class RefreshSitemapWorker host = Rails.env.production? ? "https://todayaiweather.com" : "http://127.0.0.1:3000" Rails.application.routes.default_url_options[:host] = host SitemapGenerator::Sitemap.default_host = host + if Rails.env.production? + SitemapGenerator::Sitemap.adapter = SitemapGenerator::AwsSdkAdapter.new( + ENV.fetch("AWS_BUCKET", Rails.application.credentials.dig(:aws, :bucket)), + aws_access_key_id: ENV.fetch("AWS_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws, :access_key_id)), + aws_secret_access_key: ENV.fetch("AWS_SECRET_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws, :secret_access_key)), + aws_region: ENV.fetch("AWS_REGION", "wnam"), + endpoint: ENV.fetch("AWS_ENDPOINT", Rails.application.credentials.dig(:aws, :endpoint)), + ) + else + SitemapGenerator::Sitemap.adapter = SitemapGenerator::AwsSdkAdapter.new( + ENV.fetch("AWS_DEV_BUCKET", Rails.application.credentials.dig(:aws_dev, :bucket)), + aws_access_key_id: ENV.fetch("AWS_DEV_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws_dev, :access_key_id)), + aws_secret_access_key: ENV.fetch("AWS_DEV_SECRET_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws_dev, :secret_access_key)), + aws_region: ENV.fetch("AWS_DEV_REGION", "wnam"), + endpoint: ENV.fetch("AWS_DEV_ENDPOINT", Rails.application.credentials.dig(:aws_dev, :endpoint)), + ) + end + SitemapGenerator::Sitemap.sitemaps_path = "sitemaps/" + SitemapGenerator::Sitemap.create do add root_path, changefreq: "daily", priority: 1.0 add cities_path, changefreq: "daily", priority: 0.9 @@ -32,7 +51,7 @@ class RefreshSitemapWorker end # SitemapGenerator::Sitemap.ping_search_engines if Rails.env.production? - Rails.logger.info "Sitemap has been generated successfully" + Rails.logger.info "Sitemap has been generated and uploaded to S3 successfully" rescue => e Rails.logger.error "Error refreshing sitemap: #{e.message}" end diff --git a/config/initializers/aws.rb b/config/initializers/aws.rb new file mode 100644 index 0000000..3540cc1 --- /dev/null +++ b/config/initializers/aws.rb @@ -0,0 +1,19 @@ +if Rails.env.production? + Aws.config.update({ + region: ENV.fetch("AWS_REGION", "wnam"), + credentials: Aws::Credentials.new( + ENV.fetch("AWS_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws, :access_key_id)), + ENV.fetch("AWS_SECRET_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws, :secret_access_key)) + ), + endpoint: ENV.fetch("AWS_ENDPOINT", Rails.application.credentials.dig(:aws, :endpoint)) + }) +else + Aws.config.update({ + region: ENV.fetch("AWS_DEV_REGION", "wnam"), + credentials: Aws::Credentials.new( + ENV.fetch("AWS_DEV_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws_dev, :access_key_id)), + ENV.fetch("AWS_DEV_SECRET_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws_dev, :secret_access_key)) + ), + endpoint: ENV.fetch("AWS_DEV_ENDPOINT", Rails.application.credentials.dig(:aws_dev, :endpoint)) + }) +end diff --git a/config/routes.rb b/config/routes.rb index a11760f..afea55e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -18,6 +18,8 @@ Rails.application.routes.draw do get "cities/index" get "cities/show" get "home/index" + get "sitemaps/*path", to: "sitemaps#show", format: false + devise_for :admin_users, ActiveAdmin::Devise.config ActiveAdmin.routes(self) diff --git a/config/sitemap.rb b/config/sitemap.rb index 9fb27a2..d053ca6 100644 --- a/config/sitemap.rb +++ b/config/sitemap.rb @@ -1,5 +1,13 @@ # Set the host name for URL creation host = Rails.env.production? ? "https://todayaiweather.com" : "http://127.0.0.1:3000" +Rails.application.routes.default_url_options[:host] = host +SitemapGenerator::Sitemap.adapter = SitemapGenerator::AwsSdkAdapter.new( + Rails.application.credentials.dig(:aws, :bucket), + aws_access_key_id: Rails.application.credentials.dig(:aws, :access_key_id), + aws_secret_access_key: Rails.application.credentials.dig(:aws, :secret_access_key), + aws_region: Rails.application.credentials.dig(:aws, :region) +) +SitemapGenerator::Sitemap.sitemaps_path = "sitemaps/" SitemapGenerator::Sitemap.default_host = host diff --git a/config/storage.yml b/config/storage.yml index 4dedeb4..d30c883 100644 --- a/config/storage.yml +++ b/config/storage.yml @@ -19,11 +19,11 @@ build: # bucket: your_own_bucket-<%= Rails.env %> amazon_dev: service: S3 - access_key_id: <%= ENV.fetch("AWS_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws_dev, :access_key_id)) %> - secret_access_key: <%= ENV.fetch("AWS_SECRET_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws_dev, :secret_access_key)) %> - region: <%= ENV.fetch("AWS_REGION", "wnam") %> - bucket: <%= ENV.fetch("AWS_BUCKET", Rails.application.credentials.dig(:aws_dev, :bucket)) %> - endpoint: <%= ENV.fetch("AWS_ENDPOINT", Rails.application.credentials.dig(:aws_dev, :endpoint)) %> + access_key_id: <%= ENV.fetch("AWS_DEV_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws_dev, :access_key_id)) %> + secret_access_key: <%= ENV.fetch("AWS_DEV_SECRET_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws_dev, :secret_access_key)) %> + region: <%= ENV.fetch("AWS_DEV_REGION", "wnam") %> + bucket: <%= ENV.fetch("AWS_DEV_BUCKET", Rails.application.credentials.dig(:aws_dev, :bucket)) %> + endpoint: <%= ENV.fetch("AWS_DEV_ENDPOINT", Rails.application.credentials.dig(:aws_dev, :endpoint)) %> amazon: service: S3 diff --git a/test/controllers/sitemaps_controller_test.rb b/test/controllers/sitemaps_controller_test.rb new file mode 100644 index 0000000..e93ae53 --- /dev/null +++ b/test/controllers/sitemaps_controller_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class SitemapsControllerTest < ActionDispatch::IntegrationTest + # test "the truth" do + # assert true + # end +end