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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1d06503d7f311af6ea6889c942724186869f9f40
4
- data.tar.gz: 35f4b09443af29f865ab6b27492aa3f98d6a5b07
3
+ metadata.gz: d16ff759b8282f7cb2d4488a019d6631dac732a3
4
+ data.tar.gz: e7b1e5d40ac369a8a3060701343d772c092db96d
5
5
  SHA512:
6
- metadata.gz: 32c23e0ad1396408aa4353a32b402a1dabd145e2069354a51fc91742aef9f9257f4fb79042f6a57e274136fbfdea64776f2cc68acce25c7f8a8955451437b4f7
7
- data.tar.gz: 43c51f6fc3337fa44e126c265564d9af1d208489aeb6cbe83ad2b7ce937ee27158d36bc45d7917abc2136f3277ae33747d07a570863999df261e7f50eefbc0ea
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 a Webhook calls against your localhost? PutsReq makes it easy!
116
+ Want to test Webhook calls against your localhost? PutsReq makes it easy!
117
117
 
118
- ```shell
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 :is_owner?
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 check_ownership!
13
- unless is_owner?(bucket)
14
- redirect_to bucket_path(bucket.token), alert: 'Only the bucket owner can perform this operation'
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 is_owner?(bucket)
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) { |u| u.permit(:name, :email, :password, :password_confirmation, :current_password) }
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[clear destroy update]
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.body_as_string, status: recorded_response.status
73
+ render text: body_as_string(recorded_response),
74
+ status: recorded_response.status
74
75
  end
75
76
 
76
77
  private
@@ -0,0 +1,10 @@
1
+ class RequestsController < ApplicationController
2
+ def show
3
+ request = Request.find(params[:id])
4
+
5
+ respond_to do |format|
6
+ format.html { render text: request.body }
7
+ format.json { render json: JSON.pretty_generate(request.attributes) }
8
+ end
9
+ end
10
+ end
@@ -17,7 +17,6 @@ class ForwardRequest
17
17
  private
18
18
 
19
19
  def forward_to(built_request, forward_url)
20
-
21
20
  options = { timeout: 5,
22
21
  headers: built_request['headers'],
23
22
  body: body }
@@ -17,7 +17,7 @@ class Bucket
17
17
  index owner_token: 1
18
18
  index fork_id: 1
19
19
 
20
- index({ updated_at: 1 }, { expire_after_seconds: 1.month })
20
+ index({ updated_at: 1 }, expire_after_seconds: 1.month)
21
21
 
22
22
  before_create :generate_token
23
23
 
@@ -20,12 +20,12 @@ class Request
20
20
 
21
21
  after_create :bump_requests_recorded
22
22
 
23
- def body_as_string
24
- body.is_a?(Hash) ? JSON.pretty_generate(body) : body.to_s
25
- end
23
+ def path
24
+ return unless url
25
+
26
+ u = URI(url)
26
27
 
27
- def headers_as_string
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
@@ -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 is_owner?(@bucket) %>
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><%= simple_format recorded_request.headers_as_string %></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
- Request
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><%= h recorded_request.body_as_string %></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><%= h recorded_request.response.body_as_string %></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#CLI">localhost</a>.
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>
@@ -22,33 +22,42 @@ class PutsReqCLI < Thor
22
22
 
23
23
  p
24
24
  end
25
- end
26
25
 
27
- desc 'forward', 'Forward requests from PutsReq to a given URL'
28
- method_option :token, desc: 'PutsReq token', required: true
29
- method_option :to, desc: 'destination URL', required: true
30
- def forward
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
- token = parse_bucket_token(options[:token])
34
- to = options[:to]
31
+ PusherClient.logger.level = Logger::ERROR
32
+
33
+ options = { secure: true }
34
+
35
+ socket = PusherClient::Socket.new('3466d56fe2ef1fdd2943', options)
35
36
 
36
- puts "Listening requests from #{token}"
37
- puts "Forwarding to #{to}"
38
- puts "Press CTRL+c to terminate"
37
+ channel = "channel_requests_#{token}"
39
38
 
40
- PusherClient.logger.level = Logger::ERROR
39
+ socket.subscribe(channel)
41
40
 
42
- options = { secure: true }
41
+ socket[channel].bind('new') do |data|
42
+ last_request = JSON.parse(data)['request']
43
43
 
44
- socket = PusherClient::Socket.new('3466d56fe2ef1fdd2943', options)
44
+ options = { headers: last_request['headers'] }
45
45
 
46
- channel = "channel_requests_#{token}"
46
+ options[:body] = last_request['body'] unless last_request['body'].to_s.empty?
47
47
 
48
- socket.subscribe(channel)
48
+ forward_request = HTTParty.send(last_request['request_method'].downcase.to_sym,
49
+ to,
50
+ options)
49
51
 
50
- socket[channel].bind('new') do |data|
51
- last_request = JSON.parse(data)['request']
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
- socket.connect
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'
@@ -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
@@ -1,3 +1,3 @@
1
1
  module PutsReq
2
- VERSION = '0.0.2'.freeze
2
+ VERSION = '0.0.3'.freeze
3
3
  end
@@ -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.2
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: 2016-12-21 00:00:00.000000000 Z
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