putsreq 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeclimate.yml +7 -0
- data/.coffeelint.json +5 -0
- data/.gitignore +20 -0
- data/.hound.yml +14 -0
- data/.jshintrc +3 -0
- data/.rspec +3 -0
- data/.rubocop.yml +110 -0
- data/.ruby-version +1 -0
- data/.travis.yml +18 -0
- data/Gemfile +91 -0
- data/Gemfile.lock +270 -0
- data/LICENSE +5 -0
- data/Procfile +1 -0
- data/README.md +147 -0
- data/Rakefile +8 -0
- data/app/assets/javascripts/application.js +27 -0
- data/app/assets/javascripts/buckets.js.coffee +68 -0
- data/app/assets/javascripts/initializers.js.coffee +8 -0
- data/app/assets/stylesheets/application.css +15 -0
- data/app/assets/stylesheets/base.css +68 -0
- data/app/assets/stylesheets/buckets.css.scss +91 -0
- data/app/assets/stylesheets/helpers.css +154 -0
- data/app/controllers/application_controller.rb +35 -0
- data/app/controllers/buckets_controller.rb +88 -0
- data/app/controllers/concerns/.keep +0 -0
- data/app/controllers/home_controller.rb +18 -0
- data/app/helpers/application_helper.rb +14 -0
- data/app/interactors/create_request.rb +15 -0
- data/app/interactors/create_response.rb +11 -0
- data/app/interactors/eval_response_builder.rb +55 -0
- data/app/interactors/filter_headers.rb +28 -0
- data/app/interactors/forward_request.rb +39 -0
- data/app/interactors/notify_count.rb +15 -0
- data/app/interactors/record_request.rb +5 -0
- data/app/mailers/.keep +0 -0
- data/app/models/.keep +0 -0
- data/app/models/bucket.rb +99 -0
- data/app/models/concerns/.keep +0 -0
- data/app/models/request.rb +36 -0
- data/app/models/response.rb +22 -0
- data/app/models/user.rb +42 -0
- data/app/views/buckets/_buttons.html.erb +4 -0
- data/app/views/buckets/_form.html.erb +33 -0
- data/app/views/buckets/_readonly_buttons.html.erb +1 -0
- data/app/views/buckets/_requests.html.erb +45 -0
- data/app/views/buckets/show.html.erb +58 -0
- data/app/views/home/index.html.erb +45 -0
- data/app/views/layouts/_header.html.erb +18 -0
- data/app/views/layouts/application.html.erb +28 -0
- data/app/views/layouts/devise.html.erb +22 -0
- data/app/views/shared/_flash.html.erb +10 -0
- data/app/views/users/confirmations/new.html.erb +12 -0
- data/app/views/users/mailer/confirmation_instructions.html.erb +5 -0
- data/app/views/users/mailer/reset_password_instructions.html.erb +8 -0
- data/app/views/users/mailer/unlock_instructions.html.erb +7 -0
- data/app/views/users/passwords/edit.html.erb +32 -0
- data/app/views/users/passwords/new.html.erb +23 -0
- data/app/views/users/registrations/edit.html.erb +59 -0
- data/app/views/users/registrations/new.html.erb +46 -0
- data/app/views/users/sessions/new.html.erb +38 -0
- data/app/views/users/shared/_links.erb +25 -0
- data/app/views/users/unlocks/new.html.erb +12 -0
- data/bin/bundle +3 -0
- data/bin/putsreq +71 -0
- data/bin/rails +4 -0
- data/bin/rake +4 -0
- data/bin/rspec +16 -0
- data/config.ru +4 -0
- data/config/application.rb +42 -0
- data/config/boot.rb +4 -0
- data/config/environment.rb +5 -0
- data/config/environments/development.rb +33 -0
- data/config/environments/production.rb +82 -0
- data/config/environments/test.rb +36 -0
- data/config/initializers/backtrace_silencers.rb +7 -0
- data/config/initializers/devise.rb +256 -0
- data/config/initializers/filter_parameter_logging.rb +4 -0
- data/config/initializers/inflections.rb +16 -0
- data/config/initializers/mime_types.rb +5 -0
- data/config/initializers/redis.rb +17 -0
- data/config/initializers/secret_token.rb +12 -0
- data/config/initializers/session_store.rb +3 -0
- data/config/initializers/setup_email.rb +10 -0
- data/config/initializers/wrap_parameters.rb +14 -0
- data/config/locales/devise.en.yml +59 -0
- data/config/locales/en.yml +23 -0
- data/config/mongoid.yml +47 -0
- data/config/routes.rb +15 -0
- data/config/unicorn.rb +16 -0
- data/lib/assets/.keep +0 -0
- data/lib/putsreq/version.rb +3 -0
- data/lib/tasks/.keep +0 -0
- data/public/404.html +58 -0
- data/public/422.html +58 -0
- data/public/500.html +57 -0
- data/public/favicon.ico +0 -0
- data/public/images/.keep +0 -0
- data/public/images/favicon.png +0 -0
- data/public/images/favicon144.png +0 -0
- data/public/images/favicon152.png +0 -0
- data/public/images/glyphicons-halflings-white.png +0 -0
- data/public/images/glyphicons-halflings.png +0 -0
- data/public/images/logo.png +0 -0
- data/public/javascripts/vendor/ace/theme-monokai.js +1 -0
- data/public/javascripts/vendor/ace/theme-textmate.js +1 -0
- data/public/javascripts/vendor/ace/worker-javascript.js +1 -0
- data/public/javascripts/vendor/ace/worker-json.js +1 -0
- data/public/robots.txt +5 -0
- data/putsreq.gemspec +22 -0
- data/spec/controllers/buckets_controller_spec.rb +164 -0
- data/spec/interactors/create_request_spec.rb +34 -0
- data/spec/interactors/create_response_spec.rb +14 -0
- data/spec/interactors/eval_response_builder_spec.rb +63 -0
- data/spec/interactors/forward_request_spec.rb +39 -0
- data/spec/models/bucket_spec.rb +96 -0
- data/spec/models/user_spec.rb +5 -0
- data/spec/spec_helper.rb +66 -0
- data/vendor/assets/javascripts/.keep +0 -0
- data/vendor/assets/javascripts/ace/ace.js +10 -0
- data/vendor/assets/javascripts/ace/ext-searchbox.js +1 -0
- data/vendor/assets/javascripts/ace/ext-spellcheck.js +1 -0
- data/vendor/assets/javascripts/ace/ext-static_highlight.js +1 -0
- data/vendor/assets/javascripts/ace/ext-textarea.js +1 -0
- data/vendor/assets/javascripts/ace/keybinding-emacs.js +1 -0
- data/vendor/assets/javascripts/ace/keybinding-vim.js +1 -0
- data/vendor/assets/javascripts/ace/mode-abap.js +1 -0
- data/vendor/assets/javascripts/ace/mode-asciidoc.js +1 -0
- data/vendor/assets/javascripts/ace/mode-c9search.js +1 -0
- data/vendor/assets/javascripts/ace/mode-c_cpp.js +1 -0
- data/vendor/assets/javascripts/ace/mode-clojure.js +1 -0
- data/vendor/assets/javascripts/ace/mode-coffee.js +1 -0
- data/vendor/assets/javascripts/ace/mode-coldfusion.js +1 -0
- data/vendor/assets/javascripts/ace/mode-csharp.js +1 -0
- data/vendor/assets/javascripts/ace/mode-css.js +1 -0
- data/vendor/assets/javascripts/ace/mode-curly.js +1 -0
- data/vendor/assets/javascripts/ace/mode-dart.js +1 -0
- data/vendor/assets/javascripts/ace/mode-diff.js +1 -0
- data/vendor/assets/javascripts/ace/mode-django.js +1 -0
- data/vendor/assets/javascripts/ace/mode-dot.js +1 -0
- data/vendor/assets/javascripts/ace/mode-glsl.js +1 -0
- data/vendor/assets/javascripts/ace/mode-golang.js +1 -0
- data/vendor/assets/javascripts/ace/mode-groovy.js +1 -0
- data/vendor/assets/javascripts/ace/mode-haml.js +1 -0
- data/vendor/assets/javascripts/ace/mode-haxe.js +1 -0
- data/vendor/assets/javascripts/ace/mode-html.js +1 -0
- data/vendor/assets/javascripts/ace/mode-jade.js +1 -0
- data/vendor/assets/javascripts/ace/mode-java.js +1 -0
- data/vendor/assets/javascripts/ace/mode-javascript.js +1 -0
- data/vendor/assets/javascripts/ace/mode-json.js +1 -0
- data/vendor/assets/javascripts/ace/mode-jsp.js +1 -0
- data/vendor/assets/javascripts/ace/mode-jsx.js +1 -0
- data/vendor/assets/javascripts/ace/mode-latex.js +1 -0
- data/vendor/assets/javascripts/ace/mode-less.js +1 -0
- data/vendor/assets/javascripts/ace/mode-liquid.js +1 -0
- data/vendor/assets/javascripts/ace/mode-lisp.js +1 -0
- data/vendor/assets/javascripts/ace/mode-livescript.js +1 -0
- data/vendor/assets/javascripts/ace/mode-lua.js +1 -0
- data/vendor/assets/javascripts/ace/mode-luapage.js +1 -0
- data/vendor/assets/javascripts/ace/mode-lucene.js +1 -0
- data/vendor/assets/javascripts/ace/mode-makefile.js +1 -0
- data/vendor/assets/javascripts/ace/mode-markdown.js +1 -0
- data/vendor/assets/javascripts/ace/mode-objectivec.js +1 -0
- data/vendor/assets/javascripts/ace/mode-ocaml.js +1 -0
- data/vendor/assets/javascripts/ace/mode-perl.js +1 -0
- data/vendor/assets/javascripts/ace/mode-pgsql.js +1 -0
- data/vendor/assets/javascripts/ace/mode-php.js +1 -0
- data/vendor/assets/javascripts/ace/mode-powershell.js +1 -0
- data/vendor/assets/javascripts/ace/mode-python.js +1 -0
- data/vendor/assets/javascripts/ace/mode-r.js +1 -0
- data/vendor/assets/javascripts/ace/mode-rdoc.js +1 -0
- data/vendor/assets/javascripts/ace/mode-rhtml.js +1 -0
- data/vendor/assets/javascripts/ace/mode-ruby.js +1 -0
- data/vendor/assets/javascripts/ace/mode-scad.js +1 -0
- data/vendor/assets/javascripts/ace/mode-scala.js +1 -0
- data/vendor/assets/javascripts/ace/mode-scheme.js +1 -0
- data/vendor/assets/javascripts/ace/mode-scss.js +1 -0
- data/vendor/assets/javascripts/ace/mode-sh.js +1 -0
- data/vendor/assets/javascripts/ace/mode-sql.js +1 -0
- data/vendor/assets/javascripts/ace/mode-stylus.js +1 -0
- data/vendor/assets/javascripts/ace/mode-svg.js +1 -0
- data/vendor/assets/javascripts/ace/mode-tcl.js +1 -0
- data/vendor/assets/javascripts/ace/mode-tex.js +1 -0
- data/vendor/assets/javascripts/ace/mode-text.js +0 -0
- data/vendor/assets/javascripts/ace/mode-textile.js +1 -0
- data/vendor/assets/javascripts/ace/mode-tm_snippet.js +1 -0
- data/vendor/assets/javascripts/ace/mode-typescript.js +1 -0
- data/vendor/assets/javascripts/ace/mode-vbscript.js +1 -0
- data/vendor/assets/javascripts/ace/mode-xml.js +1 -0
- data/vendor/assets/javascripts/ace/mode-xquery.js +1 -0
- data/vendor/assets/javascripts/ace/mode-yaml.js +1 -0
- data/vendor/assets/javascripts/ace/theme-ambiance.js +1 -0
- data/vendor/assets/javascripts/ace/theme-chaos.js +1 -0
- data/vendor/assets/javascripts/ace/theme-chrome.js +1 -0
- data/vendor/assets/javascripts/ace/theme-clouds.js +1 -0
- data/vendor/assets/javascripts/ace/theme-clouds_midnight.js +1 -0
- data/vendor/assets/javascripts/ace/theme-cobalt.js +1 -0
- data/vendor/assets/javascripts/ace/theme-crimson_editor.js +1 -0
- data/vendor/assets/javascripts/ace/theme-dawn.js +1 -0
- data/vendor/assets/javascripts/ace/theme-dreamweaver.js +1 -0
- data/vendor/assets/javascripts/ace/theme-eclipse.js +1 -0
- data/vendor/assets/javascripts/ace/theme-github.js +1 -0
- data/vendor/assets/javascripts/ace/theme-idle_fingers.js +1 -0
- data/vendor/assets/javascripts/ace/theme-kr.js +1 -0
- data/vendor/assets/javascripts/ace/theme-merbivore.js +1 -0
- data/vendor/assets/javascripts/ace/theme-merbivore_soft.js +1 -0
- data/vendor/assets/javascripts/ace/theme-mono_industrial.js +1 -0
- data/vendor/assets/javascripts/ace/theme-monokai.js +1 -0
- data/vendor/assets/javascripts/ace/theme-pastel_on_dark.js +1 -0
- data/vendor/assets/javascripts/ace/theme-solarized_dark.js +1 -0
- data/vendor/assets/javascripts/ace/theme-solarized_light.js +1 -0
- data/vendor/assets/javascripts/ace/theme-textmate.js +1 -0
- data/vendor/assets/javascripts/ace/theme-tomorrow.js +1 -0
- data/vendor/assets/javascripts/ace/theme-tomorrow_night.js +1 -0
- data/vendor/assets/javascripts/ace/theme-tomorrow_night_blue.js +1 -0
- data/vendor/assets/javascripts/ace/theme-tomorrow_night_bright.js +1 -0
- data/vendor/assets/javascripts/ace/theme-tomorrow_night_eighties.js +1 -0
- data/vendor/assets/javascripts/ace/theme-twilight.js +1 -0
- data/vendor/assets/javascripts/ace/theme-vibrant_ink.js +1 -0
- data/vendor/assets/javascripts/ace/theme-xcode.js +1 -0
- data/vendor/assets/javascripts/ace/worker-coffee.js +1 -0
- data/vendor/assets/javascripts/ace/worker-css.js +1 -0
- data/vendor/assets/javascripts/ace/worker-javascript.js +1 -0
- data/vendor/assets/javascripts/ace/worker-json.js +1 -0
- data/vendor/assets/javascripts/ace/worker-php.js +1 -0
- data/vendor/assets/javascripts/ace/worker-xquery.js +1 -0
- data/vendor/assets/javascripts/jquery.tipsy.js +198 -0
- data/vendor/assets/javascripts/mode-javascript.js +1 -0
- data/vendor/assets/javascripts/theme-monokai.js +1 -0
- data/vendor/assets/javascripts/worker-javascript.js +1 -0
- data/vendor/assets/stylesheets/.keep +0 -0
- data/vendor/assets/stylesheets/tipsy.css +25 -0
- metadata +311 -0
@@ -0,0 +1,15 @@
|
|
1
|
+
class NotifyCount
|
2
|
+
include Interactor
|
3
|
+
|
4
|
+
delegate :bucket, :built_request, to: :context
|
5
|
+
|
6
|
+
def call
|
7
|
+
return unless ENV['PUSHER_URL']
|
8
|
+
|
9
|
+
Pusher["channel_requests_#{bucket.token}"].trigger('new',
|
10
|
+
count: bucket.requests_count,
|
11
|
+
request: built_request)
|
12
|
+
rescue => e
|
13
|
+
Rails.logger.error(e)
|
14
|
+
end
|
15
|
+
end
|
data/app/mailers/.keep
ADDED
File without changes
|
data/app/models/.keep
ADDED
File without changes
|
@@ -0,0 +1,99 @@
|
|
1
|
+
class Bucket
|
2
|
+
include Mongoid::Document
|
3
|
+
include Mongoid::Timestamps
|
4
|
+
|
5
|
+
has_many :forks, class_name: 'Bucket'
|
6
|
+
|
7
|
+
belongs_to :fork, class_name: 'Bucket'
|
8
|
+
belongs_to :user
|
9
|
+
|
10
|
+
field :token
|
11
|
+
field :name
|
12
|
+
field :owner_token
|
13
|
+
field :response_builder, default: -> { default_response_builder }
|
14
|
+
field :history_start_at, type: Time
|
15
|
+
|
16
|
+
index token: 1
|
17
|
+
index owner_token: 1
|
18
|
+
index fork_id: 1
|
19
|
+
|
20
|
+
index({ updated_at: 1 }, { expire_after_seconds: 1.month })
|
21
|
+
|
22
|
+
before_create :generate_token
|
23
|
+
|
24
|
+
def requests
|
25
|
+
# I couldn't make has_many + conditions work with Mongoid
|
26
|
+
# requests must be filtered by created_at
|
27
|
+
# see clear_history
|
28
|
+
|
29
|
+
Request.where(bucket_id: id).gte(created_at: history_start_at || created_at).order(:created_at.desc)
|
30
|
+
end
|
31
|
+
|
32
|
+
def responses
|
33
|
+
# I couldn't make has_many + conditions work with Mongoid
|
34
|
+
# responses must be filtered by created_at
|
35
|
+
# see clear_history
|
36
|
+
Response.where(bucket_id: id).gte(created_at: history_start_at || created_at).order(:created_at.desc)
|
37
|
+
end
|
38
|
+
|
39
|
+
def clear_history
|
40
|
+
# requests and responses are capped collections in production, we cannot delete docs on a capped collection
|
41
|
+
# so we filter these objects by the history_start_at to "clear"
|
42
|
+
# db.runCommand({ "convertToCapped": "requests", size: 25000000 });
|
43
|
+
# db.runCommand({ "convertToCapped": "responses", size: 25000000 });
|
44
|
+
update_attribute :history_start_at, Time.now
|
45
|
+
end
|
46
|
+
|
47
|
+
def name
|
48
|
+
if (name = read_attribute(:name)).blank?
|
49
|
+
token
|
50
|
+
else
|
51
|
+
name
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def last_request
|
56
|
+
requests.order(:created_at.desc).first
|
57
|
+
end
|
58
|
+
|
59
|
+
def last_response
|
60
|
+
responses.order(:created_at.desc).first
|
61
|
+
end
|
62
|
+
|
63
|
+
def last_request_at
|
64
|
+
last_request.try(:created_at)
|
65
|
+
end
|
66
|
+
|
67
|
+
def first_request_at
|
68
|
+
requests.order(:created_at.asc).first.try(:created_at)
|
69
|
+
end
|
70
|
+
|
71
|
+
def requests_count
|
72
|
+
requests.count
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def generate_token
|
78
|
+
self.token = loop do
|
79
|
+
random_token = SecureRandom.urlsafe_base64(15).tr('_-', '0a')
|
80
|
+
break random_token unless Bucket.where(token: random_token).exists?
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def default_response_builder
|
85
|
+
<<-DEFAULT.strip_heredoc
|
86
|
+
// Build a response
|
87
|
+
var msg = 'Hello World';
|
88
|
+
|
89
|
+
if(request.params.name) {
|
90
|
+
msg = 'Hello ' + request.params.name;
|
91
|
+
}
|
92
|
+
|
93
|
+
response.body = msg;
|
94
|
+
|
95
|
+
// Forward a request
|
96
|
+
// request.forwardTo = 'http://example.com/api';
|
97
|
+
DEFAULT
|
98
|
+
end
|
99
|
+
end
|
File without changes
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class Request
|
2
|
+
include Mongoid::Document
|
3
|
+
include Mongoid::Timestamps
|
4
|
+
|
5
|
+
belongs_to :bucket, touch: true
|
6
|
+
|
7
|
+
has_one :response, dependent: :delete
|
8
|
+
|
9
|
+
field :body
|
10
|
+
field :headers, type: Hash
|
11
|
+
field :content_length
|
12
|
+
field :request_method
|
13
|
+
field :ip
|
14
|
+
field :url
|
15
|
+
field :params, type: Hash
|
16
|
+
|
17
|
+
index bucket_id: 1, created_at: -1
|
18
|
+
|
19
|
+
validates :bucket, presence: true
|
20
|
+
|
21
|
+
after_create :bump_requests_recorded
|
22
|
+
|
23
|
+
def body_as_string
|
24
|
+
body.is_a?(Hash) ? JSON.pretty_generate(body) : body.to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
def headers_as_string
|
28
|
+
JSON.pretty_generate(headers.to_h)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def bump_requests_recorded
|
34
|
+
REDIS.incr 'requests_recorded'
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Response
|
2
|
+
include Mongoid::Document
|
3
|
+
include Mongoid::Timestamps
|
4
|
+
|
5
|
+
belongs_to :bucket
|
6
|
+
belongs_to :request
|
7
|
+
|
8
|
+
field :body, default: 'ok'
|
9
|
+
field :headers, type: Hash, default: { 'Content-Type' => 'text/plain' }
|
10
|
+
field :status, type: Integer, default: 200
|
11
|
+
|
12
|
+
# index created_at: 1, options { expireAfterSeconds: 604800 }
|
13
|
+
index bucket_id: 1, created_at: -1
|
14
|
+
index request_id: 1
|
15
|
+
|
16
|
+
validates :bucket, presence: true
|
17
|
+
validates :request, presence: true
|
18
|
+
|
19
|
+
def body_as_string
|
20
|
+
body.is_a?(Hash) ? JSON.pretty_generate(body) : body.to_s
|
21
|
+
end
|
22
|
+
end
|
data/app/models/user.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
class User
|
2
|
+
include Mongoid::Document
|
3
|
+
# Include default devise modules. Others available are:
|
4
|
+
# :confirmable, :lockable, :timeoutable and :omniauthable
|
5
|
+
devise :database_authenticatable, :registerable,
|
6
|
+
:recoverable, :rememberable, :trackable, :validatable
|
7
|
+
|
8
|
+
## Database authenticatable
|
9
|
+
field :email, type: String, default: ""
|
10
|
+
field :encrypted_password, type: String, default: ""
|
11
|
+
|
12
|
+
## Recoverable
|
13
|
+
field :reset_password_token, type: String
|
14
|
+
field :reset_password_sent_at, type: Time
|
15
|
+
|
16
|
+
## Rememberable
|
17
|
+
field :remember_created_at, type: Time
|
18
|
+
|
19
|
+
## Trackable
|
20
|
+
field :sign_in_count, type: Integer, default: 0
|
21
|
+
field :current_sign_in_at, type: Time
|
22
|
+
field :last_sign_in_at, type: Time
|
23
|
+
field :current_sign_in_ip, type: String
|
24
|
+
field :last_sign_in_ip, type: String
|
25
|
+
|
26
|
+
## Confirmable
|
27
|
+
# field :confirmation_token, type: String
|
28
|
+
# field :confirmed_at, type: Time
|
29
|
+
# field :confirmation_sent_at, type: Time
|
30
|
+
# field :unconfirmed_email, type: String # Only if using reconfirmable
|
31
|
+
|
32
|
+
## Lockable
|
33
|
+
# field :failed_attempts, type: Integer, default: 0 # Only if lock strategy is :failed_attempts
|
34
|
+
# field :unlock_token, type: String # Only if unlock strategy is :email or :both
|
35
|
+
# field :locked_at, type: Time
|
36
|
+
|
37
|
+
has_many :users
|
38
|
+
|
39
|
+
field :name
|
40
|
+
|
41
|
+
validates :name, presence: true
|
42
|
+
end
|
@@ -0,0 +1,4 @@
|
|
1
|
+
<button class="btn btn-primary tm10">Update</button>
|
2
|
+
<%= link_to 'Fork', bucket_fork_path(@bucket.token), class: 'btn btn-default tm10 lm5', method: :post %>
|
3
|
+
<%= link_to 'Clear History', bucket_clear_path(@bucket.token), class: 'btn btn-default tm10 lm5', method: :delete, data: { confirm: 'Are you sure?' } %>
|
4
|
+
<%= link_to 'Destroy', bucket_destroy_path(@bucket.token), class: 'btn btn-default tm10 lm5', method: :delete, data: { confirm: 'Are you sure?' } %>
|
@@ -0,0 +1,33 @@
|
|
1
|
+
<%= form_for @bucket, url: update_bucket_path(@bucket.token), method: :put do |f| %>
|
2
|
+
<%= f.hidden_field :response_builder %>
|
3
|
+
<script id="response-builder-container" type='application/vns.putsreq-response_builder'><%== @bucket.response_builder %></script>
|
4
|
+
<div class="row">
|
5
|
+
<div class="col-md-6">
|
6
|
+
<h4>Bucket name
|
7
|
+
<small><em>You can change it anytime.</em></small>
|
8
|
+
</h4>
|
9
|
+
<div class="input-group putsreq-name bm30">
|
10
|
+
<%= f.text_field :name %>
|
11
|
+
<% if @bucket.fork %>
|
12
|
+
<p><small>forked from <%= link_to @bucket.fork.name, bucket_path(@bucket.fork.token) %></small></p>
|
13
|
+
<% end %>
|
14
|
+
</div>
|
15
|
+
</div>
|
16
|
+
<div class="col-md-6">
|
17
|
+
<h4>Requests
|
18
|
+
<small><em>The number of requests made to this bucket.</em></small>
|
19
|
+
</h4>
|
20
|
+
<h3 id="bucket-request-count"><%= @bucket.requests_count %></h3>
|
21
|
+
</div>
|
22
|
+
</div>
|
23
|
+
<h4>Response Builder <a href="https://github.com/phstc/putsreq#response-builder" target="_blank"><span class="glyphicon glyphicon-info-sign"></span></a></h4>
|
24
|
+
<div id="editor" name="editor" style="width: 100%; height: 150px"></div>
|
25
|
+
<textarea id="response_builder" name="response_builder" style="display:none;"></textarea>
|
26
|
+
<p>
|
27
|
+
<% if is_owner?(@bucket) %>
|
28
|
+
<%= render 'buttons' %>
|
29
|
+
<% else %>
|
30
|
+
<%= render 'readonly_buttons' %>
|
31
|
+
<% end %>
|
32
|
+
</p>
|
33
|
+
<% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= link_to 'Fork', bucket_fork_path(@bucket.token), class: 'btn btn-primary tm10', method: :post %>
|
@@ -0,0 +1,45 @@
|
|
1
|
+
<div class="panel-group request-show" id="accordion" role="tablist" aria-multiselectable="true">
|
2
|
+
<div class="panel panel-default">
|
3
|
+
<span class="pull-right label label-info" title="<%= recorded_request.created_at.utc %>"><%= time_ago_in_words recorded_request.created_at %> ago</span>
|
4
|
+
<div class="panel-heading" role="tab" id="headingOne">
|
5
|
+
<h4 class="panel-title">
|
6
|
+
<a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
|
7
|
+
Headers
|
8
|
+
</a>
|
9
|
+
</h4>
|
10
|
+
</div>
|
11
|
+
<div id="collapseOne" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne">
|
12
|
+
<div class="panel-body">
|
13
|
+
<pre><%= simple_format recorded_request.headers_as_string %></pre>
|
14
|
+
</div>
|
15
|
+
</div>
|
16
|
+
</div>
|
17
|
+
<div class="panel panel-default">
|
18
|
+
<div class="panel-heading" role="tab" id="headingTwo">
|
19
|
+
<h4 class="panel-title">
|
20
|
+
<a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseTwo" aria-expanded="true" aria-controls="collapseTwo">
|
21
|
+
Request
|
22
|
+
</a>
|
23
|
+
</h4>
|
24
|
+
</div>
|
25
|
+
<div id="collapseTwo" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingTwo">
|
26
|
+
<div class="panel-body">
|
27
|
+
<pre><%= h recorded_request.body_as_string %></pre>
|
28
|
+
</div>
|
29
|
+
</div>
|
30
|
+
</div>
|
31
|
+
<div class="panel panel-default">
|
32
|
+
<div class="panel-heading" role="tab" id="headingThree">
|
33
|
+
<h4 class="panel-title">
|
34
|
+
<a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseThree" aria-expanded="true" aria-controls="collapseThree">
|
35
|
+
Response
|
36
|
+
</a>
|
37
|
+
</h4>
|
38
|
+
</div>
|
39
|
+
<div id="collapseThree" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingThree">
|
40
|
+
<div class="panel-body">
|
41
|
+
<pre><%= h recorded_request.response.body_as_string %></pre>
|
42
|
+
</div>
|
43
|
+
</div>
|
44
|
+
</div>
|
45
|
+
</div>
|
@@ -0,0 +1,58 @@
|
|
1
|
+
<% content_for :title, @bucket.name %>
|
2
|
+
|
3
|
+
<ul class="nav">
|
4
|
+
<li class="logo"><a href="/"><%= image_tag 'logo.png' %></a></li>
|
5
|
+
<li><a href="<%= "/#{@bucket.token}/inspect" %>">Inspect</a></li>
|
6
|
+
<li><a href="<%= "/#{@bucket.token}/last" %>" title="JSON-formatted">Last Request</a></li>
|
7
|
+
<li><a href="<%= "/#{@bucket.token}/last_response" %>" title="JSON-formatted">Last Response</a></li>
|
8
|
+
<% if user_signed_in? %>
|
9
|
+
<li><%= link_to 'Sign out', destroy_user_session_path, method: :delete %></li>
|
10
|
+
<% else %>
|
11
|
+
<li><%= link_to 'Sign in', new_user_session_path %></li>
|
12
|
+
<li><%= link_to 'Sign up', new_user_registration_path %></li>
|
13
|
+
<% end %>
|
14
|
+
</ul>
|
15
|
+
|
16
|
+
<section class="putsreq-url-box">
|
17
|
+
<h3>Your PutsReq URL</h3>
|
18
|
+
<div class="input-group putsreq-url">
|
19
|
+
<input id="putsreq-url-input" data-bucket-token="<%= @bucket.token %>" type="text" value="<%= token_url(@bucket.token) %>" readonly="readonly"></input>
|
20
|
+
<span id="copy-button" class="input-group-addon hastip clipboard" data-clipboard-target="#putsreq-url-input">
|
21
|
+
<span class="glyphicon glyphicon-link hastip"></span>
|
22
|
+
</span>
|
23
|
+
</div>
|
24
|
+
</section>
|
25
|
+
|
26
|
+
<br/><br/>
|
27
|
+
|
28
|
+
<section>
|
29
|
+
<h4>Sample Request using cURL</h4>
|
30
|
+
<code>curl -i -X POST -d 'name=Pablo' <%= token_url(@bucket.token) %></code>
|
31
|
+
</section>
|
32
|
+
|
33
|
+
<hr/>
|
34
|
+
<%= render 'form' %>
|
35
|
+
<hr/>
|
36
|
+
|
37
|
+
<p id="new-requests-info"><!-- placeholder: New requests found. Load newer requests? --></p>
|
38
|
+
|
39
|
+
<div class="row">
|
40
|
+
<div class="col-md-6">
|
41
|
+
<% if @bucket.first_request_at %>
|
42
|
+
<p>
|
43
|
+
<em>First request at: <%= @bucket.first_request_at %></br>
|
44
|
+
Last request at: <%= @bucket.last_request_at %></br>
|
45
|
+
<% if @bucket.last_request_at - @bucket.first_request_at > 0 %>
|
46
|
+
From first to last: <%= distance_of_time_in_words @bucket.first_request_at, @bucket.last_request_at, include_seconds: true %>
|
47
|
+
<% end %>
|
48
|
+
</em>
|
49
|
+
</p>
|
50
|
+
<% end %>
|
51
|
+
</div>
|
52
|
+
<div class="col-md-6"></div>
|
53
|
+
</div>
|
54
|
+
<p><%= paginate @requests %></p>
|
55
|
+
<%= render(partial: 'requests', collection: @requests, as: :recorded_request) || show_no_requests_found(@bucket) %>
|
56
|
+
<p><%= paginate @requests %></p>
|
57
|
+
|
58
|
+
<script src="//js.pusher.com/2.2/pusher.min.js" type="text/javascript"></script>
|
@@ -0,0 +1,45 @@
|
|
1
|
+
<div class="row">
|
2
|
+
<div class="span10">
|
3
|
+
<div class="">
|
4
|
+
<header>
|
5
|
+
<%= image_tag 'logo.png' %>
|
6
|
+
<h3><em>PutsReq</em> lets you record HTTP requests and simulate responses like no other tool available. Try it now!</h3>
|
7
|
+
<%= form_for :bucket, url: buckets_path do |f| %>
|
8
|
+
<button class="btn btn-primary btn-large">Create a PutsReq</button>
|
9
|
+
<em>
|
10
|
+
<% if user_signed_in? %>
|
11
|
+
<%= link_to 'Sign out', destroy_user_session_path, method: :delete %>
|
12
|
+
<% else %>
|
13
|
+
<%= link_to 'Sign in', new_user_session_path %> | <%= link_to 'Sign up', new_user_registration_path %>
|
14
|
+
<% end %>
|
15
|
+
</em>
|
16
|
+
<% end %>
|
17
|
+
</header>
|
18
|
+
<section class="start">
|
19
|
+
<% if @buckets.any? %>
|
20
|
+
<div class="history">
|
21
|
+
<h4 class="bm0 tm0">History</h4>
|
22
|
+
<small>View and manage your buckets:</small>
|
23
|
+
<ul class="tm5">
|
24
|
+
<% @buckets.each do |bucket| %>
|
25
|
+
<li><%= link_to "#{bucket.name} (#{bucket.requests_count})", bucket_path(bucket.token) %></li>
|
26
|
+
<% end %>
|
27
|
+
</ul>
|
28
|
+
</div>
|
29
|
+
<% end %>
|
30
|
+
<h4>Record the requests sent or received</h4>
|
31
|
+
<p>Change your target URL to a PutsReq URL, then you will be able to inspect all headers and body being sent.
|
32
|
+
You can also debug callbacks from external services by configuring a PutsReq URL instead of your Webhook URL.</p>
|
33
|
+
<h4 class="tm20">Simulate responses</h4>
|
34
|
+
<p>PutsReq is the easiest way to simulate/stub HTTP responses. You can define the response status, headers and body with JavaScript using the <a href="https://github.com/phstc/putsreq#response-builder">Response Builder</a>.
|
35
|
+
If you don't want to test against the real API, but you know how to simulate (mock) the response, you can do that using a Response Builder.</p>
|
36
|
+
<p>Some use cases:</p>
|
37
|
+
<ul>
|
38
|
+
<li>Get the real response once then create a Response Builder simulating it and use PutsReq for the next calls.</li>
|
39
|
+
<li>Use PutsReq for your integration tests to verify if your application is making the HTTP requests as expected <a href="https://github.com/phstc/putsreq_integration_sample/blob/master/spec/acceptance/create_user_spec.rb">by checking the last recorded request</a>.</li>
|
40
|
+
<li>To benchmark by checking the First and Last request timestamps, or by checking the numbers of requests made within a period.</li>
|
41
|
+
</ul>
|
42
|
+
</section>
|
43
|
+
</div>
|
44
|
+
</div>
|
45
|
+
</div>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<title><%= content_for?(:title) ? yield(:title) : 'PutsReq' %></title>
|
2
|
+
|
3
|
+
<link rel="apple-touch-icon-precomposed" href="/images/favicon152.png" />
|
4
|
+
<link rel="icon" href="/images/favicon.png" />
|
5
|
+
<meta name="msapplication-TileColor" content="#ffffff" />
|
6
|
+
<meta name="msapplication-TileImage" content="/images/favicon144.png" />
|
7
|
+
<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
|
8
|
+
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
|
9
|
+
<%= csrf_meta_tags %>
|
10
|
+
<script>
|
11
|
+
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
12
|
+
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
13
|
+
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
14
|
+
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
15
|
+
|
16
|
+
ga('create', 'UA-50754009-1', 'auto');
|
17
|
+
ga('send', 'pageview');
|
18
|
+
</script>
|