putsreq 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -2
- data/app/controllers/application_controller.rb +46 -6
- data/app/controllers/buckets_controller.rb +3 -2
- data/app/controllers/requests_controller.rb +10 -0
- data/app/interactors/forward_request.rb +0 -1
- data/app/models/bucket.rb +1 -1
- data/app/models/request.rb +5 -5
- data/app/models/response.rb +0 -5
- data/app/views/buckets/_form.html.erb +2 -2
- data/app/views/buckets/_requests.html.erb +5 -4
- data/app/views/buckets/show.html.erb +2 -1
- data/app/views/home/index.html.erb +1 -1
- data/bin/putsreq +43 -19
- data/config/routes.rb +1 -0
- data/lib/putsreq/version.rb +1 -1
- data/spec/models/request_spec.rb +21 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d16ff759b8282f7cb2d4488a019d6631dac732a3
|
4
|
+
data.tar.gz: e7b1e5d40ac369a8a3060701343d772c092db96d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0ac7b3f2361a504d38e929713f4a438e4fcbee4aacd15016bac9c296733e8647fadf56d438b781c0799d086d4a20ae3626317de520dfbebcc3785e1a0b04764e
|
7
|
+
data.tar.gz: 094d545c5baca272fbd54c40d1fd13d53ebb0c06c11ebcc328b260d3ad83d99f8e7552bcd4d211e4d86deae8f12e525240852d337ef77771f6307f12a7fdff9a
|
data/README.md
CHANGED
@@ -113,12 +113,15 @@ request.forwardTo = 'http://example.com/api';
|
|
113
113
|
|
114
114
|
### CLI
|
115
115
|
|
116
|
-
Want to test
|
116
|
+
Want to test Webhook calls against your localhost? PutsReq makes it easy!
|
117
117
|
|
118
|
-
|
118
|
+
You can think of it, as a kind of [ngrok](http://ngrok.io), but instead of creating a tunnel to your localhost, PutsReq polls requests from `YOUR-PUTSREQ-TOKEN` and forwards to your localhost.
|
119
|
+
|
120
|
+
```bash
|
119
121
|
gem install putsreq
|
120
122
|
|
121
123
|
putsreq forward --to http://localhost:3000 --token YOUR-TOKEN
|
124
|
+
|
122
125
|
Listening requests from YOUR-TOKEN
|
123
126
|
Forwarding to http://localhost:3000
|
124
127
|
Press CTRL+c to terminate
|
@@ -3,19 +3,57 @@ class ApplicationController < ActionController::Base
|
|
3
3
|
# For APIs, you may want to use :null_session instead.
|
4
4
|
protect_from_forgery with: :exception
|
5
5
|
|
6
|
-
helper_method :
|
6
|
+
helper_method :owner?, :body_as_string, :headers_as_string
|
7
7
|
|
8
8
|
before_action :configure_permitted_parameters, if: :devise_controller?
|
9
9
|
|
10
10
|
protected
|
11
11
|
|
12
|
-
def
|
13
|
-
|
14
|
-
|
12
|
+
def body_as_string(req_or_res)
|
13
|
+
body = req_or_res.body
|
14
|
+
|
15
|
+
if body_json?(req_or_res) && body.is_a?(String)
|
16
|
+
# See https://github.com/phstc/putsreq/issues/31#issuecomment-271681249
|
17
|
+
return JSON.pretty_generate(JSON.parse(body))
|
18
|
+
end
|
19
|
+
|
20
|
+
if body.is_a?(Hash)
|
21
|
+
# For responses body can be a hash
|
22
|
+
# body.to_h because body can be a BSON::Document
|
23
|
+
# which for some reason does format well with
|
24
|
+
# pretty_generate
|
25
|
+
return JSON.pretty_generate(body.to_h)
|
26
|
+
end
|
27
|
+
|
28
|
+
if body.is_a?(Array)
|
29
|
+
# see https://github.com/phstc/putsreq/issues/33
|
30
|
+
return JSON.pretty_generate(body.to_a)
|
31
|
+
end
|
32
|
+
|
33
|
+
body.to_s
|
34
|
+
rescue
|
35
|
+
body.to_s
|
36
|
+
end
|
37
|
+
|
38
|
+
def headers_as_string(req_or_res)
|
39
|
+
JSON.pretty_generate(req_or_res.headers.to_h)
|
40
|
+
end
|
41
|
+
|
42
|
+
def body_json?(req_or_res)
|
43
|
+
req_or_res.headers.to_h.each do |key, value|
|
44
|
+
return !!(value =~ /application\/json/i) if key =~ /^content-type$/i
|
15
45
|
end
|
46
|
+
|
47
|
+
false
|
16
48
|
end
|
17
49
|
|
18
|
-
def
|
50
|
+
def check_ownership!
|
51
|
+
return if owner?(bucket)
|
52
|
+
|
53
|
+
redirect_to bucket_path(bucket.token), alert: 'Only the bucket owner can perform this operation'
|
54
|
+
end
|
55
|
+
|
56
|
+
def owner?(bucket)
|
19
57
|
owner_token == bucket.owner_token || (user_signed_in? && bucket.user == current_user)
|
20
58
|
end
|
21
59
|
|
@@ -30,6 +68,8 @@ class ApplicationController < ActionController::Base
|
|
30
68
|
def configure_permitted_parameters
|
31
69
|
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:name, :email, :password, :password_confirmation, :remember_me) }
|
32
70
|
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:name, :email, :password, :remember_me) }
|
33
|
-
devise_parameter_sanitizer.for(:account_update)
|
71
|
+
devise_parameter_sanitizer.for(:account_update) do |u|
|
72
|
+
u.permit(:name, :email, :password, :password_confirmation, :current_password)
|
73
|
+
end
|
34
74
|
end
|
35
75
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class BucketsController < ApplicationController
|
2
2
|
skip_before_action :verify_authenticity_token, only: :record
|
3
3
|
|
4
|
-
before_filter :check_ownership!, only: %i
|
4
|
+
before_filter :check_ownership!, only: %i(clear destroy update)
|
5
5
|
|
6
6
|
def create
|
7
7
|
new_bucket = { owner_token: owner_token }
|
@@ -70,7 +70,8 @@ class BucketsController < ApplicationController
|
|
70
70
|
|
71
71
|
response.headers.merge! recorded_response.headers.to_h
|
72
72
|
|
73
|
-
render text: recorded_response
|
73
|
+
render text: body_as_string(recorded_response),
|
74
|
+
status: recorded_response.status
|
74
75
|
end
|
75
76
|
|
76
77
|
private
|
data/app/models/bucket.rb
CHANGED
data/app/models/request.rb
CHANGED
@@ -20,12 +20,12 @@ class Request
|
|
20
20
|
|
21
21
|
after_create :bump_requests_recorded
|
22
22
|
|
23
|
-
def
|
24
|
-
|
25
|
-
|
23
|
+
def path
|
24
|
+
return unless url
|
25
|
+
|
26
|
+
u = URI(url)
|
26
27
|
|
27
|
-
|
28
|
-
JSON.pretty_generate(headers.to_h)
|
28
|
+
url.gsub(/.*#{Regexp.escape(u.host)}(\:#{Regexp.escape(u.port.to_s)})?/, '')
|
29
29
|
end
|
30
30
|
|
31
31
|
private
|
data/app/models/response.rb
CHANGED
@@ -9,14 +9,9 @@ class Response
|
|
9
9
|
field :headers, type: Hash, default: { 'Content-Type' => 'text/plain' }
|
10
10
|
field :status, type: Integer, default: 200
|
11
11
|
|
12
|
-
# index created_at: 1, options { expireAfterSeconds: 604800 }
|
13
12
|
index bucket_id: 1, created_at: -1
|
14
13
|
index request_id: 1
|
15
14
|
|
16
15
|
validates :bucket, presence: true
|
17
16
|
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
17
|
end
|
@@ -24,10 +24,10 @@
|
|
24
24
|
<div id="editor" name="editor" style="width: 100%; height: 150px"></div>
|
25
25
|
<textarea id="response_builder" name="response_builder" style="display:none;"></textarea>
|
26
26
|
<p>
|
27
|
-
<% if
|
27
|
+
<% if owner?(@bucket) %>
|
28
28
|
<%= render 'buttons' %>
|
29
29
|
<% else %>
|
30
30
|
<%= render 'readonly_buttons' %>
|
31
31
|
<% end %>
|
32
32
|
</p>
|
33
|
-
<% end %>
|
33
|
+
<% end %>
|
@@ -1,3 +1,4 @@
|
|
1
|
+
<!-- request id: <%= recorded_request.id %> -->
|
1
2
|
<div class="panel-group request-show" id="accordion" role="tablist" aria-multiselectable="true">
|
2
3
|
<div class="panel panel-default">
|
3
4
|
<span class="pull-right label label-info" title="<%= recorded_request.created_at.utc %>"><%= time_ago_in_words recorded_request.created_at %> ago</span>
|
@@ -10,7 +11,7 @@
|
|
10
11
|
</div>
|
11
12
|
<div id="collapseOne" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne">
|
12
13
|
<div class="panel-body">
|
13
|
-
<pre><%=
|
14
|
+
<pre><%= headers_as_string(recorded_request) %></pre>
|
14
15
|
</div>
|
15
16
|
</div>
|
16
17
|
</div>
|
@@ -18,13 +19,13 @@
|
|
18
19
|
<div class="panel-heading" role="tab" id="headingTwo">
|
19
20
|
<h4 class="panel-title">
|
20
21
|
<a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseTwo" aria-expanded="true" aria-controls="collapseTwo">
|
21
|
-
|
22
|
+
<%= recorded_request.request_method.upcase %> <%= recorded_request.path %>
|
22
23
|
</a>
|
23
24
|
</h4>
|
24
25
|
</div>
|
25
26
|
<div id="collapseTwo" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingTwo">
|
26
27
|
<div class="panel-body">
|
27
|
-
<pre><%=
|
28
|
+
<pre><%= body_as_string(recorded_request) %></pre>
|
28
29
|
</div>
|
29
30
|
</div>
|
30
31
|
</div>
|
@@ -38,7 +39,7 @@
|
|
38
39
|
</div>
|
39
40
|
<div id="collapseThree" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingThree">
|
40
41
|
<div class="panel-body">
|
41
|
-
<pre><%=
|
42
|
+
<pre><%= body_as_string(recorded_request.response) %></pre>
|
42
43
|
</div>
|
43
44
|
</div>
|
44
45
|
</div>
|
@@ -43,8 +43,9 @@
|
|
43
43
|
<em>First request at: <%= @bucket.first_request_at %></br>
|
44
44
|
Last request at: <%= @bucket.last_request_at %></br>
|
45
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
|
46
|
+
From first to last: <%= distance_of_time_in_words @bucket.first_request_at, @bucket.last_request_at, include_seconds: true %></br>
|
47
47
|
<% end %>
|
48
|
+
Request ID: <%= link_to @requests.first.id, request_path(id: @requests.first.id, format: :json) %>
|
48
49
|
</em>
|
49
50
|
</p>
|
50
51
|
<% end %>
|
@@ -32,7 +32,7 @@
|
|
32
32
|
<h4 class="tm20">Fake responses</h4>
|
33
33
|
<p>PutsReq is the easiest way to fake HTTP responses. You can define the response status, headers and body you want using <a href="https://github.com/phstc/putsreq#response-builder">JavaScript</a>.
|
34
34
|
<h4 class="tm20">Forward requests</h4>
|
35
|
-
<p>You can easily <a href="https://github.com/phstc/putsreq#forwardto">forward requests to another URL</a>, including <a href="https://github.com/phstc/putsreq#
|
35
|
+
<p>You can easily <a href="https://github.com/phstc/putsreq#forwardto">forward requests to another URL</a>, including <a href="https://github.com/phstc/putsreq#cli">localhost</a>.
|
36
36
|
</section>
|
37
37
|
</div>
|
38
38
|
</div>
|
data/bin/putsreq
CHANGED
@@ -22,33 +22,42 @@ class PutsReqCLI < Thor
|
|
22
22
|
|
23
23
|
p
|
24
24
|
end
|
25
|
-
end
|
26
25
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
trap('SIGINT', 'EXIT')
|
26
|
+
def subscribe_and_forward(token, to)
|
27
|
+
puts "Listening requests from #{token}"
|
28
|
+
puts "Forwarding to #{to}"
|
29
|
+
puts 'Press CTRL+c to terminate'
|
32
30
|
|
33
|
-
|
34
|
-
|
31
|
+
PusherClient.logger.level = Logger::ERROR
|
32
|
+
|
33
|
+
options = { secure: true }
|
34
|
+
|
35
|
+
socket = PusherClient::Socket.new('3466d56fe2ef1fdd2943', options)
|
35
36
|
|
36
|
-
|
37
|
-
puts "Forwarding to #{to}"
|
38
|
-
puts "Press CTRL+c to terminate"
|
37
|
+
channel = "channel_requests_#{token}"
|
39
38
|
|
40
|
-
|
39
|
+
socket.subscribe(channel)
|
41
40
|
|
42
|
-
|
41
|
+
socket[channel].bind('new') do |data|
|
42
|
+
last_request = JSON.parse(data)['request']
|
43
43
|
|
44
|
-
|
44
|
+
options = { headers: last_request['headers'] }
|
45
45
|
|
46
|
-
|
46
|
+
options[:body] = last_request['body'] unless last_request['body'].to_s.empty?
|
47
47
|
|
48
|
-
|
48
|
+
forward_request = HTTParty.send(last_request['request_method'].downcase.to_sym,
|
49
|
+
to,
|
50
|
+
options)
|
49
51
|
|
50
|
-
|
51
|
-
|
52
|
+
puts "#{Time.now}\t#{last_request['request_method']}\t#{forward_request.code}"
|
53
|
+
end
|
54
|
+
|
55
|
+
socket.connect
|
56
|
+
end
|
57
|
+
|
58
|
+
def forward_request(token, to, id)
|
59
|
+
url = "http://putsreq.com/#{token}/requests/#{id}.json"
|
60
|
+
last_request = HTTParty.get(url)
|
52
61
|
|
53
62
|
options = { headers: last_request['headers'] }
|
54
63
|
|
@@ -60,8 +69,23 @@ class PutsReqCLI < Thor
|
|
60
69
|
|
61
70
|
puts "#{Time.now}\t#{last_request['request_method']}\t#{forward_request.code}"
|
62
71
|
end
|
72
|
+
end
|
73
|
+
|
74
|
+
desc 'forward', 'Forward requests from PutsReq to a given URL'
|
75
|
+
method_option :token, desc: 'PutsReq token', required: true
|
76
|
+
method_option :to, desc: 'destination URL', required: true
|
77
|
+
method_option :id, desc: 'ID to forward a single request', required: false
|
78
|
+
def forward
|
79
|
+
trap('SIGINT', 'EXIT')
|
80
|
+
|
81
|
+
token = parse_bucket_token(options[:token])
|
82
|
+
to = options[:to]
|
63
83
|
|
64
|
-
|
84
|
+
if id = options[:id]
|
85
|
+
forward_request(token, to, id)
|
86
|
+
else
|
87
|
+
subscribe_and_forward(token, to)
|
88
|
+
end
|
65
89
|
end
|
66
90
|
|
67
91
|
desc 'version', 'Show version'
|
data/config/routes.rb
CHANGED
@@ -6,6 +6,7 @@ PutsReq::Application.routes.draw do
|
|
6
6
|
post 'buckets' => 'buckets#create', as: :buckets
|
7
7
|
get ':token/inspect' => 'buckets#show', as: :bucket
|
8
8
|
get ':token/last' => 'buckets#last', as: :bucket_last
|
9
|
+
get ':token/requests/:id' => 'requests#show', as: :request
|
9
10
|
get ':token/last_response' => 'buckets#last_response', as: :bucket_last_response
|
10
11
|
put ':token/buckets' => 'buckets#update', as: :update_bucket
|
11
12
|
match ':token' => 'buckets#record', via: :all, as: :bucket_record
|
data/lib/putsreq/version.rb
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Request do
|
4
|
+
describe '#path' do
|
5
|
+
let(:path) { '/12345?name=test' }
|
6
|
+
|
7
|
+
it 'returns path' do
|
8
|
+
subject.url = "https://putsreq.com#{path}"
|
9
|
+
|
10
|
+
expect(subject.path).to eq path
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'when domain with port' do
|
14
|
+
it 'returns path' do
|
15
|
+
subject.url = "http://localhost:3000#{path}"
|
16
|
+
|
17
|
+
expect(subject.path).to eq path
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: putsreq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pablo Cantero
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-02-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -72,6 +72,7 @@ files:
|
|
72
72
|
- app/controllers/buckets_controller.rb
|
73
73
|
- app/controllers/concerns/.keep
|
74
74
|
- app/controllers/home_controller.rb
|
75
|
+
- app/controllers/requests_controller.rb
|
75
76
|
- app/helpers/application_helper.rb
|
76
77
|
- app/interactors/create_request.rb
|
77
78
|
- app/interactors/create_response.rb
|
@@ -161,6 +162,7 @@ files:
|
|
161
162
|
- spec/interactors/eval_response_builder_spec.rb
|
162
163
|
- spec/interactors/forward_request_spec.rb
|
163
164
|
- spec/models/bucket_spec.rb
|
165
|
+
- spec/models/request_spec.rb
|
164
166
|
- spec/models/user_spec.rb
|
165
167
|
- spec/spec_helper.rb
|
166
168
|
- vendor/assets/javascripts/.keep
|
@@ -307,5 +309,6 @@ test_files:
|
|
307
309
|
- spec/interactors/eval_response_builder_spec.rb
|
308
310
|
- spec/interactors/forward_request_spec.rb
|
309
311
|
- spec/models/bucket_spec.rb
|
312
|
+
- spec/models/request_spec.rb
|
310
313
|
- spec/models/user_spec.rb
|
311
314
|
- spec/spec_helper.rb
|