Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 738b058224 |
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 Keith Casko
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -0,0 +1,245 @@
|
|||||||
|
# ByteGeist Toolbox
|
||||||
|
|
||||||
|
ByteGeist Toolbox is a plain Node.js and Express web app that provides practical website and network inspection tools from a single browser page.
|
||||||
|
|
||||||
|
Live site: [https://toolbox.casko.dev](https://toolbox.casko.dev)
|
||||||
|
|
||||||
|
## Tools
|
||||||
|
|
||||||
|
1. Website Status Checker
|
||||||
|
- Accepts a public HTTP or HTTPS URL.
|
||||||
|
- Returns online status, HTTP status code, response time, redirect count, final URL, and check timestamp.
|
||||||
|
|
||||||
|
2. DNS Lookup
|
||||||
|
- Accepts a public hostname or pasted website URL.
|
||||||
|
- Returns A, AAAA, CNAME, MX, TXT, and NS records plus a check timestamp.
|
||||||
|
|
||||||
|
3. SSL Certificate Checker
|
||||||
|
- Accepts a public hostname or pasted website URL.
|
||||||
|
- Returns certificate trust status, subject, issuer, validity dates, days remaining, TLS protocol, cipher, resolved address, SHA-256 fingerprint, authorization error when present, and check timestamp.
|
||||||
|
|
||||||
|
4. HTTP Headers Checker
|
||||||
|
- Accepts a public HTTP or HTTPS URL.
|
||||||
|
- Returns HTTP status, redirect count, final URL, all response headers, and whether common security headers are present.
|
||||||
|
- The header review is informational. It is not a complete website security grade.
|
||||||
|
|
||||||
|
## Technology Stack
|
||||||
|
|
||||||
|
- Plain HTML
|
||||||
|
- Plain CSS
|
||||||
|
- Plain browser JavaScript
|
||||||
|
- Node.js
|
||||||
|
- Express
|
||||||
|
- Docker and Docker Compose
|
||||||
|
- Node's built-in test runner
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
```text
|
||||||
|
.
|
||||||
|
|-- Dockerfile
|
||||||
|
|-- docker-compose.yml
|
||||||
|
|-- LICENSE
|
||||||
|
|-- package-lock.json
|
||||||
|
|-- package.json
|
||||||
|
|-- README.md
|
||||||
|
|-- docs
|
||||||
|
| |-- DEPLOYMENT.md
|
||||||
|
| |-- PORTFOLIO.md
|
||||||
|
| |-- RELEASE_CHECKLIST.md
|
||||||
|
| `-- screenshots
|
||||||
|
| `-- .gitkeep
|
||||||
|
|-- public
|
||||||
|
| |-- app.js
|
||||||
|
| |-- index.html
|
||||||
|
| `-- styles.css
|
||||||
|
|-- src
|
||||||
|
| |-- middleware
|
||||||
|
| | |-- rateLimit.js
|
||||||
|
| | `-- validateHostname.js
|
||||||
|
| |-- routes
|
||||||
|
| | |-- dns.js
|
||||||
|
| | |-- headers.js
|
||||||
|
| | |-- ssl.js
|
||||||
|
| | `-- uptime.js
|
||||||
|
| |-- server.js
|
||||||
|
| `-- services
|
||||||
|
| |-- dnsService.js
|
||||||
|
| |-- headersService.js
|
||||||
|
| |-- sslService.js
|
||||||
|
| |-- uptimeService.js
|
||||||
|
| `-- urlSecurityService.js
|
||||||
|
`-- tests
|
||||||
|
|-- dnsService.test.js
|
||||||
|
|-- headersService.test.js
|
||||||
|
|-- sslService.test.js
|
||||||
|
|-- urlSecurityService.test.js
|
||||||
|
`-- validateHostname.test.js
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security Controls
|
||||||
|
|
||||||
|
The code implements these controls for server-side outbound requests:
|
||||||
|
|
||||||
|
- Allows only `http:` and `https:` URLs for URL-based tools.
|
||||||
|
- Blocks credentials in submitted URLs.
|
||||||
|
- Allows only standard ports `80` and `443` for URL-based tools.
|
||||||
|
- Blocks common local hostnames including `localhost`, `.localhost`, `.local`, and `host.docker.internal`.
|
||||||
|
- Resolves hostnames before outbound requests and blocks loopback, private, link-local, unique-local, multicast, unspecified, reserved, broadcast, and carrier-grade NAT addresses.
|
||||||
|
- Revalidates every redirect destination before following it.
|
||||||
|
- Limits redirects to 5.
|
||||||
|
- Uses 5 second network timeouts for HTTP and TLS checks.
|
||||||
|
- Applies Express rate limiting of 30 requests per IP per 15 minutes on tool API routes.
|
||||||
|
- Returns safe client-facing error messages instead of raw low-level network errors.
|
||||||
|
- Uses Node DNS, Fetch, and TLS APIs without shell execution.
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
Current test command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm test
|
||||||
|
```
|
||||||
|
|
||||||
|
Current automated test count: 62 tests.
|
||||||
|
|
||||||
|
Baseline verified result: 62 pass, 0 fail, 0 skipped.
|
||||||
|
|
||||||
|
The current `npm test` suite includes public-network integration checks for DNS, SSL, and HTTP headers. Internet access is required for the full suite as currently organized.
|
||||||
|
|
||||||
|
## Local Development
|
||||||
|
|
||||||
|
Install dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
Run tests:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm test
|
||||||
|
```
|
||||||
|
|
||||||
|
Start local development with nodemon:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Start without nodemon:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
The app listens on port `3001` by default. The health endpoint is:
|
||||||
|
|
||||||
|
```text
|
||||||
|
GET /health
|
||||||
|
```
|
||||||
|
|
||||||
|
It returns JSON shaped like:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"status":"ok","service":"bytegeist-toolbox","timestamp":"2026-07-23T10:03:36.388Z"}
|
||||||
|
```
|
||||||
|
|
||||||
|
The timestamp is generated at request time.
|
||||||
|
|
||||||
|
## Docker
|
||||||
|
|
||||||
|
Build and run with Docker Compose:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
Check status:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose ps
|
||||||
|
docker compose logs --tail=100
|
||||||
|
```
|
||||||
|
|
||||||
|
Stop the service:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose down
|
||||||
|
```
|
||||||
|
|
||||||
|
The container runs the production start command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
The production application port is `3001`.
|
||||||
|
|
||||||
|
## Production Deployment
|
||||||
|
|
||||||
|
Production is intended to run as a Docker Compose service named `bytegeist-toolbox` on port `3001`, behind Nginx Proxy Manager.
|
||||||
|
|
||||||
|
The Compose file attaches the application to the external Docker network:
|
||||||
|
|
||||||
|
```text
|
||||||
|
nginx-proxy-manager_default
|
||||||
|
```
|
||||||
|
|
||||||
|
Nginx Proxy Manager should proxy to:
|
||||||
|
|
||||||
|
```text
|
||||||
|
http://bytegeist-toolbox:3001
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not assume the Nginx Proxy Manager container name. Confirm container names with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker ps
|
||||||
|
```
|
||||||
|
|
||||||
|
## Repository Workflow
|
||||||
|
|
||||||
|
The configured remotes are:
|
||||||
|
|
||||||
|
```text
|
||||||
|
origin https://git.casko.dev/keith/bytegeist-toolbox.git
|
||||||
|
github https://github.com/kcasko/bytegeist-toolbox.git
|
||||||
|
```
|
||||||
|
|
||||||
|
Use `origin` for the primary Gitea repository and `github` for the GitHub mirror.
|
||||||
|
|
||||||
|
## Screenshots
|
||||||
|
|
||||||
|
No screenshot image files currently exist under `docs/screenshots/`.
|
||||||
|
|
||||||
|
Expected screenshot filenames for the v1.0.0 README are:
|
||||||
|
|
||||||
|
```text
|
||||||
|
docs/screenshots/status-checker.png
|
||||||
|
docs/screenshots/dns-lookup.png
|
||||||
|
docs/screenshots/ssl-checker.png
|
||||||
|
docs/screenshots/http-headers.png
|
||||||
|
```
|
||||||
|
|
||||||
|
Add image references to this README only after those files exist.
|
||||||
|
|
||||||
|
## Current Limitations
|
||||||
|
|
||||||
|
- The automated test suite mixes local helper tests with public-network integration tests.
|
||||||
|
- DNS and network integration tests depend on external DNS and public websites being reachable.
|
||||||
|
- The HTTP Headers Checker reports common header presence only; it does not evaluate full security posture.
|
||||||
|
- The app checks public endpoints only and intentionally blocks local, private, reserved, and nonstandard-port destinations.
|
||||||
|
- Screenshots have not yet been captured for README display.
|
||||||
|
|
||||||
|
## Planned Improvements
|
||||||
|
|
||||||
|
- Split public-network integration tests from local unit tests while preserving coverage.
|
||||||
|
- Add screenshot images for all four tools.
|
||||||
|
- Add local mock-based route tests for API responses and error paths.
|
||||||
|
- Add manual release evidence for mobile screenshots and production verification.
|
||||||
|
|
||||||
|
## Author
|
||||||
|
|
||||||
|
Keith Casko
|
||||||
|
|
||||||
@@ -10,3 +10,10 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
PORT: 3001
|
PORT: 3001
|
||||||
NODE_ENV: production
|
NODE_ENV: production
|
||||||
|
|
||||||
|
networks:
|
||||||
|
- nginx-proxy-manager_default
|
||||||
|
|
||||||
|
networks:
|
||||||
|
nginx-proxy-manager_default:
|
||||||
|
external: true
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
# Deployment
|
||||||
|
|
||||||
|
## Local Use
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
npm test
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
The local development server listens on port `3001` unless `PORT` is set.
|
||||||
|
|
||||||
|
## Production Update
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /srv/bytegeist-toolbox
|
||||||
|
git pull origin main
|
||||||
|
docker compose down
|
||||||
|
docker compose up -d --build
|
||||||
|
docker compose ps
|
||||||
|
docker compose logs --tail=100
|
||||||
|
```
|
||||||
|
|
||||||
|
## Docker Network
|
||||||
|
|
||||||
|
The application joins the external Nginx Proxy Manager Docker network:
|
||||||
|
|
||||||
|
```text
|
||||||
|
nginx-proxy-manager_default
|
||||||
|
```
|
||||||
|
|
||||||
|
Nginx Proxy Manager should proxy to:
|
||||||
|
|
||||||
|
```text
|
||||||
|
http://bytegeist-toolbox:3001
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not assume the Nginx Proxy Manager container name. Confirm container names with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker ps
|
||||||
|
```
|
||||||
|
|
||||||
|
## Internal Health Check
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker exec -it npm curl -sS http://bytegeist-toolbox:3001/health
|
||||||
|
```
|
||||||
|
|
||||||
|
The `npm` container name is environment-specific. Confirm it with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker ps
|
||||||
|
```
|
||||||
|
|
||||||
|
## Public Verification
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -I https://toolbox.casko.dev
|
||||||
|
```
|
||||||
|
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
# ByteGeist Toolbox
|
||||||
|
|
||||||
|
## Project Description
|
||||||
|
|
||||||
|
ByteGeist Toolbox is a lightweight website and network diagnostics app that combines a website status checker, DNS lookup, SSL certificate checker, and HTTP headers checker in one plain HTML, CSS, JavaScript, Node.js, and Express application.
|
||||||
|
|
||||||
|
## Key Features
|
||||||
|
|
||||||
|
- Website status checks with status code, response time, redirects, final URL, and timestamp.
|
||||||
|
- DNS lookups for A, AAAA, CNAME, MX, TXT, and NS records.
|
||||||
|
- SSL certificate inspection with issuer, subject, validity dates, trust status, TLS protocol, cipher, resolved address, and SHA-256 fingerprint.
|
||||||
|
- HTTP response header inspection with common security-header presence indicators and raw header output.
|
||||||
|
- Responsive browser interface for desktop, tablet, and phone widths.
|
||||||
|
|
||||||
|
## Security Work
|
||||||
|
|
||||||
|
- Restricted URL checks to HTTP and HTTPS.
|
||||||
|
- Blocked URL credentials and nonstandard ports.
|
||||||
|
- Validated DNS resolution before outbound requests.
|
||||||
|
- Blocked loopback, private, link-local, local, reserved, and related non-public address ranges.
|
||||||
|
- Revalidated redirect destinations before following them.
|
||||||
|
- Added redirect limits, network timeouts, rate limiting, and safe client-facing errors.
|
||||||
|
- Used Node APIs for network work without shell execution.
|
||||||
|
|
||||||
|
## Testing Work
|
||||||
|
|
||||||
|
- Uses Node's built-in test runner.
|
||||||
|
- Current automated test count: 62 tests.
|
||||||
|
- Covers hostname validation, URL security checks, DNS helpers, SSL helper logic, HTTP header analysis, and public-network integration behavior.
|
||||||
|
- Current full test suite requires internet access.
|
||||||
|
|
||||||
|
## Deployment Architecture
|
||||||
|
|
||||||
|
- Node.js and Express app served from a Docker container.
|
||||||
|
- Production port: `3001`.
|
||||||
|
- Docker Compose service: `bytegeist-toolbox`.
|
||||||
|
- Reverse proxy: Nginx Proxy Manager over the external `nginx-proxy-manager_default` Docker network.
|
||||||
|
- Public site: `https://toolbox.casko.dev`.
|
||||||
|
|
||||||
|
## Technologies Used
|
||||||
|
|
||||||
|
- HTML
|
||||||
|
- CSS
|
||||||
|
- JavaScript
|
||||||
|
- Node.js
|
||||||
|
- Express
|
||||||
|
- Docker
|
||||||
|
- Docker Compose
|
||||||
|
- Node test runner
|
||||||
|
|
||||||
|
## Resume Entry
|
||||||
|
|
||||||
|
ByteGeist Toolbox - Built and prepared a production-ready Node.js diagnostics toolbox with four public website inspection tools, SSRF-resistant outbound request validation, Docker deployment, and automated test coverage.
|
||||||
|
|
||||||
|
## Resume Bullets
|
||||||
|
|
||||||
|
- Built a lightweight Express application providing website status, DNS, SSL certificate, and HTTP header inspection tools.
|
||||||
|
- Implemented outbound request controls to block private, loopback, link-local, reserved, local, credentialed, and nonstandard-port destinations.
|
||||||
|
- Added redirect revalidation, redirect limits, network timeouts, rate limiting, and safe client-facing error handling.
|
||||||
|
- Designed a responsive plain HTML, CSS, and JavaScript interface without adding frontend frameworks.
|
||||||
|
- Wrote and maintained 62 automated tests with coverage for validation, network helper logic, and integration behavior.
|
||||||
|
- Containerized the app with Docker and Docker Compose for deployment behind Nginx Proxy Manager.
|
||||||
|
- Documented release, deployment, security controls, limitations, and production verification steps for v1.0.0.
|
||||||
|
|
||||||
|
## LinkedIn Project Description
|
||||||
|
|
||||||
|
ByteGeist Toolbox is a lightweight Node.js and Express diagnostics app for checking website status, DNS records, SSL certificates, and HTTP headers. I prepared the project for a v1.0.0 release with Docker deployment docs, SSRF-resistant request validation, rate limiting, responsive UI checks, and 62 automated tests.
|
||||||
|
|
||||||
|
## Skills Demonstrated
|
||||||
|
|
||||||
|
- Node.js backend development
|
||||||
|
- Express routing and middleware
|
||||||
|
- Secure outbound request validation
|
||||||
|
- DNS, HTTP, and TLS diagnostics
|
||||||
|
- Docker deployment
|
||||||
|
- Automated testing
|
||||||
|
- Responsive frontend implementation
|
||||||
|
- Release documentation
|
||||||
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# ByteGeist Toolbox v1.0.0 Release Checklist
|
||||||
|
|
||||||
|
- [ ] Automated tests pass.
|
||||||
|
- [ ] Exact test count recorded.
|
||||||
|
- [ ] All four tools work locally.
|
||||||
|
- [ ] All four tools work in production.
|
||||||
|
- [ ] Private and loopback destinations are blocked.
|
||||||
|
- [ ] Invalid inputs return readable errors.
|
||||||
|
- [ ] Mobile layout checked at 375px, 390px, and 768px.
|
||||||
|
- [ ] Docker rebuild succeeds.
|
||||||
|
- [ ] Health endpoint succeeds.
|
||||||
|
- [ ] Nginx Proxy Manager can reach `bytegeist-toolbox:3001`.
|
||||||
|
- [ ] README screenshots exist.
|
||||||
|
- [ ] Gitea updated.
|
||||||
|
- [ ] GitHub mirror updated.
|
||||||
|
- [ ] Production deployment verified.
|
||||||
|
- [ ] v1.0.0 tag created and pushed.
|
||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
Generated
+1
-1
@@ -7,7 +7,7 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "bytegeist-toolbox",
|
"name": "bytegeist-toolbox",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "ISC",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"express": "^5.2.1",
|
"express": "^5.2.1",
|
||||||
"express-rate-limit": "^8.6.0",
|
"express-rate-limit": "^8.6.0",
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "bytegeist-toolbox",
|
"name": "bytegeist-toolbox",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "ISC",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node src/server.js",
|
"start": "node src/server.js",
|
||||||
"dev": "nodemon src/server.js",
|
"dev": "nodemon src/server.js",
|
||||||
|
|||||||
+10
-5
@@ -13,10 +13,15 @@ toolTabs.forEach((tab) => {
|
|||||||
|
|
||||||
// Mark only the selected tab as active.
|
// Mark only the selected tab as active.
|
||||||
toolTabs.forEach((currentTab) => {
|
toolTabs.forEach((currentTab) => {
|
||||||
currentTab.classList.toggle(
|
const isSelected = currentTab === tab;
|
||||||
"active",
|
|
||||||
currentTab === tab
|
currentTab.classList.toggle("active", isSelected);
|
||||||
);
|
|
||||||
|
if (isSelected) {
|
||||||
|
currentTab.setAttribute("aria-current", "page");
|
||||||
|
} else {
|
||||||
|
currentTab.removeAttribute("aria-current");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Show only the selected tool panel.
|
// Show only the selected tool panel.
|
||||||
@@ -658,4 +663,4 @@ headersForm.addEventListener("submit", async (event) => {
|
|||||||
headersButton.disabled = false;
|
headersButton.disabled = false;
|
||||||
headersButton.textContent = "Check Headers";
|
headersButton.textContent = "Check Headers";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
+6
-1
@@ -30,6 +30,8 @@
|
|||||||
class="tool-tab active"
|
class="tool-tab active"
|
||||||
type="button"
|
type="button"
|
||||||
data-tool="status-tool"
|
data-tool="status-tool"
|
||||||
|
aria-controls="status-tool"
|
||||||
|
aria-current="page"
|
||||||
>
|
>
|
||||||
Website Status
|
Website Status
|
||||||
</button>
|
</button>
|
||||||
@@ -39,6 +41,7 @@
|
|||||||
class="tool-tab"
|
class="tool-tab"
|
||||||
type="button"
|
type="button"
|
||||||
data-tool="dns-tool"
|
data-tool="dns-tool"
|
||||||
|
aria-controls="dns-tool"
|
||||||
>
|
>
|
||||||
DNS Lookup
|
DNS Lookup
|
||||||
</button>
|
</button>
|
||||||
@@ -48,6 +51,7 @@
|
|||||||
class="tool-tab"
|
class="tool-tab"
|
||||||
type="button"
|
type="button"
|
||||||
data-tool="ssl-tool"
|
data-tool="ssl-tool"
|
||||||
|
aria-controls="ssl-tool"
|
||||||
>
|
>
|
||||||
SSL Certificate
|
SSL Certificate
|
||||||
</button>
|
</button>
|
||||||
@@ -57,6 +61,7 @@
|
|||||||
class="tool-tab"
|
class="tool-tab"
|
||||||
type="button"
|
type="button"
|
||||||
data-tool="headers-tool"
|
data-tool="headers-tool"
|
||||||
|
aria-controls="headers-tool"
|
||||||
>
|
>
|
||||||
HTTP Headers
|
HTTP Headers
|
||||||
</button>
|
</button>
|
||||||
@@ -417,4 +422,4 @@
|
|||||||
<!-- Load browser JavaScript after the page elements exist. -->
|
<!-- Load browser JavaScript after the page elements exist. -->
|
||||||
<script src="app.js"></script>
|
<script src="app.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user