added request contents to the web interface
This commit is contained in:
parent
4046e5b59d
commit
8449230620
|
@ -1,34 +1,81 @@
|
|||
function logger(message) {
|
||||
let datetime = new Date().toISOString();
|
||||
console.log(`[Webhook_logger] [${datetime}] ${message}`);
|
||||
}
|
||||
|
||||
function getCallbackCode() {
|
||||
let urlParams = new URLSearchParams(window.location.search);
|
||||
return urlParams.get("cb");
|
||||
}
|
||||
|
||||
function setCallbackUrl(callbackCode) {
|
||||
let protocol = document.location.protocol;
|
||||
let host = document.location.host;
|
||||
let submitURL = `${protocol}//${host}/${getCallbackCode()}`;
|
||||
document.getElementById("callback-uuid-field").value = submitURL;
|
||||
}
|
||||
|
||||
function setupConnection() {
|
||||
/*
|
||||
Setup a connection to receive all the information
|
||||
about the webhooks in real-time.
|
||||
*/
|
||||
var callbackCode = getCallbackCode();
|
||||
console.log(callbackCode);
|
||||
|
||||
var webhookSocket = new WebSocket(
|
||||
let callbackCode = getCallbackCode();
|
||||
let webhookSocket = new WebSocket(
|
||||
"ws://" + window.location.host + "/ws/callback/" + callbackCode + "/"
|
||||
);
|
||||
|
||||
webhookSocket.onmessage = function(event) {
|
||||
/*
|
||||
Parses the information adds it to the UI state
|
||||
Parses the information adds it to the UI state
|
||||
*/
|
||||
console.log(event);
|
||||
logger("Message Received");
|
||||
requestList.addRequest(JSON.parse(event.data));
|
||||
};
|
||||
|
||||
webhookSocket.onopen = function(event) {
|
||||
console.log("[Webhook_logger] Connection stablished");
|
||||
logger("Connection stablished");
|
||||
};
|
||||
|
||||
webhookSocket.onclose = function(event) {
|
||||
console.log("[Webhook_logger] Connection lost");
|
||||
console.log("[Webhook_logger] Trying to reconnect");
|
||||
logger("Connection lost");
|
||||
logger("Trying to reconnect");
|
||||
setupConnection();
|
||||
};
|
||||
}
|
||||
|
||||
function getCallbackCode() {
|
||||
var urlParams = new URLSearchParams(window.location.search);
|
||||
return urlParams.get("cb");
|
||||
}
|
||||
/*
|
||||
Setup a simple component to handle the display of new content.
|
||||
Only supports two functions:
|
||||
- Add new content
|
||||
- Clean existing content
|
||||
*/
|
||||
var requestList = new Vue({
|
||||
el: "#app",
|
||||
delimiters: ["[[", "]]"],
|
||||
data: {
|
||||
requests: []
|
||||
},
|
||||
methods: {
|
||||
addRequest: function(request) {
|
||||
request.displayFull = false;
|
||||
this.requests.unshift(request);
|
||||
},
|
||||
toggleDetail: function(index) {
|
||||
let req = this.requests[index];
|
||||
req.displayFull = !req.displayFull;
|
||||
},
|
||||
removeItem: function(index) {
|
||||
this.requests.splice(index, 1);
|
||||
},
|
||||
clean: function() {
|
||||
this.requests = [];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
Prepare the page for action
|
||||
*/
|
||||
setCallbackUrl();
|
||||
setupConnection();
|
||||
|
|
|
@ -4,9 +4,76 @@
|
|||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css"
|
||||
/>
|
||||
<title>Webhook Logger</title>
|
||||
</head>
|
||||
<body>
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
<h1 class="title">Webhook Logger</h1>
|
||||
<h2 class="subtitle">
|
||||
Easily test and inspect
|
||||
<a href="https://en.wikipedia.org/wiki/Webhook">webhooks</a>
|
||||
</h2>
|
||||
<p>Use the following URL as your webhook callback:</p>
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<input
|
||||
id="callback-uuid-field"
|
||||
class="input is-large is-info"
|
||||
type="text"
|
||||
placeholder="Large input"
|
||||
readonly
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="section" id="app">
|
||||
<div class="container">
|
||||
<div v-if="requests.length === 0">No requests received yet</div>
|
||||
<div class="card" v-for="(request, index) in requests">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title" v-on:click="toggleDetail(index)">
|
||||
<span class="tag is-info">[[request.method]]</span>
|
||||
<span> from: [[request.ip_address]]</span>
|
||||
</p>
|
||||
<p class="card-header-icon">
|
||||
<span class="tag"
|
||||
>[[new Date(request.received_at).toLocaleString()]]</span
|
||||
>
|
||||
<button class="delete" v-on:click="removeItem(index)"></button>
|
||||
</p>
|
||||
</header>
|
||||
<div class="card-content" v-if="request.displayFull">
|
||||
<div class="content">
|
||||
<h2>Headers</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<th>Header</th>
|
||||
<th>Content</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="header in request.headers">
|
||||
<td>[[header.name]]</td>
|
||||
<td>[[header.value]]</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2>Query Params</h2>
|
||||
<div class="box">[[request.query_params]]</div>
|
||||
|
||||
<h2>Body</h2>
|
||||
<div class="box">[[request.body]]</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
|
||||
<script src="{% static 'js/viewer.js' %}"></script>
|
||||
</body>
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
from django.http import HttpRequest
|
||||
|
||||
|
||||
def get_ip_address(request: HttpRequest) -> str:
|
||||
forwarded = request.META.get("X-FORWARDED-FOR")
|
||||
if forwarded:
|
||||
return forwarded.split(",")[0]
|
||||
else:
|
||||
return request.META.get("REMOTE_ADDR")
|
|
@ -8,6 +8,8 @@ from django.utils import timezone
|
|||
from channels.layers import get_channel_layer
|
||||
from asgiref.sync import async_to_sync
|
||||
|
||||
from .utils import get_ip_address
|
||||
|
||||
|
||||
class HomeView(RedirectView):
|
||||
"""Initial page, just sends the visitor to an unique url"""
|
||||
|
@ -37,15 +39,28 @@ class CallbackView(View):
|
|||
def dispatch(self, request, *args, **kwargs):
|
||||
channel_layer = get_channel_layer()
|
||||
async_to_sync(channel_layer.group_send)(
|
||||
kwargs["uuid"], {"type": "new_request", "data": self.request_data(request)}
|
||||
kwargs["uuid"], {"type": "new_request", "data": self._request_data(request)}
|
||||
)
|
||||
return HttpResponse()
|
||||
|
||||
def request_data(self, request):
|
||||
def _request_data(self, request):
|
||||
body = request.body.decode("utf-8")
|
||||
return {
|
||||
"method": request.method,
|
||||
"ip_address": get_ip_address(request),
|
||||
"query_params": request.GET,
|
||||
"body": request.POST,
|
||||
"headers": request.META,
|
||||
"body": body,
|
||||
"headers": self._received_headers(),
|
||||
"received_at": timezone.now().isoformat(),
|
||||
}
|
||||
|
||||
def _received_headers(self):
|
||||
request = self.request
|
||||
headers = []
|
||||
for key, value in request.META.items():
|
||||
if key.startswith("HTTP"):
|
||||
original_header = (
|
||||
key.replace("HTTP_", "").replace("_", "-").capitalize()
|
||||
)
|
||||
headers.append({"name": original_header, "value": value})
|
||||
return headers
|
||||
|
|
|
@ -17,7 +17,7 @@ from django.urls import path
|
|||
from callbacks.views import HomeView, CheckView, CallbackView
|
||||
|
||||
urlpatterns = [
|
||||
path('check', CheckView.as_view(), name='callback-check'),
|
||||
path('submit/<uuid>', CallbackView.as_view(), name='callback-submit'),
|
||||
path('', HomeView.as_view(), name='callback-home')
|
||||
path("check", CheckView.as_view(), name="callback-check"),
|
||||
path("<uuid>", CallbackView.as_view(), name="callback-submit"),
|
||||
path("", HomeView.as_view(), name="callback-home"),
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue