This repository has been archived by the owner on Feb 23, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathrpaproxy.rb
231 lines (203 loc) · 5.55 KB
/
rpaproxy.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# -*- coding: utf-8 -*-
require 'sinatra'
require 'mongoid'
require 'omniauth'
require 'omniauth-twitter'
require 'haml'
require './models/user.rb'
require './models/proxy.rb'
require './models/log.rb'
require './models/stat.rb'
require './models/client.rb'
if production?
require 'memcachier'
require 'rack/session/dalli'
use Rack::Session::Dalli, cache: Dalli::Client.new, expire_after: 2592000
else
use Rack::Session::Pool, expire_after: 2592000
end
use OmniAuth::Builder do
provider :twitter, ENV['TWITTER_KEY'], ENV['TWITTER_SECRET']
provider :developer unless production?
end
set :haml, { format: :html5, escape_html: true }
configure do
Mongoid.load!("config/mongoid.yml")
Mongo::Logger.level = Logger::FATAL
end
configure :production do
require 'newrelic_rpm'
require 'newrelic_moped'
raise StandardError.new("not found ENV['TWITTER_KEY']") unless ENV['TWITTER_KEY']
raise StandardError.new("not found ENV['TWITTER_SECRET']") unless ENV['TWITTER_SECRET']
end
helpers do
def current_user
@current_user ||= User.where(uid: session[:user_id]).first if session[:user_id]
end
def locales
['jp', 'us', 'ca', 'de', 'fr', 'uk', 'es', 'it', 'cn']
end
def forbidden?
client = Client.find_or_initialize_by(atag: params['AssociateTag'])
client.update_status
if client.status == Client::Status::ACTIVE
client.save if client.changed? and client.created_at
false
else
client.save if client.changed?
true
end
end
end
before do
content_type :html, 'charset' => 'utf-8'
end
before '/profile*' do
redirect '/' unless current_user
end
before '/proxy*' do
redirect '/' unless current_user
end
# ログアウト
get '/logout' do
session[:user_id] = nil
redirect '/'
end
# トップページ
get '/' do
haml :index
end
# ログイン処理
get '/auth/twitter/callback' do
auth = request.env['omniauth.auth']
@current_user = User.find_or_create_with_omniauth(auth)
session[:user_id] = @current_user.uid
request.logger.info "[INFO] @#{current_user.screen_name} logged in"
redirect '/profile'
end
# ログイン処理(開発用)
post '/auth/developer/callback' do
auth = request.env['omniauth.auth']
auth['uid'] = auth['info']['nickname'] = auth['info']['name']
request.logger.info request.env['omniauth.auth'].inspect
@current_user = User.find_or_create_with_omniauth(auth)
session[:user_id] = @current_user.uid
request.logger.info "[INFO] @#{current_user.screen_name} logged in"
redirect '/profile'
end
# ログイン後の画面
get '/profile' do
haml :profile
end
# プロフィール更新
put '/profile/:id' do
user = User.find(params[:id])
raise StandardError.new("error") unless current_user.id == user.id
user.name = params[:name]
user.url = params[:url]
if user.save
request.logger.info "[INFO] updated profile by @#{current_user.screen_name}"
else
request.logger.error "[ERROR] failed to update profile. #{user.errors.full_messages}"
end
redirect '/profile'
end
# プロキシ一覧
get '/proxies' do
@proxies = Proxy.all
haml :proxies
end
post '/proxy' do
# create a new proxy
# TODO: エラー処理
proxy = Proxy.new_with_yaml(params[:endpoint])
proxy.user = current_user
begin
if proxy.valid_endpoint? && proxy.save
request.logger.info "[INFO] added proxy by @#{current_user.screen_name}"
else
request.logger.error "[ERROR] failed to add proxy. #{proxy.errors.full_messages}"
end
rescue StandardError => e
request.logger.error "[ERROR] failed to add proxy. #{e.class}: #{e.message}"
end
redirect '/profile'
end
put '/proxy/:id' do
# update an existing proxy
proxy = Proxy.find(params[:id])
raise StandardError.new("error") unless current_user.id == proxy.user.id
proxy.name = params[:name]
# proxy.endpoint = params[:endpoint]
begin
if proxy.save
request.logger.info "[INFO] updated proxy by @#{current_user.screen_name}"
else
request.logger.error "[ERROR] failed to update proxy. #{proxy.errors.full_messages}"
end
rescue StandardError => e
request.logger.error "[ERROR] failed to update proxy. #{e.class}: #{e.message}"
end
redirect '/profile'
end
delete '/proxy/:id' do
proxy = Proxy.find(params[:id])
raise StandardError.new("error") unless current_user.id == proxy.user.id
proxy.destroy
request.logger.info "[INFO] deleted proxy by @#{current_user.screen_name}"
redirect '/profile'
end
# リバースプロキシ http://rpaproxy.heroku.com/rpaproxy/jp/
get %r{/rpaproxy/([\w]{2})/} do |locale|
# deny bot
if forbidden?
env['QUERY_STRING'] = request.params.reject{|k,v| k == 'AssociateTag' }.to_query
end
# FIXME: 全件取得しているのを最適化したい
proxies = Proxy.random(locale)
res = nil
proxies.each do |proxy|
start_time = Time.now
res = proxy.fetch(locale, request.query_string)
if res
Log.create(
atag: params['AssociateTag'],
locale: locale,
created_at: Time.now,
response: Time.now - start_time,
proxy: proxy,
success: true)
break
end
end
unless res
# TODO: トータルの失敗回数を増分
Log.create(
atag: params['AssociateTag'],
locale: locale,
created_at: Time.now,
success: false)
request.logger.error "[ERROR] failed to return response"
halt 503, "proxy unavailable"
end
redirect res['location'], 302
end
get '/stats' do
Stat.destroy_all
@stats = locales.map{|locale| Stat.create_by_logs(locale) }
haml :stats
end
get '/logs' do
redirect '/' unless current_user
@logs = Log.desc('$natural').limit(100).reverse
haml :logs
end
get '/users' do
redirect '/' unless current_user
@users = User.all.select{|user| user.proxies.size > 0 }
haml :users
end
get '/debug' do
raise StandardError.new('デバッグ')
end