putsreq 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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