putsreq 0.0.3 → 0.0.4
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 +5 -5
- data/.babelrc +26 -0
- data/.codeclimate.yml +29 -5
- data/.env.docker +6 -0
- data/.eslintignore +4 -0
- data/.eslintrc +22 -0
- data/.gitignore +8 -0
- data/.postcssrc.yml +3 -0
- data/.prettierrc +4 -0
- data/.reek +12 -0
- data/.rubocop.yml +47 -25
- data/.ruby-version +1 -1
- data/.simplecov +6 -0
- data/.travis.yml +38 -4
- data/Dockerfile +44 -0
- data/Gemfile +40 -61
- data/Gemfile.lock +294 -186
- data/Procfile +1 -1
- data/README.md +51 -46
- data/Rakefile +1 -1
- data/{public → app/assets}/images/logo.png +0 -0
- data/app/assets/javascripts/application.js +1 -1
- data/app/assets/javascripts/buckets.js.coffee +1 -21
- data/app/assets/stylesheets/{application.css → application.scss} +2 -1
- data/app/assets/stylesheets/buckets.css.scss +0 -2
- data/app/controllers/application_controller.rb +11 -9
- data/app/controllers/buckets_controller.rb +24 -18
- data/app/controllers/home_controller.rb +5 -5
- data/app/controllers/requests_controller.rb +13 -2
- data/app/helpers/application_helper.rb +6 -2
- data/app/interactors/create_or_retrieve_bucket.rb +17 -0
- data/app/interactors/create_request.rb +25 -7
- data/app/interactors/eval_response_builder.rb +9 -9
- data/app/interactors/filter_headers.rb +3 -3
- data/app/interactors/forward_request.rb +4 -4
- data/app/interactors/record_request.rb +1 -1
- data/app/interactors/track.rb +44 -0
- data/app/javascript/actionTypes.js +7 -0
- data/app/javascript/actions/index.js +64 -0
- data/app/javascript/components/Bucket.jsx +91 -0
- data/app/javascript/components/Pagination.jsx +67 -0
- data/app/javascript/components/RequestCount.jsx +21 -0
- data/app/javascript/components/request/Header.jsx +31 -0
- data/app/javascript/components/request/Response.jsx +28 -0
- data/app/javascript/components/request/index.jsx +47 -0
- data/app/javascript/packs/application.js +25 -0
- data/app/javascript/packs/hello_react.jsx +26 -0
- data/app/javascript/reducers/index.js +23 -0
- data/app/javascript/request_poller.js +19 -0
- data/app/javascript/store.js +9 -0
- data/app/models/bucket.rb +16 -10
- data/app/models/request.rb +2 -3
- data/app/models/user.rb +2 -2
- data/app/serializers/bucket_serializer.rb +11 -0
- data/app/serializers/request_serializer.rb +69 -0
- data/app/views/buckets/_buttons.html.erb +3 -3
- data/app/views/buckets/_form.html.erb +6 -6
- data/app/views/buckets/_readonly_buttons.html.erb +1 -1
- data/app/views/buckets/show.html.erb +12 -25
- data/app/views/home/index.html.erb +22 -16
- data/app/views/layouts/application.html.erb +21 -22
- data/app/views/layouts/devise.html.erb +16 -18
- data/app/views/shared/_flash.html.erb +3 -1
- data/bin/byebug +21 -0
- data/bin/cc-tddium-post-worker +21 -0
- data/bin/codeclimate-test-reporter +21 -0
- data/bin/coderay +21 -0
- data/bin/dotenv +21 -0
- data/bin/htmldiff +21 -0
- data/bin/httparty +21 -0
- data/bin/httpclient +21 -0
- data/bin/ldiff +21 -0
- data/bin/mongo_console +21 -0
- data/bin/nokogiri +21 -0
- data/bin/pry +21 -0
- data/bin/putsreq +18 -71
- data/bin/rackup +21 -0
- data/bin/rails +1 -1
- data/bin/ri +21 -0
- data/bin/rollbar-rails-runner +21 -0
- data/bin/rspec +10 -5
- data/bin/safe_yaml +21 -0
- data/bin/sass +21 -0
- data/bin/sass-convert +21 -0
- data/bin/scss +21 -0
- data/bin/sdoc +21 -0
- data/bin/sdoc-merge +21 -0
- data/bin/setup +38 -0
- data/bin/sprockets +21 -0
- data/bin/thor +21 -0
- data/bin/tilt +21 -0
- data/bin/unicorn +21 -0
- data/bin/unicorn_rails +21 -0
- data/bin/update +29 -0
- data/bin/webpack +15 -0
- data/bin/webpack-dev-server +15 -0
- data/bin/yarn +11 -0
- data/config/application.rb +6 -4
- data/config/boot.rb +1 -1
- data/config/environment.rb +1 -1
- data/config/environments/development.rb +7 -3
- data/config/environments/production.rb +5 -2
- data/config/environments/test.rb +3 -1
- data/config/initializers/devise.rb +2 -2
- data/config/initializers/rack_attack.rb +24 -0
- data/config/initializers/rollbar.rb +58 -0
- data/config/initializers/setup_email.rb +7 -7
- data/config/mongoid.yml +2 -2
- data/config/newrelic.yml +45 -0
- data/config/puma.rb +15 -0
- data/config/routes.rb +2 -0
- data/config/webpack/development.js +5 -0
- data/config/webpack/environment.js +3 -0
- data/config/webpack/production.js +5 -0
- data/config/webpack/test.js +5 -0
- data/config/webpacker.yml +70 -0
- data/docker-compose.yml +25 -0
- data/lib/putsreq/cli_helper.rb +114 -0
- data/lib/putsreq/version.rb +1 -1
- data/package.json +30 -0
- data/putsreq.gemspec +6 -7
- data/spec/controllers/buckets_controller_spec.rb +54 -46
- data/spec/interactors/create_or_retrieve_bucket_spec.rb +25 -0
- data/spec/interactors/create_request_spec.rb +11 -8
- data/spec/interactors/create_response_spec.rb +1 -1
- data/spec/interactors/eval_response_builder_spec.rb +14 -17
- data/spec/interactors/forward_request_spec.rb +4 -4
- data/spec/lib/putsreq/cli_helper_spec.rb +114 -0
- data/spec/models/bucket_spec.rb +3 -3
- data/spec/spec_helper.rb +25 -25
- data/yarn.lock +7043 -0
- metadata +85 -20
- data/.hound.yml +0 -14
- data/app/interactors/notify_count.rb +0 -15
- data/app/models/.keep +0 -0
- data/config/initializers/redis.rb +0 -17
- data/config/unicorn.rb +0 -16
- data/lib/assets/.keep +0 -0
- data/public/images/.keep +0 -0
- data/vendor/assets/javascripts/.keep +0 -0
- data/vendor/assets/stylesheets/.keep +0 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React, { Component } from 'react'
|
|
2
|
+
import { connect } from 'react-redux'
|
|
3
|
+
import PropTypes from 'prop-types'
|
|
4
|
+
|
|
5
|
+
export default class Header extends Component {
|
|
6
|
+
render() {
|
|
7
|
+
return (
|
|
8
|
+
<div className="panel panel-default">
|
|
9
|
+
<span className="pull-right label label-info" title={this.props.created_at}>{this.props.time_ago_in_words}</span>
|
|
10
|
+
<div className="panel-heading" role="tab" id="headingOne">
|
|
11
|
+
<h4 className="panel-title">
|
|
12
|
+
<a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
|
|
13
|
+
Headers
|
|
14
|
+
</a>
|
|
15
|
+
</h4>
|
|
16
|
+
</div>
|
|
17
|
+
<div id="collapseOne" className="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne">
|
|
18
|
+
<div className="panel-body">
|
|
19
|
+
<pre>{this.props.headers_as_string}</pre>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
Header.propTypes = {
|
|
28
|
+
created_at: PropTypes.string.isRequired,
|
|
29
|
+
time_ago_in_words: PropTypes.string.isRequired,
|
|
30
|
+
headers_as_string: PropTypes.string.isRequired
|
|
31
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React, { Component } from 'react'
|
|
2
|
+
import { connect } from 'react-redux'
|
|
3
|
+
import PropTypes from 'prop-types'
|
|
4
|
+
|
|
5
|
+
export default class Response extends Component {
|
|
6
|
+
render() {
|
|
7
|
+
return (
|
|
8
|
+
<div className="panel panel-default">
|
|
9
|
+
<div className="panel-heading" role="tab" id="headingThree">
|
|
10
|
+
<h4 className="panel-title">
|
|
11
|
+
<a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseThree" aria-expanded="true" aria-controls="collapseThree">
|
|
12
|
+
Response
|
|
13
|
+
</a>
|
|
14
|
+
</h4>
|
|
15
|
+
</div>
|
|
16
|
+
<div id="collapseThree" className="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingThree">
|
|
17
|
+
<div className="panel-body">
|
|
18
|
+
<pre>{this.props.response_body_as_string}</pre>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
Response.propTypes = {
|
|
27
|
+
response_body_as_string: PropTypes.string.isRequired
|
|
28
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import React, { Component } from 'react'
|
|
2
|
+
import { connect } from 'react-redux'
|
|
3
|
+
import Header from './Header'
|
|
4
|
+
import Response from './Response'
|
|
5
|
+
import PropTypes from 'prop-types'
|
|
6
|
+
|
|
7
|
+
export default class Request extends Component {
|
|
8
|
+
render() {
|
|
9
|
+
if(!this.props.id) {
|
|
10
|
+
return (
|
|
11
|
+
<p>No requests found</p>
|
|
12
|
+
)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<div className="panel-group request-show" id="accordion" role="tablist" aria-multiselectable="true">
|
|
17
|
+
<Header headers_as_string={this.props.headers_as_string} time_ago_in_words={this.props.time_ago_in_words} created_at={this.props.created_at} />
|
|
18
|
+
<div className="panel panel-default">
|
|
19
|
+
<div className="panel-heading" role="tab" id="headingTwo">
|
|
20
|
+
<h4 className="panel-title">
|
|
21
|
+
<a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseTwo" aria-expanded="true" aria-controls="collapseTwo">
|
|
22
|
+
{this.props.request_method} {this.props.path}
|
|
23
|
+
</a>
|
|
24
|
+
</h4>
|
|
25
|
+
</div>
|
|
26
|
+
<div id="collapseTwo" className="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingTwo">
|
|
27
|
+
<div className="panel-body">
|
|
28
|
+
<pre>{this.props.request_body_as_string}</pre>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
<Response response_body_as_string={this.props.response_body_as_string} />
|
|
33
|
+
</div>
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
Response.propTypes = {
|
|
39
|
+
request_method: PropTypes.string,
|
|
40
|
+
path: PropTypes.string,
|
|
41
|
+
request_body_as_string: PropTypes.string,
|
|
42
|
+
response_body_as_string: PropTypes.string,
|
|
43
|
+
created_at: PropTypes.string,
|
|
44
|
+
id: PropTypes.string,
|
|
45
|
+
time_ago_in_words: PropTypes.string,
|
|
46
|
+
headers_as_string: PropTypes.string
|
|
47
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import ReactDOM from 'react-dom'
|
|
3
|
+
import { Provider } from 'react-redux'
|
|
4
|
+
import store from '../store'
|
|
5
|
+
import Bucket from '../components/Bucket'
|
|
6
|
+
import RequestCount from '../components/RequestCount'
|
|
7
|
+
import startRequestPoller from '../request_poller'
|
|
8
|
+
|
|
9
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
10
|
+
ReactDOM.render(
|
|
11
|
+
<Provider store={store}>
|
|
12
|
+
<Bucket />
|
|
13
|
+
</Provider>,
|
|
14
|
+
document.getElementById('react-root')
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
ReactDOM.render(
|
|
18
|
+
<Provider store={store}>
|
|
19
|
+
<RequestCount />
|
|
20
|
+
</Provider>,
|
|
21
|
+
document.getElementById('request-count-react-root')
|
|
22
|
+
)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
$(() => startRequestPoller(store))
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Run this example by adding <%= javascript_pack_tag 'hello_react' %> to the head of your layout file,
|
|
2
|
+
// like app/views/layouts/application.html.erb. All it does is render <div>Hello React</div> at the bottom
|
|
3
|
+
// of the page.
|
|
4
|
+
|
|
5
|
+
import React from 'react'
|
|
6
|
+
import ReactDOM from 'react-dom'
|
|
7
|
+
import PropTypes from 'prop-types'
|
|
8
|
+
|
|
9
|
+
const Hello = props => (
|
|
10
|
+
<div>Hello {props.name}!</div>
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
Hello.defaultProps = {
|
|
14
|
+
name: 'David'
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
Hello.propTypes = {
|
|
18
|
+
name: PropTypes.string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
22
|
+
ReactDOM.render(
|
|
23
|
+
<Hello name="React" />,
|
|
24
|
+
document.body.appendChild(document.createElement('div')),
|
|
25
|
+
)
|
|
26
|
+
})
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { combineReducers } from 'redux'
|
|
2
|
+
import { bucketsActions } from '../actionTypes'
|
|
3
|
+
|
|
4
|
+
const bucket = (state = {}, action) => {
|
|
5
|
+
switch (action.type) {
|
|
6
|
+
case bucketsActions.populate:
|
|
7
|
+
return { ...action.bucket, loading: false, page: action.page }
|
|
8
|
+
case bucketsActions.loading:
|
|
9
|
+
return { ...state, loading: true }
|
|
10
|
+
case bucketsActions.updateRequestsCount:
|
|
11
|
+
return {
|
|
12
|
+
...state,
|
|
13
|
+
requests_count: action.requests_count,
|
|
14
|
+
page: action.page
|
|
15
|
+
}
|
|
16
|
+
default:
|
|
17
|
+
return state
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const rootReducer = combineReducers({ bucket })
|
|
22
|
+
|
|
23
|
+
export default rootReducer
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { updateRequestsCount } from './actions'
|
|
2
|
+
|
|
3
|
+
export default function startRequestPoller(store) {
|
|
4
|
+
const bucket = $('#putsreq-url-input').data('bucket-token')
|
|
5
|
+
|
|
6
|
+
const url = `/${bucket}/requests_count`
|
|
7
|
+
const poll = (previousRequestsCount = 0) => {
|
|
8
|
+
$.getJSON(url)
|
|
9
|
+
.done((data) => {
|
|
10
|
+
updateRequestsCount(data.requests_count)(store.dispatch, store.getState)
|
|
11
|
+
// use setTimeout instead of setInterval to ensure a new request will be made
|
|
12
|
+
// only when the previous one was completed
|
|
13
|
+
const timeout = previousRequestsCount == data.requests_count ? 5000 : 2500
|
|
14
|
+
setTimeout(() => { poll(data.requests_count) }, timeout)
|
|
15
|
+
})
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
poll()
|
|
19
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createStore, applyMiddleware } from 'redux'
|
|
2
|
+
import thunk from 'redux-thunk'
|
|
3
|
+
import { composeWithDevTools } from 'redux-devtools-extension'
|
|
4
|
+
import rootReducers from './reducers'
|
|
5
|
+
|
|
6
|
+
export default createStore(
|
|
7
|
+
rootReducers,
|
|
8
|
+
composeWithDevTools(applyMiddleware(thunk))
|
|
9
|
+
)
|
data/app/models/bucket.rb
CHANGED
|
@@ -4,8 +4,8 @@ class Bucket
|
|
|
4
4
|
|
|
5
5
|
has_many :forks, class_name: 'Bucket'
|
|
6
6
|
|
|
7
|
-
belongs_to :fork, class_name: 'Bucket'
|
|
8
|
-
belongs_to :user
|
|
7
|
+
belongs_to :fork, class_name: 'Bucket', optional: true
|
|
8
|
+
belongs_to :user, optional: true
|
|
9
9
|
|
|
10
10
|
field :token
|
|
11
11
|
field :name
|
|
@@ -13,6 +13,9 @@ class Bucket
|
|
|
13
13
|
field :response_builder, default: -> { default_response_builder }
|
|
14
14
|
field :history_start_at, type: Time
|
|
15
15
|
|
|
16
|
+
# temporally hack
|
|
17
|
+
attr_accessor :request
|
|
18
|
+
|
|
16
19
|
index token: 1
|
|
17
20
|
index owner_token: 1
|
|
18
21
|
index fork_id: 1
|
|
@@ -33,6 +36,7 @@ class Bucket
|
|
|
33
36
|
# I couldn't make has_many + conditions work with Mongoid
|
|
34
37
|
# responses must be filtered by created_at
|
|
35
38
|
# see clear_history
|
|
39
|
+
|
|
36
40
|
Response.where(bucket_id: id).gte(created_at: history_start_at || created_at).order(:created_at.desc)
|
|
37
41
|
end
|
|
38
42
|
|
|
@@ -41,11 +45,11 @@ class Bucket
|
|
|
41
45
|
# so we filter these objects by the history_start_at to "clear"
|
|
42
46
|
# db.runCommand({ "convertToCapped": "requests", size: 25000000 });
|
|
43
47
|
# db.runCommand({ "convertToCapped": "responses", size: 25000000 });
|
|
44
|
-
update_attribute :history_start_at, Time.now
|
|
48
|
+
update_attribute :history_start_at, Time.zone.now
|
|
45
49
|
end
|
|
46
50
|
|
|
47
51
|
def name
|
|
48
|
-
if (name =
|
|
52
|
+
if (name = self[:name]).blank?
|
|
49
53
|
token
|
|
50
54
|
else
|
|
51
55
|
name
|
|
@@ -61,21 +65,23 @@ class Bucket
|
|
|
61
65
|
end
|
|
62
66
|
|
|
63
67
|
def last_request_at
|
|
64
|
-
last_request
|
|
68
|
+
last_request&.created_at
|
|
65
69
|
end
|
|
66
70
|
|
|
67
|
-
def
|
|
68
|
-
requests.order(:created_at.asc).first
|
|
71
|
+
def first_request
|
|
72
|
+
requests.order(:created_at.asc).first
|
|
69
73
|
end
|
|
70
74
|
|
|
71
|
-
def
|
|
72
|
-
|
|
75
|
+
def first_request_at
|
|
76
|
+
first_request&.created_at
|
|
73
77
|
end
|
|
74
78
|
|
|
79
|
+
delegate :count, to: :requests, prefix: true
|
|
80
|
+
|
|
75
81
|
private
|
|
76
82
|
|
|
77
83
|
def generate_token
|
|
78
|
-
self.token
|
|
84
|
+
self.token ||= loop do
|
|
79
85
|
random_token = SecureRandom.urlsafe_base64(15).tr('_-', '0a')
|
|
80
86
|
break random_token unless Bucket.where(token: random_token).exists?
|
|
81
87
|
end
|
data/app/models/request.rb
CHANGED
|
@@ -12,7 +12,6 @@ class Request
|
|
|
12
12
|
field :request_method
|
|
13
13
|
field :ip
|
|
14
14
|
field :url
|
|
15
|
-
field :params, type: Hash
|
|
16
15
|
|
|
17
16
|
index bucket_id: 1, created_at: -1
|
|
18
17
|
|
|
@@ -25,12 +24,12 @@ class Request
|
|
|
25
24
|
|
|
26
25
|
u = URI(url)
|
|
27
26
|
|
|
28
|
-
url.gsub(/.*#{Regexp.escape(u.host)}(\:#{Regexp.escape(u.port.to_s)})?/, '')
|
|
27
|
+
url.gsub(/.*#{::Regexp.escape(u.host)}(\:#{::Regexp.escape(u.port.to_s)})?/, '')
|
|
29
28
|
end
|
|
30
29
|
|
|
31
30
|
private
|
|
32
31
|
|
|
33
32
|
def bump_requests_recorded
|
|
34
|
-
|
|
33
|
+
Rails.cache.increment 'requests_recorded'
|
|
35
34
|
end
|
|
36
35
|
end
|
data/app/models/user.rb
CHANGED
|
@@ -6,8 +6,8 @@ class User
|
|
|
6
6
|
:recoverable, :rememberable, :trackable, :validatable
|
|
7
7
|
|
|
8
8
|
## Database authenticatable
|
|
9
|
-
field :email, type: String, default:
|
|
10
|
-
field :encrypted_password, type: String, default:
|
|
9
|
+
field :email, type: String, default: ''
|
|
10
|
+
field :encrypted_password, type: String, default: ''
|
|
11
11
|
|
|
12
12
|
## Recoverable
|
|
13
13
|
field :reset_password_token, type: String
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
class BucketSerializer < ActiveModel::Serializer
|
|
2
|
+
attributes :requests_count, :path
|
|
3
|
+
|
|
4
|
+
belongs_to :request
|
|
5
|
+
belongs_to :first_request
|
|
6
|
+
belongs_to :last_request
|
|
7
|
+
|
|
8
|
+
def path
|
|
9
|
+
Rails.application.routes.url_helpers.bucket_path(token: object.token)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
class RequestSerializer < ActiveModel::Serializer
|
|
2
|
+
attributes(
|
|
3
|
+
:id,
|
|
4
|
+
:headers,
|
|
5
|
+
:time_ago_in_words,
|
|
6
|
+
:created_at,
|
|
7
|
+
:request_method,
|
|
8
|
+
:request_body_as_string,
|
|
9
|
+
:response_body_as_string,
|
|
10
|
+
:headers_as_string,
|
|
11
|
+
:path
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
def id
|
|
15
|
+
object.id.to_s
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def time_ago_in_words
|
|
19
|
+
"#{ApplicationController.helpers.time_ago_in_words(object.created_at)} ago"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def headers_as_string
|
|
23
|
+
JSON.pretty_generate(object.headers.to_h)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def request_body_as_string
|
|
27
|
+
body_as_string(object)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def response_body_as_string
|
|
31
|
+
body_as_string(object.response)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def body_as_string(req_or_res)
|
|
37
|
+
body = req_or_res.body
|
|
38
|
+
|
|
39
|
+
if body_json?(req_or_res) && body.is_a?(String)
|
|
40
|
+
# See https://github.com/phstc/putsreq/issues/31#issuecomment-271681249
|
|
41
|
+
return JSON.pretty_generate(JSON.parse(body))
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
if body.is_a?(Hash)
|
|
45
|
+
# For responses body can be a hash
|
|
46
|
+
# body.to_h because body can be a BSON::Document
|
|
47
|
+
# which for some reason does format well with
|
|
48
|
+
# pretty_generate
|
|
49
|
+
return JSON.pretty_generate(body.to_h)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
if body.is_a?(Array)
|
|
53
|
+
# see https://github.com/phstc/putsreq/issues/33
|
|
54
|
+
return JSON.pretty_generate(body.to_a)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
body.to_s
|
|
58
|
+
rescue
|
|
59
|
+
body.to_s
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def body_json?(req_or_res)
|
|
63
|
+
req_or_res.headers.to_h.each do |key, value|
|
|
64
|
+
return !!(value =~ /application\/json/i) if key =~ /^content-type$/i
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
false
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
<button class="btn btn-primary tm10">Update</button>
|
|
2
|
-
<%= link_to 'Fork', bucket_fork_path(
|
|
3
|
-
<%= link_to 'Clear History', bucket_clear_path(
|
|
4
|
-
<%= link_to 'Destroy', bucket_destroy_path(
|
|
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?' } %>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
<%= form_for
|
|
1
|
+
<%= form_for bucket, url: update_bucket_path(bucket.token), method: :put do |f| %>
|
|
2
2
|
<%= f.hidden_field :response_builder %>
|
|
3
|
-
<script id="response-builder-container" type='application/vns.putsreq-response_builder'><%==
|
|
3
|
+
<script id="response-builder-container" type='application/vns.putsreq-response_builder'><%== bucket.response_builder %></script>
|
|
4
4
|
<div class="row">
|
|
5
5
|
<div class="col-md-6">
|
|
6
6
|
<h4>Bucket name
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
</h4>
|
|
9
9
|
<div class="input-group putsreq-name bm30">
|
|
10
10
|
<%= f.text_field :name %>
|
|
11
|
-
<% if
|
|
12
|
-
<p><small>forked from <%= link_to
|
|
11
|
+
<% if bucket.fork %>
|
|
12
|
+
<p><small>forked from <%= link_to bucket.fork.name, bucket_path(bucket.fork.token) %></small></p>
|
|
13
13
|
<% end %>
|
|
14
14
|
</div>
|
|
15
15
|
</div>
|
|
@@ -17,14 +17,14 @@
|
|
|
17
17
|
<h4>Requests
|
|
18
18
|
<small><em>The number of requests made to this bucket.</em></small>
|
|
19
19
|
</h4>
|
|
20
|
-
<
|
|
20
|
+
<div id="request-count-react-root"></div>
|
|
21
21
|
</div>
|
|
22
22
|
</div>
|
|
23
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
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 owner?(
|
|
27
|
+
<% if owner?(bucket) %>
|
|
28
28
|
<%= render 'buttons' %>
|
|
29
29
|
<% else %>
|
|
30
30
|
<%= render 'readonly_buttons' %>
|