url-shortener/app.rb

107 lines
2.8 KiB
Ruby

# frozen_string_literal: true
require 'roda'
require 'securerandom'
require 'json'
require 'sequel'
require 'open-uri'
# URL Shortener App class
class App < Roda
plugin :sessions, secret: ENV.delete('APP_SESSION_SECRET')
plugin :render, escape: true
plugin :flash
plugin :json_parser
plugin :request_headers
DB = Sequel.sqlite("db/#{ENV.fetch('DB_NAME', nil)}")
links = DB[:links]
route do |r|
r.root do
@message = flash['message'] || 'Enter a URL'
view :home
end
r.get String do |url_code|
link = links.filter(code: url_code)
r.redirect link.first[:url] unless link.first.nil?
@message = "Link #{url_code} doesn't exist"
response.status = 404
view :home
end
r.post 'create' do
url = r.params['url']
if url.nil? || url.empty?
flash['message'] = 'Please enter a valid URL'
r.redirect '/'
end
begin
OpenURI.open_uri(url)
rescue URI::BadURIError
flash['message'] = 'Invalid URL'
r.redirect '/'
rescue OpenURI::HTTPError
flash['message'] = 'URL not found'
r.redirect '/'
rescue SocketError
flash['message'] = 'URL does not resolve'
r.redirect '/'
end
if links.filter(url:).first.nil?
code = SecureRandom.urlsafe_base64 4
links.insert(url:, code:)
@message = 'Link created'
end
code = links.filter(url:).first[:code]
@message ||= 'Link exists'
@new_link = "http://#{request.env['HTTP_HOST']}/#{code}"
view :create
end
r.on 'links' do
r.post do
if r.headers['CONTENT_TYPE'] != 'application/json'
response.status = 400
return { message: 'not a valid json request' }.to_json
end
url = r.params['url']
if url.nil?
response.status = 400
return { message: 'missing url parameter' }.to_json
end
if url.empty?
response.status = 400
return { message: 'invalid url parameter' }.to_json
end
begin
OpenURI.open_uri(url)
rescue URI::BadURIError
response.status = 400
return { message: 'invalid url parameter' }.to_json
rescue OpenURI::HTTPError
response.status = 400
return { message: 'url not found' }.to_json
rescue SocketError
response.status = 400
return { message: 'url does not resolve' }.to_json
end
if links.filter(url:).first.nil?
code = SecureRandom.urlsafe_base64 4
links.insert(url:, code:)
end
code = links.filter(url:).first[:code]
@new_link = "http://#{request.env['HTTP_HOST']}/#{code}"
return { url:, code:, link: @new_link }.to_json
end
end
end
end