requestkit 0.5.0 → 0.6.0
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 +4 -4
- data/README.md +27 -7
- data/lib/requestkit/server/render.rb +3 -0
- data/lib/requestkit/server/request.rb +105 -7
- data/lib/requestkit/server.rb +12 -5
- data/lib/requestkit/templates/index.css +1 -1
- data/lib/requestkit/templates/index.html.erb +134 -74
- data/lib/requestkit/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b03d1163eb2e887c855f1c4ca9b6d56bbfe9d38be3a89e6f4d9322a6b2c8768d
|
|
4
|
+
data.tar.gz: 75acfe2ad2e7a0bbfa88549d53b6096b1967b197c7cbcef2fee2cba63386c958
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4c6f9be4c8c65c91af603485349ad39bc15617eaef8304d203a99731750fe498c245ef0265cd6a75db4530929e0983eb07eb9c3fff30a42b36a127c2b888363f
|
|
7
|
+
data.tar.gz: a35745e18c86bf03ac31d72f7c087a25f39102c72a098b6193914df1685babd6d7b5bef11c0de6d7d88c4c20900041a915c9b05e9c9a44b8a728c923da4d55b6
|
data/README.md
CHANGED
|
@@ -42,14 +42,14 @@ curl -X POST http://localhost:4000/stripe/webhook \
|
|
|
42
42
|
Open `http://localhost:4000` in your browser to see all captured requests with headers and body.
|
|
43
43
|
|
|
44
44
|
|
|
45
|
-
### Custom
|
|
45
|
+
### Custom port
|
|
46
46
|
|
|
47
47
|
```bash
|
|
48
48
|
requestkit --port 8080
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
|
|
52
|
-
### Persistent
|
|
52
|
+
### Persistent storage
|
|
53
53
|
|
|
54
54
|
By default, requests are stored in memory and cleared when you stop the server. Use file storage to persist across restarts:
|
|
55
55
|
```bash
|
|
@@ -59,7 +59,7 @@ requestkit --storage file
|
|
|
59
59
|
Requests are saved to `~/.config/requestkit/requestkit.db`.
|
|
60
60
|
|
|
61
61
|
|
|
62
|
-
### Custom
|
|
62
|
+
### Custom database path
|
|
63
63
|
|
|
64
64
|
```bash
|
|
65
65
|
requestkit --storage file --database-path ./my-project.db
|
|
@@ -71,14 +71,12 @@ requestkit --storage file --database-path ./my-project.db
|
|
|
71
71
|
Create a configuration file to set defaults:
|
|
72
72
|
|
|
73
73
|
**User-wide settings** (`~/.config/requestkit/config.yml`):
|
|
74
|
-
|
|
75
74
|
```yaml
|
|
76
75
|
port: 5000
|
|
77
76
|
storage: file
|
|
78
77
|
```
|
|
79
78
|
|
|
80
79
|
**Project-specific settings** (`./.requestkit.yml`):
|
|
81
|
-
|
|
82
80
|
```yaml
|
|
83
81
|
storage: memory
|
|
84
82
|
default_namespace: my-rails-app
|
|
@@ -87,7 +85,7 @@ default_namespace: my-rails-app
|
|
|
87
85
|
Configuration precedence: CLI flags > project config > user config > defaults
|
|
88
86
|
|
|
89
87
|
|
|
90
|
-
### Available
|
|
88
|
+
### Available options
|
|
91
89
|
|
|
92
90
|
| Option | Description | Default |
|
|
93
91
|
|--------|-------------|---------|
|
|
@@ -111,6 +109,28 @@ curl http://localhost:4000/github/push-event
|
|
|
111
109
|
Filter by namespace in the web UI. Requests to `/` use the `default_namespace` from your config.
|
|
112
110
|
|
|
113
111
|
|
|
112
|
+
## Sending requests
|
|
113
|
+
|
|
114
|
+
Create JSON files to send HTTP requests and test your APIs. Requestkit loads request definitions from:
|
|
115
|
+
|
|
116
|
+
1. `./.requestkit/requests/:namespace/:name.json` (project-specific)
|
|
117
|
+
2. `~/.config/requestkit/requests/:namespace/name.json` (user-wide)
|
|
118
|
+
|
|
119
|
+
Example: (`.requestkit/requests/api/create-user.json`):
|
|
120
|
+
```json
|
|
121
|
+
{
|
|
122
|
+
"method": "POST",
|
|
123
|
+
"url": "http://localhost:3000/api/users",
|
|
124
|
+
|
|
125
|
+
"headers": {
|
|
126
|
+
"Content-Type": "application/json"
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
"body": "{\"name\": \"John Doe\", \"email\": \"john@example.com\"}"
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
|
|
114
134
|
## Help
|
|
115
135
|
|
|
116
136
|
```bash
|
|
@@ -120,4 +140,4 @@ requestkit help
|
|
|
120
140
|
|
|
121
141
|
## License
|
|
122
142
|
|
|
123
|
-
|
|
143
|
+
Requestkit is released under the [MIT License](https://opensource.org/licenses/MIT).
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
require "erb"
|
|
4
4
|
|
|
5
|
+
require "requestkit/server/request"
|
|
6
|
+
|
|
5
7
|
module Requestkit
|
|
6
8
|
class Server
|
|
7
9
|
class Render
|
|
@@ -13,6 +15,7 @@ module Requestkit
|
|
|
13
15
|
context = {
|
|
14
16
|
requests: selected_namespace ? database.by_namespace(selected_namespace) : database.all,
|
|
15
17
|
namespaces: database.namespaces,
|
|
18
|
+
saved_requests: Request.all_saved,
|
|
16
19
|
selected_namespace: selected_namespace
|
|
17
20
|
}
|
|
18
21
|
|
|
@@ -2,21 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
require "async/http/client"
|
|
4
4
|
require "openssl"
|
|
5
|
+
require "json" # not needed?
|
|
5
6
|
|
|
6
7
|
module Requestkit
|
|
7
8
|
class Server
|
|
8
9
|
class Request
|
|
9
10
|
class << self
|
|
10
|
-
def send(database:, namespace:)
|
|
11
|
+
def send(database:, namespace:, name:)
|
|
12
|
+
request_definition = load_request(namespace: namespace, name: name)
|
|
13
|
+
|
|
14
|
+
unless request_definition
|
|
15
|
+
return false
|
|
16
|
+
end
|
|
17
|
+
|
|
11
18
|
request_data = {
|
|
12
|
-
headers:
|
|
13
|
-
body:
|
|
19
|
+
headers: request_definition["headers"].merge({"User-Agent" => "Requestkit/#{Requestkit::VERSION}"}),
|
|
20
|
+
body: request_definition["body"]
|
|
14
21
|
}
|
|
15
22
|
|
|
16
|
-
|
|
23
|
+
url = request_definition["url"]
|
|
24
|
+
method = request_definition["method"].downcase
|
|
25
|
+
|
|
26
|
+
endpoint = ssl_endpoint_for(url)
|
|
17
27
|
client = Async::HTTP::Client.new(endpoint)
|
|
18
28
|
|
|
19
|
-
response = client.
|
|
29
|
+
response = client.send(method, URI(url).path, request_data[:headers], request_data[:body])
|
|
20
30
|
response_data = {
|
|
21
31
|
headers: response.headers.to_h,
|
|
22
32
|
body: response.body&.read || ""
|
|
@@ -26,18 +36,98 @@ module Requestkit
|
|
|
26
36
|
|
|
27
37
|
database.store(
|
|
28
38
|
namespace: namespace,
|
|
29
|
-
method:
|
|
30
|
-
path:
|
|
39
|
+
method: method.upcase,
|
|
40
|
+
path: url,
|
|
31
41
|
request: request_data.to_json,
|
|
32
42
|
response: response_data.to_json,
|
|
33
43
|
status: response.status,
|
|
34
44
|
direction: "outbound",
|
|
35
45
|
timestamp: Time.now.iso8601
|
|
36
46
|
)
|
|
47
|
+
|
|
48
|
+
true
|
|
49
|
+
rescue => error
|
|
50
|
+
puts "Error sending request: #{error.message}"
|
|
51
|
+
|
|
52
|
+
false
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def all_saved
|
|
56
|
+
{}.tap do |requests|
|
|
57
|
+
[local_requests_dir, user_requests_dir].each do |base_dir|
|
|
58
|
+
next unless Dir.exist?(base_dir)
|
|
59
|
+
|
|
60
|
+
Dir.glob(File.join(base_dir, "*", "*.json")).each do |file_path|
|
|
61
|
+
namespace = File.basename(File.dirname(file_path))
|
|
62
|
+
name = File.basename(file_path, ".json")
|
|
63
|
+
|
|
64
|
+
begin
|
|
65
|
+
definition = JSON.parse(File.read(file_path))
|
|
66
|
+
|
|
67
|
+
unless definition["method"] && definition["url"]
|
|
68
|
+
next
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
requests[namespace] ||= []
|
|
72
|
+
requests[namespace] << {
|
|
73
|
+
"name" => name,
|
|
74
|
+
"method" => definition["method"],
|
|
75
|
+
"url" => definition["url"]
|
|
76
|
+
}
|
|
77
|
+
rescue JSON::ParserError
|
|
78
|
+
next
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
# Dir.glob(File.join(base_dir, "*", "*.json")).each do |file_path|
|
|
82
|
+
# namespace = File.basename(File.dirname(file_path))
|
|
83
|
+
# name = File.basename(file_path, ".json")
|
|
84
|
+
# definition = JSON.parse(File.read(file_path))
|
|
85
|
+
|
|
86
|
+
# requests[namespace] ||= []
|
|
87
|
+
# requests[namespace] << {
|
|
88
|
+
# "name" => name,
|
|
89
|
+
# "method" => definition["method"],
|
|
90
|
+
# "url" => definition["url"]
|
|
91
|
+
# }
|
|
92
|
+
# end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
37
95
|
end
|
|
38
96
|
|
|
39
97
|
private
|
|
40
98
|
|
|
99
|
+
# def load_request(namespace:, name:)
|
|
100
|
+
# [local_request_path(namespace, name), user_request_path(namespace, name)].each do |path|
|
|
101
|
+
# return JSON.parse(File.read(path)) if File.exist?(path)
|
|
102
|
+
# end
|
|
103
|
+
|
|
104
|
+
# puts "Request file not found: #{namespace}/#{name}"
|
|
105
|
+
# nil
|
|
106
|
+
# end
|
|
107
|
+
def load_request(namespace:, name:)
|
|
108
|
+
[local_request_path(namespace, name), user_request_path(namespace, name)].each do |path|
|
|
109
|
+
if File.exist?(path)
|
|
110
|
+
definition = JSON.parse(File.read(path))
|
|
111
|
+
|
|
112
|
+
unless definition["method"] && definition["url"]
|
|
113
|
+
puts "Invalid request file #{namespace}/#{name}: missing `method` or `url`"
|
|
114
|
+
|
|
115
|
+
return nil
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
return definition
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
puts "Request file not found: #{namespace}/#{name}"
|
|
123
|
+
|
|
124
|
+
nil
|
|
125
|
+
rescue JSON::ParserError => error
|
|
126
|
+
puts "Invalid JSON in #{namespace}/#{name}: #{error.message}"
|
|
127
|
+
|
|
128
|
+
nil
|
|
129
|
+
end
|
|
130
|
+
|
|
41
131
|
def ssl_endpoint_for(url)
|
|
42
132
|
endpoint = Async::HTTP::Endpoint.parse(url)
|
|
43
133
|
ssl_context = OpenSSL::SSL::SSLContext.new
|
|
@@ -45,6 +135,14 @@ module Requestkit
|
|
|
45
135
|
|
|
46
136
|
endpoint.with(ssl_context: ssl_context)
|
|
47
137
|
end
|
|
138
|
+
|
|
139
|
+
def local_request_path(namespace, name) = File.join(local_requests_dir, namespace, "#{name}.json")
|
|
140
|
+
|
|
141
|
+
def user_request_path(namespace, name) = File.join(user_requests_dir, namespace, "#{name}.json")
|
|
142
|
+
|
|
143
|
+
def local_requests_dir = File.join(Dir.pwd, ".requestkit", "requests")
|
|
144
|
+
|
|
145
|
+
def user_requests_dir = File.join(Dir.home, ".config", "requestkit", "requests")
|
|
48
146
|
end
|
|
49
147
|
end
|
|
50
148
|
end
|
data/lib/requestkit/server.rb
CHANGED
|
@@ -43,11 +43,18 @@ module Requestkit
|
|
|
43
43
|
when ["/", "GET"]
|
|
44
44
|
Render.html(request, @db, @config)
|
|
45
45
|
when ["/send", "POST"]
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
query_parameters = Render.send(:query_params, from: request.path)
|
|
47
|
+
namespace = query_parameters["namespace"] || "test"
|
|
48
|
+
name = query_parameters["name"] || "default"
|
|
49
|
+
|
|
50
|
+
success = Request.send(database: @db, namespace: namespace, name: name)
|
|
51
|
+
|
|
52
|
+
if success
|
|
53
|
+
notify!
|
|
54
|
+
Protocol::HTTP::Response[303, {"location" => "/"}, []]
|
|
55
|
+
else
|
|
56
|
+
Protocol::HTTP::Response[400, {"content-type" => "text/plain"}, ["Failed to send request"]]
|
|
57
|
+
end
|
|
51
58
|
when ["/index.css", "GET"]
|
|
52
59
|
Render.css
|
|
53
60
|
when ["/clear", "POST"]
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! tailwindcss v4.1.16 | MIT License | https://tailwindcss.com */
|
|
2
|
-
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-font-weight:initial;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-200:oklch(88.5% .062 18.334);--color-red-700:oklch(50.5% .213 27.518);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-800:oklch(27.8% .033 256.848);--color-white:#fff;--spacing:.25rem;--container-5xl:64rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--radius-sm:.25rem;--radius-md:.375rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.mx-auto{margin-inline:auto}.mt-3{margin-top:calc(var(--spacing)*3)}.mt-4{margin-top:calc(var(--spacing)*4)}.flex{display:flex}.hidden{display:none}.inline-flex{display:inline-flex}.w-full{width:100%}.max-w-5xl{max-width:var(--container-5xl)}.border-collapse{border-collapse:collapse}.cursor-pointer{cursor:pointer}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-end{justify-content:flex-end}.gap-x-1\.5{column-gap:calc(var(--spacing)*1.5)}.gap-x-2{column-gap:calc(var(--spacing)*2)}.overflow-x-auto{overflow-x:auto}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.rounded-t-md{border-top-left-radius:var(--radius-md);border-top-right-radius:var(--radius-md)}.rounded-b-md{border-bottom-right-radius:var(--radius-md);border-bottom-left-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-gray-200{border-color:var(--color-gray-200)}.bg-gray-50{background-color:var(--color-gray-50)}.bg-gray-100{background-color:var(--color-gray-100)}.bg-gray-200\/60{background-color:#e5e7eb99}@supports (color:color-mix(in lab, red, red)){.bg-gray-200\/60{background-color:color-mix(in oklab,var(--color-gray-200)60%,transparent)}}.bg-white{background-color:var(--color-white)}.p-3{padding:calc(var(--spacing)*3)}.px-2{padding-inline:calc(var(--spacing)*2)}.py-1{padding-block:calc(var(--spacing)*1)}.py-3{padding-block:calc(var(--spacing)*3)}.py-4{padding-block:calc(var(--spacing)*4)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-gray-800{color:var(--color-gray-800)}.filter{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}:is(.\*\:px-4>*){padding-inline:calc(var(--spacing)*4)}:is(.\*\:py-1>*){padding-block:calc(var(--spacing)*1)}:is(.\*\:py-2>*){padding-block:calc(var(--spacing)*2)}:is(.\*\:text-left>*){text-align:left}:is(.\*\:text-sm>*){font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}:is(.\*\:text-xs>*){font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}:is(.\*\:font-semibold>*){--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}:is(.\*\:text-gray-500>*){color:var(--color-gray-500)}@media (hover:hover){.hover\:bg-gray-50:hover{background-color:var(--color-gray-50)}.hover\:bg-gray-200:hover{background-color:var(--color-gray-200)}.hover\:bg-red-200:hover{background-color:var(--color-red-200)}.hover\:text-red-700:hover{color:var(--color-red-700)}}.has-\[\+tr\[open\]\]\:bg-gray-50:has(+tr[open]){background-color:var(--color-gray-50)}.\[\&_svg\]\:size-3\.5 svg{width:calc(var(--spacing)*3.5);height:calc(var(--spacing)*3.5)}.\[\[open\]\]\:table-row[open]{display:table-row}}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}
|
|
2
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-border-style:solid;--tw-font-weight:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-200:oklch(88.5% .062 18.334);--color-red-500:oklch(63.7% .237 25.331);--color-red-700:oklch(50.5% .213 27.518);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-800:oklch(27.8% .033 256.848);--color-white:#fff;--spacing:.25rem;--container-7xl:80rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-base:1rem;--text-base--line-height:calc(1.5/1);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--radius-sm:.25rem;--radius-md:.375rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.col-span-12{grid-column:span 12/span 12}.mx-auto{margin-inline:auto}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-3{margin-top:calc(var(--spacing)*3)}.mt-4{margin-top:calc(var(--spacing)*4)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.w-full{width:100%}.max-w-7xl{max-width:var(--container-7xl)}.flex-1{flex:1}.border-collapse{border-collapse:collapse}.cursor-pointer{cursor:pointer}.grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-end{justify-content:flex-end}.gap-4{gap:calc(var(--spacing)*4)}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}.gap-x-1\.5{column-gap:calc(var(--spacing)*1.5)}.gap-x-2{column-gap:calc(var(--spacing)*2)}.overflow-x-auto{overflow-x:auto}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.rounded-t-md{border-top-left-radius:var(--radius-md);border-top-right-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-gray-200{border-color:var(--color-gray-200)}.bg-blue-500{background-color:var(--color-blue-500)}.bg-gray-50{background-color:var(--color-gray-50)}.bg-gray-100{background-color:var(--color-gray-100)}.bg-gray-200\/60{background-color:#e5e7eb99}@supports (color:color-mix(in lab, red, red)){.bg-gray-200\/60{background-color:color-mix(in oklab,var(--color-gray-200)60%,transparent)}}.bg-white{background-color:var(--color-white)}.p-3{padding:calc(var(--spacing)*3)}.p-4{padding:calc(var(--spacing)*4)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-3{padding-inline:calc(var(--spacing)*3)}.py-0\.5{padding-block:calc(var(--spacing)*.5)}.py-1{padding-block:calc(var(--spacing)*1)}.py-3{padding-block:calc(var(--spacing)*3)}.py-4{padding-block:calc(var(--spacing)*4)}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[\.675rem\],.text-\[0\.675rem\]{font-size:.675rem}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-gray-700{color:var(--color-gray-700)}.text-gray-800{color:var(--color-gray-800)}.text-red-700{color:var(--color-red-700)}.text-white{color:var(--color-white)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}:is(.\*\:px-4>*){padding-inline:calc(var(--spacing)*4)}:is(.\*\:py-1>*){padding-block:calc(var(--spacing)*1)}:is(.\*\:py-2>*){padding-block:calc(var(--spacing)*2)}:is(.\*\:text-left>*){text-align:left}:is(.\*\:text-sm>*){font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}:is(.\*\:text-xs>*){font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}:is(.\*\:font-semibold>*){--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}:is(.\*\:text-gray-500>*){color:var(--color-gray-500)}@media (hover:hover){.hover\:bg-blue-600:hover{background-color:var(--color-blue-600)}.hover\:bg-gray-50:hover{background-color:var(--color-gray-50)}.hover\:bg-gray-200:hover{background-color:var(--color-gray-200)}.hover\:bg-red-200:hover{background-color:var(--color-red-200)}.hover\:text-red-700:hover{color:var(--color-red-700)}}.has-\[\+tr\[open\]\]\:bg-gray-50:has(+tr[open]){background-color:var(--color-gray-50)}@media (min-width:48rem){.md\:col-span-4{grid-column:span 4/span 4}.md\:col-span-8{grid-column:span 8/span 8}}.\[\&_svg\]\:size-3\.5 svg{width:calc(var(--spacing)*3.5);height:calc(var(--spacing)*3.5)}.\[\&_svg\]\:size-4 svg{width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\[open\]\]\:table-row[open]{display:table-row}}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}
|
|
@@ -4,97 +4,155 @@
|
|
|
4
4
|
<title>Requestkit</title>
|
|
5
5
|
<meta charset="utf-8">
|
|
6
6
|
<link href="/index.css" rel="stylesheet" />
|
|
7
|
+
|
|
7
8
|
<script defer src="https://cdn.jsdelivr.net/npm/attractivejs@latest"></script>
|
|
8
9
|
</head>
|
|
9
10
|
|
|
10
11
|
<body class="bg-gray-100">
|
|
11
|
-
<div class="max-w-
|
|
12
|
-
<div class="
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
<
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
<% end %>
|
|
24
|
-
|
|
25
|
-
<div class="flex items-center justify-end gap-x-2 [&_svg]:size-3.5">
|
|
26
|
-
<a href="/" class="inline-flex items-center gap-x-1.5 px-2 py-1 text-xs font-normal text-gray-600 bg-gray-100 rounded-md transition hover:bg-gray-200">
|
|
27
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M240,56v48a8,8,0,0,1-8,8H184a8,8,0,0,1,0-16H211.4L184.81,71.64l-.25-.24a80,80,0,1,0-1.67,114.78,8,8,0,0,1,11,11.63A95.44,95.44,0,0,1,128,224h-1.32A96,96,0,1,1,195.75,60L224,85.8V56a8,8,0,1,1,16,0Z"/></svg>
|
|
28
|
-
|
|
29
|
-
Refresh
|
|
30
|
-
</a>
|
|
31
|
-
|
|
32
|
-
<% unless requests.empty? %>
|
|
33
|
-
<form method="post" action="/clear">
|
|
34
|
-
<button type="submit" data-action="confirm" data-confirm-message="Clear all requests?" class="inline-flex items-center gap-x-1.5 px-2 py-1 text-xs font-normal text-gray-600 bg-gray-100 rounded-md cursor-pointer transition hover:bg-red-200 hover:text-red-700">
|
|
35
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M216,48H176V40a24,24,0,0,0-24-24H104A24,24,0,0,0,80,40v8H40a8,8,0,0,0,0,16h8V208a16,16,0,0,0,16,16H192a16,16,0,0,0,16-16V64h8a8,8,0,0,0,0-16ZM96,40a8,8,0,0,1,8-8h48a8,8,0,0,1,8,8v8H96Zm96,168H64V64H192ZM112,104v64a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Zm48,0v64a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Z"/></svg>
|
|
36
|
-
|
|
37
|
-
Clear
|
|
38
|
-
</button>
|
|
12
|
+
<div class="max-w-7xl mx-auto px-2 py-4 grid grid-cols-12 gap-4">
|
|
13
|
+
<div class="col-span-12 bg-white rounded-md p-4 md:col-span-8">
|
|
14
|
+
<div class="flex items-center justify-between">
|
|
15
|
+
<% if namespaces.any? %>
|
|
16
|
+
<form method="get" action="/" id="namespace" class="inline-flex">
|
|
17
|
+
<select name="namespace" data-action="form#submit" data-target="#namespace" class="inline-flex items-center gap-x-1.5 px-2 py-1 text-xs font-normal text-gray-600 bg-gray-100 rounded-md transition hover:bg-gray-200">
|
|
18
|
+
<option value="">All namespaces</option>
|
|
19
|
+
|
|
20
|
+
<% namespaces.each do |namespace| %>
|
|
21
|
+
<option value="<%= namespace %>" <%= 'selected' if selected_namespace == namespace %>><%= namespace %></option>
|
|
22
|
+
<% end %>
|
|
23
|
+
</select>
|
|
39
24
|
</form>
|
|
40
25
|
<% end %>
|
|
41
|
-
</div>
|
|
42
|
-
</div>
|
|
43
26
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
</p>
|
|
48
|
-
<% else %>
|
|
49
|
-
<table class="w-full mt-4 border-collapse">
|
|
50
|
-
<thead>
|
|
51
|
-
<tr class="rounded-t-md *:px-4 *:py-1 *:text-left *:text-xs *:font-semibold *:text-gray-500">
|
|
52
|
-
<th>#</th>
|
|
27
|
+
<div class="flex items-center justify-end gap-x-2 [&_svg]:size-3.5">
|
|
28
|
+
<a href="/" class="inline-flex items-center gap-x-1.5 px-2 py-1 text-xs font-normal text-gray-600 bg-gray-100 rounded-md transition hover:bg-gray-200">
|
|
29
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M240,56v48a8,8,0,0,1-8,8H184a8,8,0,0,1,0-16H211.4L184.81,71.64l-.25-.24a80,80,0,1,0-1.67,114.78,8,8,0,0,1,11,11.63A95.44,95.44,0,0,1,128,224h-1.32A96,96,0,1,1,195.75,60L224,85.8V56a8,8,0,1,1,16,0Z"/></svg>
|
|
53
30
|
|
|
54
|
-
|
|
31
|
+
Refresh
|
|
32
|
+
</a>
|
|
55
33
|
|
|
56
|
-
|
|
34
|
+
<% unless requests.empty? %>
|
|
35
|
+
<form method="post" action="/clear">
|
|
36
|
+
<button type="submit" data-action="confirm" data-confirm-message="Clear all requests?" class="inline-flex items-center gap-x-1.5 px-2 py-1 text-xs font-normal text-gray-600 bg-gray-100 rounded-md cursor-pointer transition hover:bg-red-200 hover:text-red-700">
|
|
37
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M216,48H176V40a24,24,0,0,0-24-24H104A24,24,0,0,0,80,40v8H40a8,8,0,0,0,0,16h8V208a16,16,0,0,0,16,16H192a16,16,0,0,0,16-16V64h8a8,8,0,0,0,0-16ZM96,40a8,8,0,0,1,8-8h48a8,8,0,0,1,8,8v8H96Zm96,168H64V64H192ZM112,104v64a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Zm48,0v64a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Z"/></svg>
|
|
57
38
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
39
|
+
Clear
|
|
40
|
+
</button>
|
|
41
|
+
</form>
|
|
42
|
+
<% end %>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
61
45
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
46
|
+
<% if requests.empty? %>
|
|
47
|
+
<p class="mt-3 text-sm text-gray-500">
|
|
48
|
+
No webhooks received yet. Send a request to any endpoint.
|
|
49
|
+
</p>
|
|
50
|
+
<% else %>
|
|
51
|
+
<table class="w-full mt-4 border-collapse">
|
|
52
|
+
<thead>
|
|
53
|
+
<tr class="rounded-t-md *:px-4 *:py-1 *:text-left *:text-xs *:font-semibold *:text-gray-500">
|
|
54
|
+
<th>#</th>
|
|
67
55
|
|
|
68
|
-
<
|
|
56
|
+
<th>Method</th>
|
|
69
57
|
|
|
70
|
-
<
|
|
71
|
-
<code class="text-xs bg-gray-200/60 px-2 py-1 rounded-sm">
|
|
72
|
-
<%= request["path"] %>
|
|
73
|
-
</code>
|
|
74
|
-
</td>
|
|
58
|
+
<th>Path</th>
|
|
75
59
|
|
|
76
|
-
<
|
|
60
|
+
<th>Time</th>
|
|
77
61
|
</tr>
|
|
62
|
+
</thead>
|
|
63
|
+
|
|
64
|
+
<tbody>
|
|
65
|
+
<% requests.each do |request| %>
|
|
66
|
+
<% request_data = JSON.parse(request["request"]) %>
|
|
67
|
+
<tr data-action="toggleAttribute#open" data-target="#details-<%= request["id"] %>" class="*:px-4 *:py-2 *:text-sm has-[+tr[open]]:bg-gray-50 hover:bg-gray-50">
|
|
68
|
+
<td><%= request["id"] %></td>
|
|
69
|
+
|
|
70
|
+
<td class="flex items-center gap-x-1.5 text-[0.675rem] font-medium [&_svg]:size-4 [&_svg]:shrink-0 <%= 'text-red-700' if request["status"] && !(200..299).include?(request["status"].to_i) %>">
|
|
71
|
+
<% if request["direction"] == "outbound" %>
|
|
72
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M178.34,165.66,160,147.31V208a8,8,0,0,1-16,0V147.31l-18.34,18.35a8,8,0,0,1-11.32-11.32l32-32a8,8,0,0,1,11.32,0l32,32a8,8,0,0,1-11.32,11.32ZM160,40A88.08,88.08,0,0,0,81.29,88.68,64,64,0,1,0,72,216h40a8,8,0,0,0,0-16H72a48,48,0,0,1,0-96c1.1,0,2.2,0,3.29.12A88,88,0,0,0,72,128a8,8,0,0,0,16,0,72,72,0,1,1,100.8,66,8,8,0,0,0,3.2,15.34,7.9,7.9,0,0,0,3.2-.68A88,88,0,0,0,160,40Z"/></svg>
|
|
73
|
+
<% else %>
|
|
74
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M248,128a87.34,87.34,0,0,1-17.6,52.81,8,8,0,1,1-12.8-9.62A71.34,71.34,0,0,0,232,128a72,72,0,0,0-144,0,8,8,0,0,1-16,0,88,88,0,0,1,3.29-23.88C74.2,104,73.1,104,72,104a48,48,0,0,0,0,96H96a8,8,0,0,1,0,16H72A64,64,0,1,1,81.29,88.68,88,88,0,0,1,248,128Zm-69.66,42.34L160,188.69V128a8,8,0,0,0-16,0v60.69l-18.34-18.35a8,8,0,0,0-11.32,11.32l32,32a8,8,0,0,0,11.32,0l32-32a8,8,0,0,0-11.32-11.32Z"/></svg>
|
|
75
|
+
<% end %>
|
|
76
|
+
|
|
77
|
+
<%= request["method"] %>
|
|
78
|
+
</td>
|
|
79
|
+
|
|
80
|
+
<td>
|
|
81
|
+
<code class="text-xs bg-gray-200/60 px-2 py-1 rounded-sm">
|
|
82
|
+
<%= request["path"] %>
|
|
83
|
+
</code>
|
|
84
|
+
</td>
|
|
85
|
+
|
|
86
|
+
<td class="text-xs"><%= request["timestamp"] %></td>
|
|
87
|
+
</tr>
|
|
88
|
+
|
|
89
|
+
<tr id="details-<%= request["id"] %>" class="hidden w-full bg-gray-50 [[open]]:table-row">
|
|
90
|
+
<td colspan="5" class="px-2 py-3">
|
|
91
|
+
<section>
|
|
92
|
+
<h4 class="font-medium text-sm text-gray-800">
|
|
93
|
+
Headers
|
|
94
|
+
</h4>
|
|
95
|
+
<pre class="text-xs bg-white p-3 rounded-sm border border-gray-200 overflow-x-auto"><%= JSON.pretty_generate(request_data["headers"]) %></pre>
|
|
96
|
+
|
|
97
|
+
<h4 class="mt-4 font-medium text-sm text-gray-800">
|
|
98
|
+
Body
|
|
99
|
+
</h4>
|
|
100
|
+
<pre class="text-xs bg-white p-3 rounded-sm border border-gray-200 overflow-x-auto"><%= request_data["body"].empty? ? "(empty)" : request_data["body"] %></pre>
|
|
101
|
+
|
|
102
|
+
<% if request["response"] %>
|
|
103
|
+
<% response_data = JSON.parse(request["response"]) %>
|
|
104
|
+
|
|
105
|
+
<h4 class="mt-4 font-medium text-sm text-gray-800">Response Status</h4>
|
|
106
|
+
<pre class="text-xs bg-white p-3 rounded-sm border border-gray-200 overflow-x-auto"><%= request["status"] %></pre>
|
|
107
|
+
|
|
108
|
+
<h4 class="mt-4 font-medium text-sm text-gray-800">Response Headers</h4>
|
|
109
|
+
<pre class="text-xs bg-white p-3 rounded-sm border border-gray-200 overflow-x-auto"><%= JSON.pretty_generate(response_data["headers"]) %></pre>
|
|
110
|
+
|
|
111
|
+
<h4 class="mt-4 font-medium text-sm text-gray-800">Response Body</h4>
|
|
112
|
+
<pre class="text-xs bg-white p-3 rounded-sm border border-gray-200 overflow-x-auto"><%= response_data["body"].empty? ? "(empty)" : response_data["body"] %></pre>
|
|
113
|
+
<% end %>
|
|
114
|
+
</section>
|
|
115
|
+
</td>
|
|
116
|
+
</tr>
|
|
117
|
+
<% end %>
|
|
118
|
+
</tbody>
|
|
119
|
+
</table>
|
|
120
|
+
<% end %>
|
|
121
|
+
</div>
|
|
78
122
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
123
|
+
<div class="col-span-12 bg-white rounded-md p-4 md:col-span-4">
|
|
124
|
+
<h2 class="text-base font-bold">Outbound Requests</h2>
|
|
125
|
+
|
|
126
|
+
<% if saved_requests.empty? %>
|
|
127
|
+
<p class="mt-4 text-sm text-gray-500">No saved requests found. Create JSON files in <code>.requestkit/requests/:namespace/:name.json</code></p>
|
|
128
|
+
<% else %>
|
|
129
|
+
<ul class="mt-4">
|
|
130
|
+
<% saved_requests.each do |namespace, requests| %>
|
|
131
|
+
<li class="mb-4">
|
|
132
|
+
<h3 class="text-sm font-semibold text-gray-700"><%= namespace %></h3>
|
|
133
|
+
|
|
134
|
+
<div class="mt-2 space-y-2">
|
|
135
|
+
<% requests.each do |request| %>
|
|
136
|
+
<div class="flex items-center justify-between px-2 py-0.5 bg-gray-50 rounded-md">
|
|
137
|
+
<div class="flex-1">
|
|
138
|
+
<div class="text-sm font-medium"><%= request["name"] %></div>
|
|
139
|
+
|
|
140
|
+
<div class="text-xs text-gray-500"><%= request["url"] %></div>
|
|
141
|
+
</div>
|
|
142
|
+
|
|
143
|
+
<form method="post" action="/send?namespace=<%= namespace %>&name=<%= request["name"] %>" class="inline">
|
|
144
|
+
<button type="submit" class="px-3 py-1 text-[.675rem] font-medium text-white bg-blue-500 rounded-sm hover:bg-blue-600">
|
|
145
|
+
<%= request["method"] %>
|
|
146
|
+
</button>
|
|
147
|
+
</form>
|
|
148
|
+
</div>
|
|
149
|
+
<% end %>
|
|
150
|
+
</div>
|
|
151
|
+
</li>
|
|
94
152
|
<% end %>
|
|
95
|
-
</
|
|
96
|
-
|
|
97
|
-
|
|
153
|
+
</ul>
|
|
154
|
+
<% end %>
|
|
155
|
+
</div>
|
|
98
156
|
</div>
|
|
99
157
|
|
|
100
158
|
<script>
|
|
@@ -144,3 +202,5 @@
|
|
|
144
202
|
</script>
|
|
145
203
|
</body>
|
|
146
204
|
</html>
|
|
205
|
+
|
|
206
|
+
<!-- Icons by https://phosphoricons.com/ -->
|
data/lib/requestkit/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: requestkit
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Rails Designer Developers
|
|
@@ -79,7 +79,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
79
79
|
- !ruby/object:Gem::Version
|
|
80
80
|
version: '0'
|
|
81
81
|
requirements: []
|
|
82
|
-
rubygems_version:
|
|
82
|
+
rubygems_version: 4.0.0
|
|
83
83
|
specification_version: 4
|
|
84
84
|
summary: Local HTTP request toolkit
|
|
85
85
|
test_files: []
|