Compare commits
257 Commits
FEAT/impro
...
contributo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55fa726ef2 | ||
|
|
f233de9bca | ||
|
|
da0204c156 | ||
|
|
7ca22daa9a | ||
|
|
7ca8412cc9 | ||
|
|
bc6afa635c | ||
|
|
1627bed25c | ||
|
|
00af9f35cd | ||
|
|
95469b971f | ||
|
|
c30bea943b | ||
|
|
2bcf0bc670 | ||
|
|
15d32a5551 | ||
|
|
42ecdd9ef6 | ||
|
|
89cdbedf11 | ||
|
|
27f719078a | ||
|
|
67cc4c5275 | ||
|
|
db242fb980 | ||
|
|
9512595e21 | ||
|
|
7ee81a14e7 | ||
|
|
c63adc6678 | ||
|
|
21ab305c43 | ||
|
|
2445381b8e | ||
|
|
09efe9904e | ||
|
|
203a634f7c | ||
|
|
2186fff4dc | ||
|
|
07b6ca3222 | ||
|
|
abab9f1940 | ||
|
|
99f1e2768f | ||
|
|
2ff8155a35 | ||
|
|
c0f7ef1079 | ||
|
|
9bb8b3f46d | ||
|
|
ce9201594e | ||
|
|
0ff76de682 | ||
|
|
cee06c987a | ||
|
|
0a419045c0 | ||
|
|
ba8880cff7 | ||
|
|
a6bc8d790e | ||
|
|
8c17303179 | ||
|
|
e529a2e229 | ||
|
|
43fb27eade | ||
|
|
aea93fedeb | ||
|
|
7d4eab28b4 | ||
|
|
316e0d97fd | ||
|
|
ad9ea9137b | ||
|
|
2628655cdd | ||
|
|
7c0f750f6f | ||
|
|
0716ff5265 | ||
|
|
ff18904d6c | ||
|
|
0172de829c | ||
|
|
4fd5ff4315 | ||
|
|
8feb67de38 | ||
|
|
d3cbc50fb7 | ||
|
|
82be27c263 | ||
|
|
f0ec686f23 | ||
|
|
6773e61a89 | ||
|
|
73d1c248ca | ||
|
|
80bcd1d619 | ||
|
|
6207157da7 | ||
|
|
8013a0a445 | ||
|
|
2f1bab569d | ||
|
|
e2d83b627a | ||
|
|
03e980eafc | ||
|
|
f4196c79d4 | ||
|
|
6a04cdef46 | ||
|
|
2fe645fa37 | ||
|
|
8f552147ed | ||
|
|
a12e7c5c22 | ||
|
|
f9e6878cea | ||
|
|
50cc152491 | ||
|
|
68f95d503c | ||
|
|
fa6ef6f929 | ||
|
|
c46ec14cb1 | ||
|
|
10cbc2a738 | ||
|
|
ed1d33d81a | ||
|
|
5b71ba96c5 | ||
|
|
b55a1cc1b3 | ||
|
|
ca3f8a4235 | ||
|
|
fd49c488b1 | ||
|
|
3d6539b673 | ||
|
|
17696d80cc | ||
|
|
322ef5e0ea | ||
|
|
d826e97c4d | ||
|
|
b090dcadb1 | ||
|
|
34ca09fc20 | ||
|
|
97fd19492e | ||
|
|
a2f5bcb263 | ||
|
|
5de879be9f | ||
|
|
8a0ec5a7a7 | ||
|
|
d2f58f40b5 | ||
|
|
891982321c | ||
|
|
bf41ce0466 | ||
|
|
cb8db0b1f5 | ||
|
|
cc510bd281 | ||
|
|
c30e3a015c | ||
|
|
7125eeff5d | ||
|
|
a59c33571a | ||
|
|
26d51708eb | ||
|
|
37f711d95b | ||
|
|
9f82e19957 | ||
|
|
a5a277c20a | ||
|
|
91404d1c44 | ||
|
|
7557cb9b3a | ||
|
|
8a7e431af5 | ||
|
|
70724be65a | ||
|
|
7e27143a90 | ||
|
|
e5738d1f5b | ||
|
|
69abef34c5 | ||
|
|
32138847dd | ||
|
|
22cf1244c7 | ||
|
|
1478fa738d | ||
|
|
de75d1c71f | ||
|
|
390b8b9df7 | ||
|
|
42d6e0394f | ||
|
|
d9135883de | ||
|
|
c9e57400fd | ||
|
|
e255c358cb | ||
|
|
e6eb91a33a | ||
|
|
e3214660d0 | ||
|
|
bb6845d044 | ||
|
|
fd0b1e7d7f | ||
|
|
9a59d12a00 | ||
|
|
20ef316081 | ||
|
|
45bf452f17 | ||
|
|
7234e11e87 | ||
|
|
9609cd3701 | ||
|
|
031b0e37bb | ||
|
|
f1fff427f8 | ||
|
|
584c145b15 | ||
|
|
d9e7bb57f3 | ||
|
|
c9631e6848 | ||
|
|
06965b0e82 | ||
|
|
be741a1087 | ||
|
|
52b3960ce3 | ||
|
|
d7bcbcb5b4 | ||
|
|
4d54cdccac | ||
|
|
da75fb25d7 | ||
|
|
42023039c1 | ||
|
|
affec03d6c | ||
|
|
ecaffda777 | ||
|
|
0d484e3ffa | ||
|
|
38d6b5b97e | ||
|
|
728a8237aa | ||
|
|
24ca677021 | ||
|
|
ed53c29a55 | ||
|
|
c4e29fda0f | ||
|
|
ff65696729 | ||
|
|
2304aaf17c | ||
|
|
d43a05a0ed | ||
|
|
ada1dccc5b | ||
|
|
7a8e694abc | ||
|
|
c764bbfcd4 | ||
|
|
523419df11 | ||
|
|
62a213d74d | ||
|
|
7fc8ba4c15 | ||
|
|
f63418039a | ||
|
|
3f80d58085 | ||
|
|
ee74c5866a | ||
|
|
41cd379805 | ||
|
|
0c5dbd66a3 | ||
|
|
18f72788aa | ||
|
|
cd3ab4a264 | ||
|
|
ab66def695 | ||
|
|
68778d3824 | ||
|
|
43851ae0fb | ||
|
|
91a6e6221c | ||
|
|
7f2da1905c | ||
|
|
7583843e80 | ||
|
|
e77075764e | ||
|
|
195577fe0c | ||
|
|
29398665b0 | ||
|
|
1780b2323d | ||
|
|
1e6802afbf | ||
|
|
2cd68c5b98 | ||
|
|
ac3a70ae0d | ||
|
|
761f9dab81 | ||
|
|
64fbcb3f7d | ||
|
|
2fb7dc9a2b | ||
|
|
0a1023ce19 | ||
|
|
f4dd5d7a31 | ||
|
|
aff5ea5f52 | ||
|
|
4c4813620d | ||
|
|
b9bc24156b | ||
|
|
13d0e4ac9f | ||
|
|
01fb32e43c | ||
|
|
ec30ef7b8b | ||
|
|
af70930be2 | ||
|
|
55299f001f | ||
|
|
7e51239c8d | ||
|
|
cb6a008680 | ||
|
|
55f30f5537 | ||
|
|
cc3ca64f25 | ||
|
|
8c0cf5f870 | ||
|
|
2f46de124d | ||
|
|
0db0b044b2 | ||
|
|
299925d22e | ||
|
|
db9b69fac3 | ||
|
|
be307e6876 | ||
|
|
e44f8e73aa | ||
|
|
9c4335f2af | ||
|
|
44cbe47983 | ||
|
|
5924d89f54 | ||
|
|
b5ec08da8b | ||
|
|
184b962731 | ||
|
|
d6035b8e9c | ||
|
|
2988486a65 | ||
|
|
5616b71564 | ||
|
|
5348175b5e | ||
|
|
f9b4edda01 | ||
|
|
50590334be | ||
|
|
33a35b94f5 | ||
|
|
a6711aeb63 | ||
|
|
f36ac56370 | ||
|
|
09e5b5d888 | ||
|
|
ad57aaa7f8 | ||
|
|
2bce29e3cb | ||
|
|
6b9aad81fd | ||
|
|
afc5b54207 | ||
|
|
71ce9a6623 | ||
|
|
d8bb822a4e | ||
|
|
5297b2ffe7 | ||
|
|
79c88a5d9a | ||
|
|
0e022f97a2 | ||
|
|
0d4942738d | ||
|
|
32d5962dc3 | ||
|
|
8a7b024e99 | ||
|
|
c169a3762d | ||
|
|
d26f5b26a7 | ||
|
|
c2a937ac8e | ||
|
|
59203acdfa | ||
|
|
63db1dbd85 | ||
|
|
e23347a936 | ||
|
|
d41af54513 | ||
|
|
73c44e39de | ||
|
|
7dd398a9c3 | ||
|
|
1a95a42853 | ||
|
|
3695c82472 | ||
|
|
6a4eb5aa8e | ||
|
|
1630f2a050 | ||
|
|
b1f8c0144b | ||
|
|
76cce7ef9a | ||
|
|
393dafbf84 | ||
|
|
6bd353273a | ||
|
|
8a60b77135 | ||
|
|
ab59afc150 | ||
|
|
b314168da1 | ||
|
|
33e1adb974 | ||
|
|
8688fd23f5 | ||
|
|
cd2681fd84 | ||
|
|
0cb9cedd8c | ||
|
|
20762dc3ad | ||
|
|
359c6ca476 | ||
|
|
f7573572e5 | ||
|
|
975c73fd2b | ||
|
|
acf4f90aee | ||
|
|
daf6850052 | ||
|
|
3aa385cf41 | ||
|
|
394b68fa29 |
31
.env
@@ -2,11 +2,26 @@
|
|||||||
# Be sure to uncomment any line you populate
|
# Be sure to uncomment any line you populate
|
||||||
# Everything is optional, but some features won't work without external API access
|
# Everything is optional, but some features won't work without external API access
|
||||||
|
|
||||||
# GOOGLE_CLOUD_API_KEY=''
|
# API Keys for external services (backend)
|
||||||
# SHODAN_API_KEY=''
|
GOOGLE_CLOUD_API_KEY=''
|
||||||
# REACT_APP_SHODAN_API_KEY=''
|
TORRENT_IP_API_KEY=''
|
||||||
# WHO_API_KEY=''
|
SECURITY_TRAILS_API_KEY=''
|
||||||
# REACT_APP_WHO_API_KEY=''
|
BUILT_WITH_API_KEY=''
|
||||||
# SECURITY_TRAILS_API_KEY=''
|
URL_SCAN_API_KEY=''
|
||||||
# BUILT_WITH_API_KEY=''
|
TRANCO_USERNAME=''
|
||||||
# CI=false
|
TRANCO_API_KEY=''
|
||||||
|
CLOUDMERSIVE_API_KEY=''
|
||||||
|
|
||||||
|
# API Keys for external services (frontend)
|
||||||
|
REACT_APP_SHODAN_API_KEY=''
|
||||||
|
REACT_APP_WHO_API_KEY=''
|
||||||
|
|
||||||
|
# Configuration settings
|
||||||
|
# CHROME_PATH='/usr/bin/chromium' # The path the the Chromium executable
|
||||||
|
# PORT='3000' # Port to serve the API, when running server.js
|
||||||
|
# DISABLE_GUI='false' # Disable the GUI, and only serve the API
|
||||||
|
# API_TIMEOUT_LIMIT='10000' # The timeout limit for API requests, in milliseconds
|
||||||
|
# API_CORS_ORIGIN='*' # Enable CORS, by setting your allowed hostname(s) here
|
||||||
|
# API_ENABLE_RATE_LIMIT='true' # Enable rate limiting for the API
|
||||||
|
# REACT_APP_API_ENDPOINT='/api' # The endpoint for the API (can be local or remote)
|
||||||
|
# ENABLE_ANALYTICS='false' # Enable Plausible hit counter for the frontend
|
||||||
|
|||||||
667
.github/README.md
vendored
@@ -9,6 +9,22 @@
|
|||||||
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
---
|
||||||
|
<p align="center">
|
||||||
|
<sup>Kindly supported by:</sup><br>
|
||||||
|
<a href="https://terminaltrove.com/?utm_campaign=github&utm_medium=referral&utm_content=web-check&utm_source=wcgh">
|
||||||
|
<img src="https://i.ibb.co/8jrrcZ0/IMG-7210.jpg" width="300" alt="Terminal Trove">
|
||||||
|
<br>
|
||||||
|
<strong>The $HOME of all things in the terminal.</strong>
|
||||||
|
</a>
|
||||||
|
<br>
|
||||||
|
<a href="https://terminaltrove.com/newsletter?utm_campaign=github&utm_medium=referral&utm_content=web-check&utm_source=wcgh">
|
||||||
|
<sub>Find your next CLI / TUI tool and more at Terminal Trove,</sub>
|
||||||
|
<br>
|
||||||
|
<sup>Get updates on new tools on our newsletter.</sup>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
#### Contents
|
#### Contents
|
||||||
@@ -19,11 +35,13 @@
|
|||||||
- [Mirror](#mirror)
|
- [Mirror](#mirror)
|
||||||
- [Features](#features)
|
- [Features](#features)
|
||||||
- **[Usage](#usage)**
|
- **[Usage](#usage)**
|
||||||
- [Developer Setup](#developing)
|
- [Deployment](#deployment)
|
||||||
- [Deploying, Option#1: Netlify](#deploying---option-1-netlify)
|
- [Option#1: Netlify](#deploying---option-1-netlify)
|
||||||
- [Deploying, Option#2: Docker](#deploying---option-2-docker)
|
- [Option#2: Vercel](#deploying---option-2-vercel)
|
||||||
- [Deploying, Option#3: Source](#deploying---option-3-from-source)
|
- [Option#3: Docker](#deploying---option-3-docker)
|
||||||
|
- [Option#4: Source](#deploying---option-4-from-source)
|
||||||
- [Configuration Options](#configuring)
|
- [Configuration Options](#configuring)
|
||||||
|
- [Developer Setup](#developing)
|
||||||
- **[Community](#community)**
|
- **[Community](#community)**
|
||||||
- [Contributing](#contributing)
|
- [Contributing](#contributing)
|
||||||
- [Bugs](#reporting-bugs)
|
- [Bugs](#reporting-bugs)
|
||||||
@@ -56,18 +74,27 @@ A hosted version can be accessed at: **[web-check.as93.net](https://web-check.as
|
|||||||
### Mirror
|
### Mirror
|
||||||
The source for this repo is mirrored to CodeBerg, available at: **[codeberg.org/alicia/web-check](https://codeberg.org/alicia/web-check)**
|
The source for this repo is mirrored to CodeBerg, available at: **[codeberg.org/alicia/web-check](https://codeberg.org/alicia/web-check)**
|
||||||
|
|
||||||
### Motivation
|
### Status
|
||||||
Often when you're looking into a website, there's several things you always initially check.
|
|
||||||
|
|
||||||
|
Build & Deploys: [](https://app.netlify.com/sites/web-check/deploys)
|
||||||
|
[](https://vercel.com/as93/web-check/)
|
||||||
|
[](https://github.com/Lissy93/web-check/actions/workflows/docker.yml)
|
||||||
|
[](https://github.com/Lissy93/web-check/actions/workflows/deploy-aws.yml)
|
||||||
|
<br />
|
||||||
|
Repo Management & Miscellaneous: [](https://github.com/Lissy93/web-check/actions/workflows/mirror.yml)
|
||||||
|
[](https://github.com/Lissy93/web-check/actions/workflows/credits.yml)
|
||||||
|
|
||||||
None of this is hard to find with a series of basic curl commands and NPMAP plus a combination of online tools. But it's just so much easier to have everything done all at once, presented clearly and visible in one place :)
|
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
<details>
|
<details open>
|
||||||
<summary><h4>Expand to see all features</h4></summary>
|
<summary><b>Click to expand / collapse section</b></summary>
|
||||||
|
|
||||||
<sup>**Note** _this list needs updating, many more jobs have been added since..._</sup>
|
<sup>**Note** _this list needs updating, many more jobs have been added since..._</sup>
|
||||||
|
|
||||||
|
The following section outlines the core features, and briefly explains why this data might be useful for you to know, as well as linking to further resources for learning more.
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary><b>IP Info</b></summary>
|
<summary><b>IP Info</b></summary>
|
||||||
|
|
||||||
@@ -730,23 +757,13 @@ This may be useful to see what a given website looks like, free of the constrain
|
|||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
Read more here: **[web-check.as93.net/about](https://web-check.as93.net/about)**
|
Read more here: **[web-check.xyz/about](https://web-check.xyz/about)**
|
||||||
|
|
||||||
_Note that not all checks will work for all sites. Sometimes it's not possible to determine some information, and the demo instance has some limitations imposed by Netlify for the lambda functions._
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
### Developing
|
### Deployment
|
||||||
|
|
||||||
1. Clone the repo, `git clone git@github.com:Lissy93/web-check.git`
|
|
||||||
2. Cd into it, `cd web-check`
|
|
||||||
3. Install dependencies: `yarn`
|
|
||||||
4. Start the dev server, with `yarn dev`
|
|
||||||
|
|
||||||
You'll need [Node.js](https://nodejs.org/en) (V 18.16.1 or later) installed, plus [yarn](https://yarnpkg.com/getting-started/install) as well as [git](https://git-scm.com/).
|
|
||||||
Some checks also require `chromium`, `traceroute` and `dns` to be installed within your environment. These jobs will just be skipped if those packages aren't present.
|
|
||||||
|
|
||||||
### Deploying - Option #1: Netlify
|
### Deploying - Option #1: Netlify
|
||||||
|
|
||||||
@@ -754,28 +771,39 @@ Click the button below, to deploy to Netlify 👇
|
|||||||
|
|
||||||
[](https://app.netlify.com/start/deploy?repository=https://github.com/lissy93/web-check)
|
[](https://app.netlify.com/start/deploy?repository=https://github.com/lissy93/web-check)
|
||||||
|
|
||||||
### Deploying - Option #2: Docker
|
### Deploying - Option #2: Vercel
|
||||||
|
|
||||||
Run `docker run -p 8888:3000 lissy93/web-check`, then open `http://localhost:3000`
|
Click the button below, to deploy to Vercel 👇
|
||||||
|
|
||||||
|
[](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Flissy93%2Fweb-check&project-name=web-check&repository-name=web-check-fork&demo-title=Web-Check%20Demo&demo-description=Check%20out%20web-check.xyz%20to%20see%20a%20live%20demo%20of%20this%20application%20running.&demo-url=https%3A%2F%2Fweb-check.xyz&demo-image=https%3A%2F%2Fraw.githubusercontent.com%2FLissy93%2Fweb-check%2Fmaster%2F.github%2Fscreenshots%2Fweb-check-screenshot10.png)
|
||||||
|
|
||||||
|
### Deploying - Option #3: Docker
|
||||||
|
|
||||||
|
Run `docker run -p 3000:3000 lissy93/web-check`, then open [`localhost:3000`](http://localhost:3000)
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Docker Options</summary>
|
||||||
|
|
||||||
You can get the Docker image from:
|
You can get the Docker image from:
|
||||||
- DockerHub: [`lissy93/web-check`](https://hub.docker.com/r/lissy93/web-check)
|
- DockerHub: [`lissy93/web-check`](https://hub.docker.com/r/lissy93/web-check)
|
||||||
- GHCR: [`ghcr.io/lissy93/web-check`](https://github.com/Lissy93/web-check/pkgs/container/web-check)
|
- GHCR: [`ghcr.io/lissy93/web-check`](https://github.com/Lissy93/web-check/pkgs/container/web-check)
|
||||||
- Or build the image yourself by cloning the repo and running `docker build -t web-check .`
|
- Or build the image yourself by cloning the repo and running `docker build -t web-check .`
|
||||||
|
|
||||||
### Deploying - Option #3: From Source
|
</details>
|
||||||
|
|
||||||
Follow the instructions in the [Developing](#developing) section above, then run `yarn build` && `yarn serve` to build and serve the application.
|
### Deploying - Option #4: From Source
|
||||||
The following commands will work:
|
|
||||||
|
Install the prerequisites listed in the [Developing](#developing) section, then run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/Lissy93/web-check.git # Grab the code
|
git clone https://github.com/Lissy93/web-check.git # Download the code from GitHub
|
||||||
cd web-check # Move into the project directory
|
cd web-check # Navigate into the project dir
|
||||||
yarn install # Install dependencies
|
yarn install # Install the NPM dependencies
|
||||||
yarn build # Build the app for production
|
yarn build # Build the app for production
|
||||||
yarn serve # Start the app (API and GUI)
|
yarn serve # Start the app (API and GUI)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### Configuring
|
### Configuring
|
||||||
|
|
||||||
@@ -783,9 +811,17 @@ By default, no configuration is needed.
|
|||||||
|
|
||||||
But there are some optional environmental variables that you can set to give you access to some additional checks, or to increase rate-limits for some checks that use external APIs.
|
But there are some optional environmental variables that you can set to give you access to some additional checks, or to increase rate-limits for some checks that use external APIs.
|
||||||
|
|
||||||
Note that keys that are prefixed with `REACT_APP_` are used client-side, and as such they must be scoped correctly with minimum privileges.
|
|
||||||
|
|
||||||
**API Keys & Credentials**:
|
**API Keys & Credentials**:
|
||||||
|
|
||||||
|
Key | Value
|
||||||
|
---|---
|
||||||
|
`GOOGLE_CLOUD_API_KEY` | A Google API key ([get here](https://cloud.google.com/api-gateway/docs/authenticate-api-keys)). This can be used to return quality metrics for a site
|
||||||
|
`REACT_APP_SHODAN_API_KEY` | A Shodan API key ([get here](https://account.shodan.io/)). This will show associated host names for a given domain
|
||||||
|
`REACT_APP_WHO_API_KEY` | A WhoAPI key ([get here](https://whoapi.com/)). This will show more comprehensive WhoIs records than the default job
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><small>Full / Upcoming Vals</small></summary>
|
||||||
|
|
||||||
- `GOOGLE_CLOUD_API_KEY` - A Google API key ([get here](https://cloud.google.com/api-gateway/docs/authenticate-api-keys)). This can be used to return quality metrics for a site
|
- `GOOGLE_CLOUD_API_KEY` - A Google API key ([get here](https://cloud.google.com/api-gateway/docs/authenticate-api-keys)). This can be used to return quality metrics for a site
|
||||||
- `REACT_APP_SHODAN_API_KEY` - A Shodan API key ([get here](https://account.shodan.io/)). This will show associated host names for a given domain
|
- `REACT_APP_SHODAN_API_KEY` - A Shodan API key ([get here](https://account.shodan.io/)). This will show associated host names for a given domain
|
||||||
- `REACT_APP_WHO_API_KEY` - A WhoAPI key ([get here](https://whoapi.com/)). This will show more comprehensive WhoIs records than the default job
|
- `REACT_APP_WHO_API_KEY` - A WhoAPI key ([get here](https://whoapi.com/)). This will show more comprehensive WhoIs records than the default job
|
||||||
@@ -797,15 +833,38 @@ Note that keys that are prefixed with `REACT_APP_` are used client-side, and as
|
|||||||
- `BUILT_WITH_API_KEY` - A BuiltWith API key ([get here](https://api.builtwith.com/)). This will show the main features of a site
|
- `BUILT_WITH_API_KEY` - A BuiltWith API key ([get here](https://api.builtwith.com/)). This will show the main features of a site
|
||||||
- `TORRENT_IP_API_KEY` - A torrent API key ([get here](https://iknowwhatyoudownload.com/en/api/)). This will show torrents downloaded by an IP
|
- `TORRENT_IP_API_KEY` - A torrent API key ([get here](https://iknowwhatyoudownload.com/en/api/)). This will show torrents downloaded by an IP
|
||||||
|
|
||||||
**Configuration Settings**:
|
</details>
|
||||||
- `CHROME_PATH` (e.g. `/usr/bin/chromium`) - The path the the Chromium executable
|
|
||||||
- `PORT` (e.g. `3000`) - Port to serve the API, when running server.js
|
**Configuration Settings**:
|
||||||
- `DISABLE_GUI` (e.g. `false`) - Disable the GUI, and only serve the API
|
|
||||||
- `API_TIMEOUT_LIMIT` (e.g. `10000`) - The timeout limit for API requests, in milliseconds
|
Key | Value
|
||||||
- `REACT_APP_API_ENDPOINT` (e.g. `/api`) - The endpoint for the API (can be local or remote)
|
---|---
|
||||||
|
`PORT` | Port to serve the API, when running server.js (e.g. `3000`)
|
||||||
|
`API_ENABLE_RATE_LIMIT` | Enable rate-limiting for the /api endpoints (e.g. `true`)
|
||||||
|
`API_TIMEOUT_LIMIT` | The timeout limit for API requests, in milliseconds (e.g. `10000`)
|
||||||
|
`API_CORS_ORIGIN` | Enable CORS, by setting your allowed hostname(s) here (e.g. `example.com`)
|
||||||
|
`CHROME_PATH` | The path the Chromium executable (e.g. `/usr/bin/chromium`)
|
||||||
|
`DISABLE_GUI` | Disable the GUI, and only serve the API (e.g. `false`)
|
||||||
|
`REACT_APP_API_ENDPOINT` | The endpoint for the API, either local or remote (e.g. `/api`)
|
||||||
|
|
||||||
|
All values are optional.
|
||||||
|
|
||||||
|
You can add these as environmental variables. Either put them directly into an `.env` file in the projects root, or via the Netlify / Vercel UI, or by passing to the Docker container with the --env flag, or using your own environmental variable management system
|
||||||
|
|
||||||
|
Note that keys that are prefixed with `REACT_APP_` are used client-side, and as such they must be scoped correctly with minimum privileges, since may be made visible when intercepting browser <-> server network requests
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Developing
|
||||||
|
|
||||||
|
1. Clone the repo, `git clone git@github.com:Lissy93/web-check.git`
|
||||||
|
2. Cd into it, `cd web-check`
|
||||||
|
3. Install dependencies: `yarn`
|
||||||
|
4. Start the dev server, with `yarn dev`
|
||||||
|
|
||||||
|
You'll need [Node.js](https://nodejs.org/en) (V 18.16.1 or later) installed, plus [yarn](https://yarnpkg.com/getting-started/install) as well as [git](https://git-scm.com/).
|
||||||
|
Some checks also require `chromium`, `traceroute` and `dns` to be installed within your environment. These jobs will just be skipped if those packages aren't present.
|
||||||
|
|
||||||
The above can be added into an `.env` file in the projects root, or via the Netlify UI, or by passing directly to the Docker container with the --env flag.
|
|
||||||
All variables are optional.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -831,8 +890,9 @@ For bugs, please outline the steps needed to reproduce, and include relevant inf
|
|||||||
### Supporting
|
### Supporting
|
||||||
|
|
||||||
The app will remain 100% free and open source.
|
The app will remain 100% free and open source.
|
||||||
But due to the amount of traffic that the hosted instance gets, the lambda function usage is costing about $25/month. Any help with covering the costs via GitHub Sponsorship would be much appreciated. It's thanks to the support of the community that this project is able to be freely available for everyone :)
|
But due to the amount of traffic that the hosted instance gets, the lambda function usage is costing about $25/month.
|
||||||
|
Any help with covering the costs via GitHub Sponsorship would be much appreciated.
|
||||||
|
It's thanks to the support of the community that this project is able to be freely available for everyone :)
|
||||||
|
|
||||||
[](https://github.com/sponsors/Lissy93)
|
[](https://github.com/sponsors/Lissy93)
|
||||||
|
|
||||||
@@ -843,49 +903,200 @@ Credit to the following users for contributing to Web-Check
|
|||||||
|
|
||||||
<!-- readme: contributors -start -->
|
<!-- readme: contributors -start -->
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tbody>
|
||||||
<td align="center">
|
<tr>
|
||||||
<a href="https://github.com/Lissy93">
|
<td align="center">
|
||||||
<img src="https://avatars.githubusercontent.com/u/1862727?v=4" width="80;" alt="Lissy93"/>
|
<a href="https://github.com/Lissy93">
|
||||||
<br />
|
<img src="https://avatars.githubusercontent.com/u/1862727?v=4" width="80;" alt="Lissy93"/>
|
||||||
<sub><b>Alicia Sykes</b></sub>
|
<br />
|
||||||
</a>
|
<sub><b>Alicia Sykes</b></sub>
|
||||||
</td>
|
</a>
|
||||||
<td align="center">
|
</td>
|
||||||
<a href="https://github.com/muni106">
|
<td align="center">
|
||||||
<img src="https://avatars.githubusercontent.com/u/65845442?v=4" width="80;" alt="muni106"/>
|
<a href="https://github.com/liss-bot">
|
||||||
<br />
|
<img src="https://avatars.githubusercontent.com/u/87835202?v=4" width="80;" alt="liss-bot"/>
|
||||||
<sub><b>Mounir Samite</b></sub>
|
<br />
|
||||||
</a>
|
<sub><b>Alicia Bot</b></sub>
|
||||||
</td>
|
</a>
|
||||||
<td align="center">
|
</td>
|
||||||
<a href="https://github.com/gso-trifork-security">
|
<td align="center">
|
||||||
<img src="https://avatars.githubusercontent.com/u/69247026?v=4" width="80;" alt="gso-trifork-security"/>
|
<a href="https://github.com/n0a">
|
||||||
<br />
|
<img src="https://avatars.githubusercontent.com/u/14150948?v=4" width="80;" alt="n0a"/>
|
||||||
<sub><b>Gustav Soelberg</b></sub>
|
<br />
|
||||||
</a>
|
<sub><b>Denis Simonov</b></sub>
|
||||||
</td>
|
</a>
|
||||||
<td align="center">
|
</td>
|
||||||
<a href="https://github.com/treatmesubj">
|
<td align="center">
|
||||||
<img src="https://avatars.githubusercontent.com/u/39680353?v=4" width="80;" alt="treatmesubj"/>
|
<a href="https://github.com/muni106">
|
||||||
<br />
|
<img src="https://avatars.githubusercontent.com/u/65845442?v=4" width="80;" alt="muni106"/>
|
||||||
<sub><b>John Hupperts</b></sub>
|
<br />
|
||||||
</a>
|
<sub><b>Mounir Samite</b></sub>
|
||||||
</td>
|
</a>
|
||||||
<td align="center">
|
</td>
|
||||||
<a href="https://github.com/UlisesGascon">
|
<td align="center">
|
||||||
<img src="https://avatars.githubusercontent.com/u/5110813?v=4" width="80;" alt="UlisesGascon"/>
|
<a href="https://github.com/ChrisCarini">
|
||||||
<br />
|
<img src="https://avatars.githubusercontent.com/u/6374067?v=4" width="80;" alt="ChrisCarini"/>
|
||||||
<sub><b>Ulises Gascón</b></sub>
|
<br />
|
||||||
</a>
|
<sub><b>Chris Carini</b></sub>
|
||||||
</td>
|
</a>
|
||||||
<td align="center">
|
</td>
|
||||||
<a href="https://github.com/abhishekMuge">
|
<td align="center">
|
||||||
<img src="https://avatars.githubusercontent.com/u/49590582?v=4" width="80;" alt="abhishekMuge"/>
|
<a href="https://github.com/bolens">
|
||||||
<br />
|
<img src="https://avatars.githubusercontent.com/u/1218380?v=4" width="80;" alt="bolens"/>
|
||||||
<sub><b>Abhishek Muge</b></sub>
|
<br />
|
||||||
</a>
|
<sub><b>Michael Bolens</b></sub>
|
||||||
</td></tr>
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/HeroGamers">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/15278940?v=4" width="80;" alt="HeroGamers"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Marcus Sand</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/jinnabaalu">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/11784253?v=4" width="80;" alt="jinnabaalu"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Jinna Baalu</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/GreyXor">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/79602273?v=4" width="80;" alt="GreyXor"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>GreyXor</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/brianteeman">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/1296369?v=4" width="80;" alt="brianteeman"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Brian Teeman</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/vitalykarasik">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/7628795?v=4" width="80;" alt="vitalykarasik"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Vitaly Karasik</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/Its-Just-Nans">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/56606507?v=4" width="80;" alt="Its-Just-Nans"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>n4n5</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/robinson">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/237874?v=4" width="80;" alt="robinson"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Lth</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/abhishekMuge">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/49590582?v=4" width="80;" alt="abhishekMuge"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Abhishek Muge</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/UlisesGascon">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/5110813?v=4" width="80;" alt="UlisesGascon"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Ulises Gascón</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/PhiRequiem">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/1323576?v=4" width="80;" alt="PhiRequiem"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>PhiRequiem</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/34bits">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/108784453?v=4" width="80;" alt="34bits"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Nikolaos G. Ntaiko</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/Myzel394">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/50424412?v=4" width="80;" alt="Myzel394"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Myzel394</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/murrple-1">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/5559656?v=4" width="80;" alt="murrple-1"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Murray Christopherson</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/t3chn0m4g3">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/4318452?v=4" width="80;" alt="t3chn0m4g3"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Marco Ochse</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/treatmesubj">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/39680353?v=4" width="80;" alt="treatmesubj"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>John Hupperts</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/eltociear">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/22633385?v=4" width="80;" alt="eltociear"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Ikko Eltociear Ashimine</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/Gertje823">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/36937387?v=4" width="80;" alt="Gertje823"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Gertje823</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/epreston">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/347224?v=4" width="80;" alt="epreston"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Ed Preston</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/dimitri-kandassamy">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/21193806?v=4" width="80;" alt="dimitri-kandassamy"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Dimitri Kandassamy</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/0xflotus">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/26602940?v=4" width="80;" alt="0xflotus"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>0xflotus</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tbody>
|
||||||
</table>
|
</table>
|
||||||
<!-- readme: contributors -end -->
|
<!-- readme: contributors -end -->
|
||||||
|
|
||||||
@@ -895,114 +1106,177 @@ Huge thanks to these wonderful people, who sponsor me on GitHub, their support h
|
|||||||
|
|
||||||
<!-- readme: sponsors -start -->
|
<!-- readme: sponsors -start -->
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tbody>
|
||||||
<td align="center">
|
<tr>
|
||||||
<a href="https://github.com/emlazzarin">
|
<td align="center">
|
||||||
<img src="https://avatars.githubusercontent.com/u/1141361?v=4" width="80;" alt="emlazzarin"/>
|
<a href="https://github.com/vincentkoc">
|
||||||
<br />
|
<img src="https://avatars.githubusercontent.com/u/25068?v=4" width="80;" alt="vincentkoc"/>
|
||||||
<sub><b>Eddy Lazzarin</b></sub>
|
<br />
|
||||||
</a>
|
<sub><b>Vincent Koc</b></sub>
|
||||||
</td>
|
</a>
|
||||||
<td align="center">
|
</td>
|
||||||
<a href="https://github.com/AnandChowdhary">
|
<td align="center">
|
||||||
<img src="https://avatars.githubusercontent.com/u/2841780?v=4" width="80;" alt="AnandChowdhary"/>
|
<a href="https://github.com/AnandChowdhary">
|
||||||
<br />
|
<img src="https://avatars.githubusercontent.com/u/2841780?u=747e554b3a7f12eb20b7910e1c87d817844f714f&v=4" width="80;" alt="AnandChowdhary"/>
|
||||||
<sub><b>Anand Chowdhary</b></sub>
|
<br />
|
||||||
</a>
|
<sub><b>Anand Chowdhary</b></sub>
|
||||||
</td>
|
</a>
|
||||||
<td align="center">
|
</td>
|
||||||
<a href="https://github.com/shrippen">
|
<td align="center">
|
||||||
<img src="https://avatars.githubusercontent.com/u/2873570?v=4" width="80;" alt="shrippen"/>
|
<a href="https://github.com/shrippen">
|
||||||
<br />
|
<img src="https://avatars.githubusercontent.com/u/2873570?v=4" width="80;" alt="shrippen"/>
|
||||||
<sub><b>shrippen</b></sub>
|
<br />
|
||||||
</a>
|
<sub><b>Shrippen</b></sub>
|
||||||
</td>
|
</a>
|
||||||
<td align="center">
|
</td>
|
||||||
<a href="https://github.com/davidpaulyoung">
|
<td align="center">
|
||||||
<img src="https://avatars.githubusercontent.com/u/3418369?v=4" width="80;" alt="davidpaulyoung"/>
|
<a href="https://github.com/bile0026">
|
||||||
<br />
|
<img src="https://avatars.githubusercontent.com/u/5022496?u=aec96ad173c0ea9baaba93807efa8a848af6595c&v=4" width="80;" alt="bile0026"/>
|
||||||
<sub><b>David Young</b></sub>
|
<br />
|
||||||
</a>
|
<sub><b>Zach Biles</b></sub>
|
||||||
</td>
|
</a>
|
||||||
<td align="center">
|
</td>
|
||||||
<a href="https://github.com/k-rol">
|
<td align="center">
|
||||||
<img src="https://avatars.githubusercontent.com/u/4050412?v=4" width="80;" alt="k-rol"/>
|
<a href="https://github.com/UlisesGascon">
|
||||||
<br />
|
<img src="https://avatars.githubusercontent.com/u/5110813?u=3c41facd8aa26154b9451de237c34b0f78d672a5&v=4" width="80;" alt="UlisesGascon"/>
|
||||||
<sub><b>Carol Ouellet</b></sub>
|
<br />
|
||||||
</a>
|
<sub><b>Ulises Gascón</b></sub>
|
||||||
</td>
|
</a>
|
||||||
<td align="center">
|
</td>
|
||||||
<a href="https://github.com/bile0026">
|
<td align="center">
|
||||||
<img src="https://avatars.githubusercontent.com/u/5022496?v=4" width="80;" alt="bile0026"/>
|
<a href="https://github.com/digitalarche">
|
||||||
<br />
|
<img src="https://avatars.githubusercontent.com/u/6546135?u=564756d7f44ab2206819eb3148f6d822673f5066&v=4" width="80;" alt="digitalarche"/>
|
||||||
<sub><b>Zach Biles</b></sub>
|
<br />
|
||||||
</a>
|
<sub><b>Digital Archeology</b></sub>
|
||||||
</td></tr>
|
</a>
|
||||||
<tr>
|
</td>
|
||||||
<td align="center">
|
</tr>
|
||||||
<a href="https://github.com/UlisesGascon">
|
<tr>
|
||||||
<img src="https://avatars.githubusercontent.com/u/5110813?v=4" width="80;" alt="UlisesGascon"/>
|
<td align="center">
|
||||||
<br />
|
<a href="https://github.com/InDieTasten">
|
||||||
<sub><b>Ulises Gascón</b></sub>
|
<img src="https://avatars.githubusercontent.com/u/7047377?u=8d8f8017628b38bc46dcbf3620e194b01d3fb2d1&v=4" width="80;" alt="InDieTasten"/>
|
||||||
</a>
|
<br />
|
||||||
</td>
|
<sub><b>InDieTasten</b></sub>
|
||||||
<td align="center">
|
</a>
|
||||||
<a href="https://github.com/digitalarche">
|
</td>
|
||||||
<img src="https://avatars.githubusercontent.com/u/6546135?v=4" width="80;" alt="digitalarche"/>
|
<td align="center">
|
||||||
<br />
|
<a href="https://github.com/araguaci">
|
||||||
<sub><b>Digital Archeology</b></sub>
|
<img src="https://avatars.githubusercontent.com/u/7318668?v=4" width="80;" alt="araguaci"/>
|
||||||
</a>
|
<br />
|
||||||
</td>
|
<sub><b>Araguaci</b></sub>
|
||||||
<td align="center">
|
</a>
|
||||||
<a href="https://github.com/bmcgonag">
|
</td>
|
||||||
<img src="https://avatars.githubusercontent.com/u/7346620?v=4" width="80;" alt="bmcgonag"/>
|
<td align="center">
|
||||||
<br />
|
<a href="https://github.com/bmcgonag">
|
||||||
<sub><b>Brian McGonagill</b></sub>
|
<img src="https://avatars.githubusercontent.com/u/7346620?u=2a0f9284f3e12ac1cc15288c254d1ec68a5081e8&v=4" width="80;" alt="bmcgonag"/>
|
||||||
</a>
|
<br />
|
||||||
</td>
|
<sub><b>Brian McGonagill</b></sub>
|
||||||
<td align="center">
|
</a>
|
||||||
<a href="https://github.com/vlad-timofeev">
|
</td>
|
||||||
<img src="https://avatars.githubusercontent.com/u/11474041?v=4" width="80;" alt="vlad-timofeev"/>
|
<td align="center">
|
||||||
<br />
|
<a href="https://github.com/vlad-tim">
|
||||||
<sub><b>Vlad Timofeev</b></sub>
|
<img src="https://avatars.githubusercontent.com/u/11474041?u=eee43705b54d2ec9f51fc4fcce5ad18dd17c87e4&v=4" width="80;" alt="vlad-tim"/>
|
||||||
</a>
|
<br />
|
||||||
</td>
|
<sub><b>Vlad</b></sub>
|
||||||
<td align="center">
|
</a>
|
||||||
<a href="https://github.com/iJasonWade">
|
</td>
|
||||||
<img src="https://avatars.githubusercontent.com/u/12824479?v=4" width="80;" alt="iJasonWade"/>
|
<td align="center">
|
||||||
<br />
|
<a href="https://github.com/helixzz">
|
||||||
<sub><b>Jason Ash</b></sub>
|
<img src="https://avatars.githubusercontent.com/u/12218889?u=d06d0c103dfbdb99450623064f7da3c5a3675fb6&v=4" width="80;" alt="helixzz"/>
|
||||||
</a>
|
<br />
|
||||||
</td>
|
<sub><b>HeliXZz</b></sub>
|
||||||
<td align="center">
|
</a>
|
||||||
<a href="https://github.com/DRXAquosus">
|
</td>
|
||||||
<img src="https://avatars.githubusercontent.com/u/45409262?v=4" width="80;" alt="DRXAquosus"/>
|
<td align="center">
|
||||||
<br />
|
<a href="https://github.com/patvdv">
|
||||||
<sub><b>DRXAquosus</b></sub>
|
<img src="https://avatars.githubusercontent.com/u/12430107?u=e8911c2fb91af4d30432f76da8c40927b2830bd7&v=4" width="80;" alt="patvdv"/>
|
||||||
</a>
|
<br />
|
||||||
</td></tr>
|
<sub><b>Patrick Van Der Veken</b></sub>
|
||||||
<tr>
|
</a>
|
||||||
<td align="center">
|
</td>
|
||||||
<a href="https://github.com/Bastii717">
|
</tr>
|
||||||
<img src="https://avatars.githubusercontent.com/u/53431819?v=4" width="80;" alt="Bastii717"/>
|
<tr>
|
||||||
<br />
|
<td align="center">
|
||||||
<sub><b>Bastii717</b></sub>
|
<a href="https://github.com/MioOgbeni">
|
||||||
</a>
|
<img src="https://avatars.githubusercontent.com/u/24291977?v=4" width="80;" alt="MioOgbeni"/>
|
||||||
</td>
|
<br />
|
||||||
<td align="center">
|
<sub><b>Tomáš Novák</b></sub>
|
||||||
<a href="https://github.com/ratty222">
|
</a>
|
||||||
<img src="https://avatars.githubusercontent.com/u/92832598?v=4" width="80;" alt="ratty222"/>
|
</td>
|
||||||
<br />
|
<td align="center">
|
||||||
<sub><b>Brent</b></sub>
|
<a href="https://github.com/mryesiller">
|
||||||
</a>
|
<img src="https://avatars.githubusercontent.com/u/24632172?u=0d20f2d615158f87cd60a3398d3efb026c32f291&v=4" width="80;" alt="mryesiller"/>
|
||||||
</td>
|
<br />
|
||||||
<td align="center">
|
<sub><b>Göksel Yeşiller</b></sub>
|
||||||
<a href="https://github.com/jtfinley72">
|
</a>
|
||||||
<img src="https://avatars.githubusercontent.com/u/96497997?v=4" width="80;" alt="jtfinley72"/>
|
</td>
|
||||||
<br />
|
<td align="center">
|
||||||
<sub><b>jtfinley72</b></sub>
|
<a href="https://github.com/sushibait">
|
||||||
</a>
|
<img src="https://avatars.githubusercontent.com/u/26634535?v=4" width="80;" alt="sushibait"/>
|
||||||
</td></tr>
|
<br />
|
||||||
|
<sub><b>Shiverme Timbers</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/forwardemail">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/32481436?v=4" width="80;" alt="forwardemail"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Forward Email - Open-source & Privacy-focused Email Service (2023)</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/getumbrel">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/59408891?v=4" width="80;" alt="getumbrel"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Umbrel</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/OlliVHH">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/84959562?v=4" width="80;" alt="OlliVHH"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>HamburgerJung</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/frankdez93">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/87549420?v=4" width="80;" alt="frankdez93"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Frankdez93</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/terminaltrove">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/121595180?v=4" width="80;" alt="terminaltrove"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Terminal Trove</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/st617">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/128325650?v=4" width="80;" alt="st617"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>st617</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/nrvo">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/151435968?u=e1dcb307fd0efdc45cddbe9490a7b956e4da6835&v=4" width="80;" alt="nrvo"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Nrvo</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/hudsonrock-partnerships">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/163282900?u=5f2667f7fe5d284ac7a2da6b0800ea8970b0fcbf&v=4" width="80;" alt="hudsonrock-partnerships"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>hudsonrock-partnerships</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tbody>
|
||||||
</table>
|
</table>
|
||||||
<!-- readme: sponsors -end -->
|
<!-- readme: sponsors -end -->
|
||||||
|
|
||||||
@@ -1038,8 +1312,11 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
[](https://app.fossa.com/projects/git%2Bgithub.com%2FLissy93%2Fweb-check?ref=badge_large&issueType=license)
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|
||||||
<!-- License + Copyright -->
|
<!-- License + Copyright -->
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<i>© <a href="https://aliciasykes.com">Alicia Sykes</a> 2023</i><br>
|
<i>© <a href="https://aliciasykes.com">Alicia Sykes</a> 2023</i><br>
|
||||||
@@ -1048,7 +1325,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||||||
<sup>Thanks for visiting :)</sup>
|
<sup>Thanks for visiting :)</sup>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<!-- Dinosaur -->
|
<!-- Dinosaurs are Awesome -->
|
||||||
<!--
|
<!--
|
||||||
. - ~ ~ ~ - .
|
. - ~ ~ ~ - .
|
||||||
.. _ .-~ ~-.
|
.. _ .-~ ~-.
|
||||||
|
|||||||
6
.github/workflows/credits.yml
vendored
@@ -12,9 +12,9 @@ jobs:
|
|||||||
name: Inserts Sponsors 💓
|
name: Inserts Sponsors 💓
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
- name: Updates readme with sponsors
|
- name: Updates readme with sponsors
|
||||||
uses: JamesIves/github-sponsors-readme-action@1.0.5
|
uses: JamesIves/github-sponsors-readme-action@v1
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.BOT_TOKEN || secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.BOT_TOKEN || secrets.GITHUB_TOKEN }}
|
||||||
file: .github/README.md
|
file: .github/README.md
|
||||||
@@ -25,7 +25,7 @@ jobs:
|
|||||||
name: Inserts Contributors 💓
|
name: Inserts Contributors 💓
|
||||||
steps:
|
steps:
|
||||||
- name: Updates readme with contributors
|
- name: Updates readme with contributors
|
||||||
uses: akhilmhdh/contributors-readme-action@v2.3.4
|
uses: akhilmhdh/contributors-readme-action@v2.3.10
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.BOT_TOKEN || secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.BOT_TOKEN || secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
|
|||||||
128
.github/workflows/deploy-aws.yml
vendored
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
name: 🚀 Deploy to AWS
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
paths:
|
||||||
|
- api/**
|
||||||
|
- serverless.yml
|
||||||
|
- package.json
|
||||||
|
- .github/workflows/deploy-aws.yml
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy-api:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 16
|
||||||
|
|
||||||
|
- name: Cache node_modules
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: node_modules
|
||||||
|
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-yarn-
|
||||||
|
|
||||||
|
- name: Create GitHub deployment for API
|
||||||
|
uses: chrnorm/deployment-action@releases/v2
|
||||||
|
id: deployment_api
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.BOT_TOKEN || secrets.GITHUB_TOKEN }}
|
||||||
|
environment: AWS (Backend API)
|
||||||
|
ref: ${{ github.ref }}
|
||||||
|
|
||||||
|
- name: Install Serverless CLI and dependencies
|
||||||
|
run: |
|
||||||
|
npm i -g serverless
|
||||||
|
yarn
|
||||||
|
|
||||||
|
- name: Deploy to AWS
|
||||||
|
env:
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }}
|
||||||
|
run: serverless deploy
|
||||||
|
|
||||||
|
- name: Update GitHub deployment status (API)
|
||||||
|
if: always()
|
||||||
|
uses: chrnorm/deployment-status@v2
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.BOT_TOKEN || secrets.GITHUB_TOKEN }}
|
||||||
|
state: "${{ job.status }}"
|
||||||
|
deployment_id: ${{ steps.deployment_api.outputs.deployment_id }}
|
||||||
|
ref: ${{ github.ref }}
|
||||||
|
|
||||||
|
deploy-frontend:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 16
|
||||||
|
|
||||||
|
- name: Cache node_modules
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: node_modules
|
||||||
|
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-yarn-
|
||||||
|
|
||||||
|
- name: Create GitHub deployment for Frontend
|
||||||
|
uses: chrnorm/deployment-action@v2
|
||||||
|
id: deployment_frontend
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.BOT_TOKEN || secrets.GITHUB_TOKEN }}
|
||||||
|
environment: AWS (Frontend Web UI)
|
||||||
|
ref: ${{ github.ref }}
|
||||||
|
|
||||||
|
- name: Install dependencies and build
|
||||||
|
run: |
|
||||||
|
yarn install
|
||||||
|
yarn build
|
||||||
|
|
||||||
|
- name: Setup AWS
|
||||||
|
uses: aws-actions/configure-aws-credentials@v4
|
||||||
|
with:
|
||||||
|
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
|
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
aws-region: us-east-1
|
||||||
|
|
||||||
|
- name: Upload to S3
|
||||||
|
env:
|
||||||
|
AWS_S3_BUCKET: 'web-check-frontend'
|
||||||
|
run: aws s3 sync ./build/ s3://$AWS_S3_BUCKET/ --delete
|
||||||
|
|
||||||
|
- name: Invalidate CloudFront cache
|
||||||
|
uses: chetan/invalidate-cloudfront-action@v2
|
||||||
|
env:
|
||||||
|
DISTRIBUTION: E30XKAM2TG9FD8
|
||||||
|
PATHS: '/*'
|
||||||
|
AWS_REGION: 'us-east-1'
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
|
||||||
|
- name: Update GitHub deployment status (Frontend)
|
||||||
|
if: always()
|
||||||
|
uses: chrnorm/deployment-status@v2
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.BOT_TOKEN || secrets.GITHUB_TOKEN }}
|
||||||
|
state: "${{ job.status }}"
|
||||||
|
deployment_id: ${{ steps.deployment_frontend.outputs.deployment_id }}
|
||||||
|
ref: ${{ github.ref }}
|
||||||
|
|
||||||
18
.github/workflows/docker.yml
vendored
@@ -23,14 +23,14 @@ jobs:
|
|||||||
docker:
|
docker:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout 🛎️
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Extract tag name
|
- name: Extract tag name 🏷️
|
||||||
shell: bash
|
shell: bash
|
||||||
run: echo "GIT_TAG=$(echo ${GITHUB_REF#refs/tags/} | sed 's/\//_/g')" >> $GITHUB_ENV
|
run: echo "GIT_TAG=$(echo ${GITHUB_REF#refs/tags/} | sed 's/\//_/g')" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Compute tags
|
- name: Compute tags 🔖
|
||||||
id: compute-tags
|
id: compute-tags
|
||||||
run: |
|
run: |
|
||||||
if [[ "${{ github.ref }}" == "refs/heads/master" ]]; then
|
if [[ "${{ github.ref }}" == "refs/heads/master" ]]; then
|
||||||
@@ -41,33 +41,33 @@ jobs:
|
|||||||
echo "DOCKERHUB_TAG=${DOCKERHUB_REGISTRY}/${DOCKER_USER}/${IMAGE_NAME}:${GIT_TAG}" >> $GITHUB_ENV
|
echo "DOCKERHUB_TAG=${DOCKERHUB_REGISTRY}/${DOCKER_USER}/${IMAGE_NAME}:${GIT_TAG}" >> $GITHUB_ENV
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU 🐧
|
||||||
uses: docker/setup-qemu-action@v1
|
uses: docker/setup-qemu-action@v1
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx 🐳
|
||||||
uses: docker/setup-buildx-action@v1
|
uses: docker/setup-buildx-action@v1
|
||||||
|
|
||||||
- name: Login to GitHub Container Registry
|
- name: Login to GitHub Container Registry 🔑
|
||||||
uses: docker/login-action@v1
|
uses: docker/login-action@v1
|
||||||
with:
|
with:
|
||||||
registry: ${{ env.GHCR_REGISTRY }}
|
registry: ${{ env.GHCR_REGISTRY }}
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Login to DockerHub
|
- name: Login to DockerHub 🔑
|
||||||
uses: docker/login-action@v1
|
uses: docker/login-action@v1
|
||||||
with:
|
with:
|
||||||
registry: ${{ env.DOCKERHUB_REGISTRY }}
|
registry: ${{ env.DOCKERHUB_REGISTRY }}
|
||||||
username: ${{ env.DOCKER_USER }}
|
username: ${{ env.DOCKER_USER }}
|
||||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||||
|
|
||||||
- name: Build and push Docker images
|
- name: Build and push Docker images 🛠️
|
||||||
uses: docker/build-push-action@v2
|
uses: docker/build-push-action@v2
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./Dockerfile
|
file: ./Dockerfile
|
||||||
push: true
|
push: true
|
||||||
platforms: linux/amd64
|
platforms: linux/amd64,linux/arm64/v8
|
||||||
tags: |
|
tags: |
|
||||||
${{ env.GHCR_TAG }}
|
${{ env.GHCR_TAG }}
|
||||||
${{ env.DOCKERHUB_TAG }}
|
${{ env.DOCKERHUB_TAG }}
|
||||||
|
|||||||
2
.github/workflows/mirror.yml
vendored
@@ -8,7 +8,7 @@ jobs:
|
|||||||
codeberg:
|
codeberg:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 0 }
|
with: { fetch-depth: 0 }
|
||||||
- uses: pixta-dev/repository-mirroring-action@v1
|
- uses: pixta-dev/repository-mirroring-action@v1
|
||||||
with:
|
with:
|
||||||
|
|||||||
71
.gitignore
vendored
@@ -1,27 +1,62 @@
|
|||||||
|
# ------------------------
|
||||||
# keys
|
# ENVIRONMENT SETTINGS
|
||||||
|
# ------------------------
|
||||||
.env
|
.env
|
||||||
|
|
||||||
# dependencies
|
# ------------------------
|
||||||
/node_modules
|
# PRODUCTION
|
||||||
/.pnp
|
# ------------------------
|
||||||
.pnp.js
|
/build/
|
||||||
|
|
||||||
# logs
|
# ------------------------
|
||||||
|
# BUILT FILES
|
||||||
|
# ------------------------
|
||||||
|
dist/
|
||||||
|
.vercel/
|
||||||
|
.netlify/
|
||||||
|
.webpack/
|
||||||
|
.serverless/
|
||||||
|
.astro/
|
||||||
|
|
||||||
|
# ------------------------
|
||||||
|
# DEPENDENCIES
|
||||||
|
# ------------------------
|
||||||
|
node_modules/
|
||||||
|
.yarn/cache/
|
||||||
|
.yarn/unplugged/
|
||||||
|
.yarn/build-state.yml
|
||||||
|
.yarn/install-state.gz
|
||||||
|
.pnpm/
|
||||||
|
.pnp.*
|
||||||
|
|
||||||
|
# ------------------------
|
||||||
|
# LOGS
|
||||||
|
# ------------------------
|
||||||
|
logs/
|
||||||
|
*.log
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
.pnpm-debug.log*
|
||||||
|
|
||||||
# testing
|
# ------------------------
|
||||||
/coverage
|
# TESTING
|
||||||
|
# ------------------------
|
||||||
|
coverage/
|
||||||
|
.nyc_output/
|
||||||
|
|
||||||
# production
|
# ------------------------
|
||||||
/build
|
# OS SPECIFIC
|
||||||
|
# ------------------------
|
||||||
# Random AWS and Netlify crap
|
|
||||||
.netlify
|
|
||||||
.serverless
|
|
||||||
.webpack
|
|
||||||
|
|
||||||
# OS generated files
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# ------------------------
|
||||||
|
# EDITORS
|
||||||
|
# ------------------------
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
|
|||||||
69
Dockerfile
@@ -1,13 +1,62 @@
|
|||||||
FROM node:16-buster-slim AS base
|
# Specify the Node.js version to use
|
||||||
WORKDIR /app
|
ARG NODE_VERSION=21
|
||||||
FROM base AS builder
|
|
||||||
COPY . .
|
# Specify the Debian version to use, the default is "bullseye"
|
||||||
RUN apt-get update && \
|
ARG DEBIAN_VERSION=bullseye
|
||||||
apt-get install -y chromium traceroute && \
|
|
||||||
chmod 755 /usr/bin/chromium && \
|
# Use Node.js Docker image as the base image, with specific Node and Debian versions
|
||||||
|
FROM node:${NODE_VERSION}-${DEBIAN_VERSION} AS build
|
||||||
|
|
||||||
|
# Set the container's default shell to Bash and enable some options
|
||||||
|
SHELL ["/bin/bash", "-euo", "pipefail", "-c"]
|
||||||
|
|
||||||
|
# Install Chromium browser and Download and verify Google Chrome’s signing key
|
||||||
|
RUN apt-get update -qq --fix-missing && \
|
||||||
|
apt-get -qqy install --allow-unauthenticated gnupg wget && \
|
||||||
|
wget --quiet --output-document=- https://dl-ssl.google.com/linux/linux_signing_key.pub | gpg --dearmor > /etc/apt/trusted.gpg.d/google-archive.gpg && \
|
||||||
|
echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google.list && \
|
||||||
|
apt-get update -qq && \
|
||||||
|
apt-get -qqy --no-install-recommends install chromium traceroute python make g++ && \
|
||||||
rm -rf /var/lib/apt/lists/*
|
rm -rf /var/lib/apt/lists/*
|
||||||
RUN npm install --force
|
|
||||||
RUN npm run build
|
# Run the Chromium browser's version command and redirect its output to the /etc/chromium-version file
|
||||||
|
RUN /usr/bin/chromium --no-sandbox --version > /etc/chromium-version
|
||||||
|
|
||||||
|
# Set the working directory to /app
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy package.json and yarn.lock to the working directory
|
||||||
|
COPY package.json yarn.lock ./
|
||||||
|
|
||||||
|
# Run yarn install to install dependencies and clear yarn cache
|
||||||
|
RUN apt-get update && \
|
||||||
|
yarn install --frozen-lockfile --network-timeout 100000 && \
|
||||||
|
rm -rf /app/node_modules/.cache
|
||||||
|
|
||||||
|
# Copy all files to working directory
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Run yarn build to build the application
|
||||||
|
RUN yarn build --production
|
||||||
|
|
||||||
|
# Final stage
|
||||||
|
FROM node:${NODE_VERSION}-${DEBIAN_VERSION} AS final
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package.json yarn.lock ./
|
||||||
|
COPY --from=build /app .
|
||||||
|
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y --no-install-recommends chromium traceroute && \
|
||||||
|
chmod 755 /usr/bin/chromium && \
|
||||||
|
rm -rf /var/lib/apt/lists/* /app/node_modules/.cache
|
||||||
|
|
||||||
|
# Exposed container port, the default is 3000, which can be modified through the environment variable PORT
|
||||||
EXPOSE ${PORT:-3000}
|
EXPOSE ${PORT:-3000}
|
||||||
|
|
||||||
|
# Set the environment variable CHROME_PATH to specify the path to the Chromium binaries
|
||||||
ENV CHROME_PATH='/usr/bin/chromium'
|
ENV CHROME_PATH='/usr/bin/chromium'
|
||||||
CMD ["npm", "run", "serve"]
|
|
||||||
|
# Define the command executed when the container starts and start the server.js of the Node.js application
|
||||||
|
CMD ["yarn", "start"]
|
||||||
|
|||||||
@@ -2,37 +2,154 @@ const normalizeUrl = (url) => {
|
|||||||
return url.startsWith('http') ? url : `https://${url}`;
|
return url.startsWith('http') ? url : `https://${url}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// If present, set a shorter timeout for API requests
|
||||||
|
const TIMEOUT = process.env.API_TIMEOUT_LIMIT ? parseInt(process.env.API_TIMEOUT_LIMIT, 10) : 60000;
|
||||||
|
|
||||||
|
// If present, set CORS allowed origins for responses
|
||||||
|
const ALLOWED_ORIGINS = process.env.API_CORS_ORIGIN || '*';
|
||||||
|
|
||||||
|
// Disable everything :( Setting this env var will turn off the instance, and show message
|
||||||
|
const DISABLE_EVERYTHING = !!process.env.VITE_DISABLE_EVERYTHING;
|
||||||
|
|
||||||
|
// Set the platform currently being used
|
||||||
|
let PLATFORM = 'NETLIFY';
|
||||||
|
if (process.env.PLATFORM) { PLATFORM = process.env.PLATFORM.toUpperCase(); }
|
||||||
|
else if (process.env.VERCEL) { PLATFORM = 'VERCEL'; }
|
||||||
|
else if (process.env.WC_SERVER) { PLATFORM = 'NODE'; }
|
||||||
|
|
||||||
|
// Define the headers to be returned with each response
|
||||||
|
const headers = {
|
||||||
|
'Access-Control-Allow-Origin': ALLOWED_ORIGINS,
|
||||||
|
'Access-Control-Allow-Credentials': true,
|
||||||
|
'Content-Type': 'application/json;charset=UTF-8',
|
||||||
|
};
|
||||||
|
|
||||||
|
const timeoutErrorMsg = 'You can re-trigger this request, by clicking "Retry"\n'
|
||||||
|
+ 'If you\'re running your own instance of Web Check, then you can '
|
||||||
|
+ 'resolve this issue, by increasing the timeout limit in the '
|
||||||
|
+ '`API_TIMEOUT_LIMIT` environmental variable to a higher value (in milliseconds), '
|
||||||
|
+ 'or if you\'re hosting on Vercel increase the maxDuration in vercel.json.\n\n'
|
||||||
|
+ `The public instance currently has a lower timeout of ${TIMEOUT}ms `
|
||||||
|
+ 'in order to keep running costs affordable, so that Web Check can '
|
||||||
|
+ 'remain freely available for everyone.';
|
||||||
|
|
||||||
|
const disabledErrorMsg = 'Error - WebCheck Temporarily Disabled.\n\n'
|
||||||
|
+ 'We\'re sorry, but due to the increased cost of running Web Check '
|
||||||
|
+ 'we\'ve had to temporatily disable the public instand. '
|
||||||
|
+ 'We\'re activley looking for affordable ways to keep Web Check running, '
|
||||||
|
+ 'while free to use for everybody.\n'
|
||||||
|
+ 'In the meantime, since we\'ve made our code free and open source, '
|
||||||
|
+ 'you can get Web Check running on your own system, by following the instructions in our GitHub repo';
|
||||||
|
|
||||||
|
// A middleware function used by all API routes on all platforms
|
||||||
const commonMiddleware = (handler) => {
|
const commonMiddleware = (handler) => {
|
||||||
return async (event, context, callback) => {
|
|
||||||
const queryParams = event.queryStringParameters || event.query || {};
|
// Create a timeout promise, to throw an error if a request takes too long
|
||||||
|
const createTimeoutPromise = (timeoutMs) => {
|
||||||
|
return new Promise((_, reject) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
reject(new Error(`Request timed-out after ${timeoutMs} ms`));
|
||||||
|
}, timeoutMs);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Vercel
|
||||||
|
const vercelHandler = async (request, response) => {
|
||||||
|
|
||||||
|
if (DISABLE_EVERYTHING) {
|
||||||
|
response.status(503).json({ error: disabledErrorMsg });
|
||||||
|
}
|
||||||
|
|
||||||
|
const queryParams = request.query || {};
|
||||||
const rawUrl = queryParams.url;
|
const rawUrl = queryParams.url;
|
||||||
|
|
||||||
if (!rawUrl) {
|
if (!rawUrl) {
|
||||||
callback(null, {
|
return response.status(500).json({ error: 'No URL specified' });
|
||||||
statusCode: 500,
|
|
||||||
body: JSON.stringify({ error: 'No URL specified' }),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = normalizeUrl(rawUrl);
|
const url = normalizeUrl(rawUrl);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await handler(url, event, context);
|
// Race the handler against the timeout
|
||||||
if (response.body && response.statusCode) {
|
const handlerResponse = await Promise.race([
|
||||||
callback(null, response);
|
handler(url, request),
|
||||||
|
createTimeoutPromise(TIMEOUT)
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (handlerResponse.body && handlerResponse.statusCode) {
|
||||||
|
response.status(handlerResponse.statusCode).json(handlerResponse.body);
|
||||||
|
} else {
|
||||||
|
response.status(200).json(
|
||||||
|
typeof handlerResponse === 'object' ? handlerResponse : JSON.parse(handlerResponse)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
let errorCode = 500;
|
||||||
|
if (error.message.includes('timed-out') || response.statusCode === 504) {
|
||||||
|
errorCode = 408;
|
||||||
|
error.message = `${error.message}\n\n${timeoutErrorMsg}`;
|
||||||
|
}
|
||||||
|
response.status(errorCode).json({ error: error.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Netlify
|
||||||
|
const netlifyHandler = async (event, context, callback) => {
|
||||||
|
const queryParams = event.queryStringParameters || event.query || {};
|
||||||
|
const rawUrl = queryParams.url;
|
||||||
|
|
||||||
|
if (DISABLE_EVERYTHING) {
|
||||||
|
callback(null, {
|
||||||
|
statusCode: 503,
|
||||||
|
body: JSON.stringify({ error: 'Web-Check is temporarily disabled. Please try again later.' }),
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rawUrl) {
|
||||||
|
callback(null, {
|
||||||
|
statusCode: 500,
|
||||||
|
body: JSON.stringify({ error: 'No URL specified' }),
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = normalizeUrl(rawUrl);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Race the handler against the timeout
|
||||||
|
const handlerResponse = await Promise.race([
|
||||||
|
handler(url, event, context),
|
||||||
|
createTimeoutPromise(TIMEOUT)
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (handlerResponse.body && handlerResponse.statusCode) {
|
||||||
|
callback(null, handlerResponse);
|
||||||
} else {
|
} else {
|
||||||
callback(null, {
|
callback(null, {
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
body: typeof response === 'object' ? JSON.stringify(response) : response,
|
body: typeof handlerResponse === 'object' ? JSON.stringify(handlerResponse) : handlerResponse,
|
||||||
|
headers,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
callback(null, {
|
callback(null, {
|
||||||
statusCode: 500,
|
statusCode: 500,
|
||||||
body: JSON.stringify({ error: error.message }),
|
body: JSON.stringify({ error: error.message }),
|
||||||
|
headers,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The format of the handlers varies between platforms
|
||||||
|
const nativeMode = (['VERCEL', 'NODE'].includes(PLATFORM));
|
||||||
|
return nativeMode ? vercelHandler : netlifyHandler;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = commonMiddleware;
|
if (PLATFORM === 'NETLIFY') {
|
||||||
|
module.exports = commonMiddleware;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default commonMiddleware;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
const axios = require('axios');
|
import axios from 'axios';
|
||||||
const middleware = require('./_common/middleware');
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
const convertTimestampToDate = (timestamp) => {
|
const convertTimestampToDate = (timestamp) => {
|
||||||
const [year, month, day, hour, minute, second] = [
|
const [year, month, day, hour, minute, second] = [
|
||||||
@@ -46,7 +46,7 @@ const getScanFrequency = (firstScan, lastScan, totalScans, changeCount) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const getWaybackData = async (url) => {
|
const wayBackHandler = async (url) => {
|
||||||
const cdxUrl = `https://web.archive.org/cdx/search/cdx?url=${url}&output=json&fl=timestamp,statuscode,digest,length,offset`;
|
const cdxUrl = `https://web.archive.org/cdx/search/cdx?url=${url}&output=json&fl=timestamp,statuscode,digest,length,offset`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -80,4 +80,5 @@ const getWaybackData = async (url) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = middleware(getWaybackData);
|
export const handler = middleware(wayBackHandler);
|
||||||
|
export default handler;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const dns = require('dns');
|
import dns from 'dns';
|
||||||
const { URL } = require('url');
|
import { URL } from 'url';
|
||||||
const middleware = require('./_common/middleware');
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
const DNS_SERVERS = [
|
const DNS_SERVERS = [
|
||||||
{ name: 'AdGuard', ip: '176.103.130.130' },
|
{ name: 'AdGuard', ip: '176.103.130.130' },
|
||||||
@@ -94,12 +94,12 @@ const checkDomainAgainstDnsServers = async (domain) => {
|
|||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = middleware(async (url) => {
|
export const blockListHandler = async (url) => {
|
||||||
const domain = new URL(url).hostname;
|
const domain = new URL(url).hostname;
|
||||||
const results = await checkDomainAgainstDnsServers(domain);
|
const results = await checkDomainAgainstDnsServers(domain);
|
||||||
return {
|
return { blocklists: results };
|
||||||
statusCode: 200,
|
};
|
||||||
body: JSON.stringify({ blocklists: results })
|
|
||||||
};
|
export const handler = middleware(blockListHandler);
|
||||||
});
|
export default handler;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const https = require('https');
|
import https from 'https';
|
||||||
const middleware = require('./_common/middleware');
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
const handler = async (url) => {
|
const carbonHandler = async (url) => {
|
||||||
|
|
||||||
// First, get the size of the website's HTML
|
// First, get the size of the website's HTML
|
||||||
const getHtmlSize = (url) => new Promise((resolve, reject) => {
|
const getHtmlSize = (url) => new Promise((resolve, reject) => {
|
||||||
@@ -48,4 +48,5 @@ const handler = async (url) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = middleware(handler);
|
export const handler = middleware(carbonHandler);
|
||||||
|
export default handler;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const axios = require('axios');
|
import axios from 'axios';
|
||||||
const puppeteer = require('puppeteer');
|
import puppeteer from 'puppeteer';
|
||||||
const middleware = require('./_common/middleware');
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
const getPuppeteerCookies = async (url) => {
|
const getPuppeteerCookies = async (url) => {
|
||||||
const browser = await puppeteer.launch({
|
const browser = await puppeteer.launch({
|
||||||
@@ -21,7 +21,7 @@ const getPuppeteerCookies = async (url) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handler = async (url) => {
|
const cookieHandler = async (url) => {
|
||||||
let headerCookies = null;
|
let headerCookies = null;
|
||||||
let clientCookies = null;
|
let clientCookies = null;
|
||||||
|
|
||||||
@@ -54,4 +54,5 @@ const handler = async (url) => {
|
|||||||
return { headerCookies, clientCookies };
|
return { headerCookies, clientCookies };
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = middleware(handler);
|
export const handler = middleware(cookieHandler);
|
||||||
|
export default handler;
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
const dns = require('dns');
|
import { promises as dnsPromises, lookup } from 'dns';
|
||||||
const dnsPromises = dns.promises;
|
import axios from 'axios';
|
||||||
const axios = require('axios');
|
import middleware from './_common/middleware.js';
|
||||||
const commonMiddleware = require('./_common/middleware');
|
|
||||||
|
|
||||||
const handler = async (url) => {
|
const dnsHandler = async (url) => {
|
||||||
try {
|
try {
|
||||||
const domain = url.replace(/^(?:https?:\/\/)?/i, "");
|
const domain = url.replace(/^(?:https?:\/\/)?/i, "");
|
||||||
const addresses = await dnsPromises.resolve4(domain);
|
const addresses = await dnsPromises.resolve4(domain);
|
||||||
@@ -41,4 +40,7 @@ const handler = async (url) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = commonMiddleware(handler);
|
|
||||||
|
export const handler = middleware(dnsHandler);
|
||||||
|
export default handler;
|
||||||
|
|
||||||
|
|||||||
11
api/dns.js
@@ -1,8 +1,8 @@
|
|||||||
const dns = require('dns');
|
import dns from 'dns';
|
||||||
const util = require('util');
|
import util from 'util';
|
||||||
const middleware = require('./_common/middleware');
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
const handler = async (url) => {
|
const dnsHandler = async (url) => {
|
||||||
let hostname = url;
|
let hostname = url;
|
||||||
|
|
||||||
// Handle URLs by extracting hostname
|
// Handle URLs by extracting hostname
|
||||||
@@ -51,4 +51,5 @@ const handler = async (url) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = middleware(handler);
|
export const handler = middleware(dnsHandler);
|
||||||
|
export default handler;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const https = require('https');
|
import https from 'https';
|
||||||
const commonMiddleware = require('./_common/middleware'); // Make sure this path is correct
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
const fetchDNSRecords = async (domain, event, context) => {
|
const dnsSecHandler = async (domain) => {
|
||||||
const dnsTypes = ['DNSKEY', 'DS', 'RRSIG'];
|
const dnsTypes = ['DNSKEY', 'DS', 'RRSIG'];
|
||||||
const records = {};
|
const records = {};
|
||||||
|
|
||||||
@@ -25,7 +25,11 @@ const fetchDNSRecords = async (domain, event, context) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
res.on('end', () => {
|
res.on('end', () => {
|
||||||
resolve(JSON.parse(data));
|
try {
|
||||||
|
resolve(JSON.parse(data));
|
||||||
|
} catch (error) {
|
||||||
|
reject(new Error('Invalid JSON response'));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
res.on('error', error => {
|
res.on('error', error => {
|
||||||
@@ -49,4 +53,5 @@ const fetchDNSRecords = async (domain, event, context) => {
|
|||||||
return records;
|
return records;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = commonMiddleware(fetchDNSRecords);
|
export const handler = middleware(dnsSecHandler);
|
||||||
|
export default handler;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const https = require('https');
|
import https from 'https';
|
||||||
const middleware = require('./_common/middleware');
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
const builtWithHandler = async (url) => {
|
const featuresHandler = async (url) => {
|
||||||
const apiKey = process.env.BUILT_WITH_API_KEY;
|
const apiKey = process.env.BUILT_WITH_API_KEY;
|
||||||
|
|
||||||
if (!url) {
|
if (!url) {
|
||||||
@@ -45,4 +45,5 @@ const builtWithHandler = async (url) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = middleware(builtWithHandler);
|
export const handler = middleware(featuresHandler);
|
||||||
|
export default handler;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
const axios = require('axios');
|
import axios from 'axios';
|
||||||
const middleware = require('./_common/middleware');
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
const hasWaf = (waf) => {
|
const hasWaf = (waf) => {
|
||||||
return {
|
return {
|
||||||
@@ -7,7 +7,7 @@ const hasWaf = (waf) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handler = async (url) => {
|
const firewallHandler = async (url) => {
|
||||||
const fullUrl = url.startsWith('http') ? url : `http://${url}`;
|
const fullUrl = url.startsWith('http') ? url : `http://${url}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -91,6 +91,14 @@ const handler = async (url) => {
|
|||||||
return hasWaf('IBM WebSphere DataPower');
|
return hasWaf('IBM WebSphere DataPower');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (headers['server'] && headers['server'].includes('QRATOR')) {
|
||||||
|
return hasWaf('QRATOR WAF');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers['server'] && headers['server'].includes('ddos-guard')) {
|
||||||
|
return hasWaf('DDoS-Guard WAF');
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
hasWaf: false,
|
hasWaf: false,
|
||||||
}
|
}
|
||||||
@@ -102,4 +110,5 @@ const handler = async (url) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = middleware(handler);
|
export const handler = middleware(firewallHandler);
|
||||||
|
export default handler;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
const dns = require('dns');
|
import dns from 'dns';
|
||||||
const middleware = require('./_common/middleware');
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
const lookupAsync = (address) => {
|
const lookupAsync = (address) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@@ -13,9 +13,11 @@ const lookupAsync = (address) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handler = async (url) => {
|
const ipHandler = async (url) => {
|
||||||
const address = url.replaceAll('https://', '').replaceAll('http://', '');
|
const address = url.replaceAll('https://', '').replaceAll('http://', '');
|
||||||
return await lookupAsync(address);
|
return await lookupAsync(address);
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = middleware(handler);
|
|
||||||
|
export const handler = middleware(ipHandler);
|
||||||
|
export default handler;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const axios = require('axios');
|
import axios from 'axios';
|
||||||
const middleware = require('./_common/middleware');
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
const handler = async (url, event, context) => {
|
const headersHandler = async (url, event, context) => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(url, {
|
const response = await axios.get(url, {
|
||||||
validateStatus: function (status) {
|
validateStatus: function (status) {
|
||||||
@@ -15,4 +15,5 @@ const handler = async (url, event, context) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = middleware(handler);
|
export const handler = middleware(headersHandler);
|
||||||
|
export default handler;
|
||||||
|
|||||||
26
api/hsts.js
@@ -1,18 +1,15 @@
|
|||||||
const https = require('https');
|
import https from 'https';
|
||||||
const middleware = require('./_common/middleware');
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
exports.handler = middleware(async (url, event, context) => {
|
const hstsHandler = async (url, event, context) => {
|
||||||
const errorResponse = (message, statusCode = 500) => {
|
const errorResponse = (message, statusCode = 500) => {
|
||||||
return {
|
return {
|
||||||
statusCode: statusCode,
|
statusCode: statusCode,
|
||||||
body: JSON.stringify({ error: message }),
|
body: JSON.stringify({ error: message }),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
const hstsIncompatible = (message, statusCode = 200) => {
|
const hstsIncompatible = (message, compatible = false, hstsHeader = null ) => {
|
||||||
return {
|
return { message, compatible, hstsHeader };
|
||||||
statusCode: statusCode,
|
|
||||||
body: JSON.stringify({ message, compatible: false }),
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -35,14 +32,7 @@ exports.handler = middleware(async (url, event, context) => {
|
|||||||
} else if (!preload) {
|
} else if (!preload) {
|
||||||
resolve(hstsIncompatible(`HSTS header does not contain the preload directive.`));
|
resolve(hstsIncompatible(`HSTS header does not contain the preload directive.`));
|
||||||
} else {
|
} else {
|
||||||
resolve({
|
resolve(hstsIncompatible(`Site is compatible with the HSTS preload list!`, true, hstsHeader));
|
||||||
statusCode: 200,
|
|
||||||
body: JSON.stringify({
|
|
||||||
message: "Site is compatible with the HSTS preload list!",
|
|
||||||
compatible: true,
|
|
||||||
hstsHeader: hstsHeader,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -53,5 +43,7 @@ exports.handler = middleware(async (url, event, context) => {
|
|||||||
|
|
||||||
req.end();
|
req.end();
|
||||||
});
|
});
|
||||||
});
|
};
|
||||||
|
|
||||||
|
export const handler = middleware(hstsHandler);
|
||||||
|
export default handler;
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
const axios = require('axios');
|
import axios from 'axios';
|
||||||
const middleware = require('./_common/middleware');
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
const handler = async (url) => {
|
const httpsSecHandler = async (url) => {
|
||||||
const fullUrl = url.startsWith('http') ? url : `http://${url}`;
|
const fullUrl = url.startsWith('http') ? url : `http://${url}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(fullUrl);
|
const response = await axios.get(fullUrl);
|
||||||
const headers = response.headers;
|
const headers = response.headers;
|
||||||
return {
|
return {
|
||||||
strictTransportPolicy: headers['strict-transport-policy'] ? true : false,
|
strictTransportPolicy: headers['strict-transport-security'] ? true : false,
|
||||||
xFrameOptions: headers['x-frame-options'] ? true : false,
|
xFrameOptions: headers['x-frame-options'] ? true : false,
|
||||||
xContentTypeOptions: headers['x-content-type-options'] ? true : false,
|
xContentTypeOptions: headers['x-content-type-options'] ? true : false,
|
||||||
xXSSProtection: headers['x-xss-protection'] ? true : false,
|
xXSSProtection: headers['x-xss-protection'] ? true : false,
|
||||||
@@ -22,4 +22,5 @@ const handler = async (url) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = middleware(handler);
|
export const handler = middleware(httpsSecHandler);
|
||||||
|
export default handler;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
const axios = require('axios');
|
import axios from 'axios';
|
||||||
const unzipper = require('unzipper');
|
import unzipper from 'unzipper';
|
||||||
const csv = require('csv-parser');
|
import csv from 'csv-parser';
|
||||||
const fs = require('fs');
|
import fs from 'fs';
|
||||||
const middleware = require('./_common/middleware');
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
// Should also work with the following sources:
|
// Should also work with the following sources:
|
||||||
// https://www.domcop.com/files/top/top10milliondomains.csv.zip
|
// https://www.domcop.com/files/top/top10milliondomains.csv.zip
|
||||||
@@ -14,7 +14,7 @@ const middleware = require('./_common/middleware');
|
|||||||
const FILE_URL = 'https://s3-us-west-1.amazonaws.com/umbrella-static/top-1m.csv.zip';
|
const FILE_URL = 'https://s3-us-west-1.amazonaws.com/umbrella-static/top-1m.csv.zip';
|
||||||
const TEMP_FILE_PATH = '/tmp/top-1m.csv';
|
const TEMP_FILE_PATH = '/tmp/top-1m.csv';
|
||||||
|
|
||||||
const handler = async (url) => {
|
const rankHandler = async (url) => {
|
||||||
let domain = null;
|
let domain = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -66,5 +66,5 @@ return new Promise((resolve, reject) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = middleware(handler);
|
export const handler = middleware(rankHandler);
|
||||||
|
export default handler;
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
const axios = require('axios');
|
import axios from 'axios';
|
||||||
const cheerio = require('cheerio');
|
import cheerio from 'cheerio';
|
||||||
const urlLib = require('url');
|
import urlLib from 'url';
|
||||||
const commonMiddleware = require('./_common/middleware');
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
const handler = async (url) => {
|
const linkedPagesHandler = async (url) => {
|
||||||
const response = await axios.get(url);
|
const response = await axios.get(url);
|
||||||
const html = response.data;
|
const html = response.data;
|
||||||
const $ = cheerio.load(html);
|
const $ = cheerio.load(html);
|
||||||
@@ -33,16 +33,17 @@ const handler = async (url) => {
|
|||||||
if (internalLinks.length === 0 && externalLinks.length === 0) {
|
if (internalLinks.length === 0 && externalLinks.length === 0) {
|
||||||
return {
|
return {
|
||||||
statusCode: 400,
|
statusCode: 400,
|
||||||
body: JSON.stringify({
|
body: {
|
||||||
skipped: 'No internal or external links found. '
|
skipped: 'No internal or external links found. '
|
||||||
+ 'This may be due to the website being dynamically rendered, using a client-side framework (like React), and without SSR enabled. '
|
+ 'This may be due to the website being dynamically rendered, using a client-side framework (like React), and without SSR enabled. '
|
||||||
+ 'That would mean that the static HTML returned from the HTTP request doesn\'t contain any meaningful content for Web-Check to analyze. '
|
+ 'That would mean that the static HTML returned from the HTTP request doesn\'t contain any meaningful content for Web-Check to analyze. '
|
||||||
+ 'You can rectify this by using a headless browser to render the page instead.',
|
+ 'You can rectify this by using a headless browser to render the page instead.',
|
||||||
}),
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return { internal: internalLinks, external: externalLinks };
|
return { internal: internalLinks, external: externalLinks };
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = commonMiddleware(handler);
|
export const handler = middleware(linkedPagesHandler);
|
||||||
|
export default handler;
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
const commonMiddleware = require('./_common/middleware');
|
import dns from 'dns';
|
||||||
|
import URL from 'url-parse';
|
||||||
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
const dns = require('dns').promises;
|
// TODO: Fix.
|
||||||
const URL = require('url-parse');
|
|
||||||
|
|
||||||
const handler = async (url, event, context) => {
|
const mailConfigHandler = async (url, event, context) => {
|
||||||
try {
|
try {
|
||||||
const domain = new URL(url).hostname || new URL(url).pathname;
|
const domain = new URL(url).hostname || new URL(url).pathname;
|
||||||
|
|
||||||
@@ -54,6 +55,11 @@ const handler = async (url, event, context) => {
|
|||||||
if (yahooMx.length > 0) {
|
if (yahooMx.length > 0) {
|
||||||
mailServices.push({ provider: 'Yahoo', value: yahooMx[0].exchange });
|
mailServices.push({ provider: 'Yahoo', value: yahooMx[0].exchange });
|
||||||
}
|
}
|
||||||
|
// Check MX records for Mimecast
|
||||||
|
const mimecastMx = mxRecords.filter(record => record.exchange.includes('mimecast.com'));
|
||||||
|
if (mimecastMx.length > 0) {
|
||||||
|
mailServices.push({ provider: 'Mimecast', value: mimecastMx[0].exchange });
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
mxRecords,
|
mxRecords,
|
||||||
@@ -66,10 +72,11 @@ const handler = async (url, event, context) => {
|
|||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
statusCode: 500,
|
statusCode: 500,
|
||||||
body: JSON.stringify({ error: error.message }),
|
body: { error: error.message },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.handler = commonMiddleware(handler);
|
export const handler = middleware(mailConfigHandler);
|
||||||
|
export default handler;
|
||||||
|
|||||||
23
api/ports.js
@@ -1,5 +1,5 @@
|
|||||||
const net = require('net');
|
import net from 'net';
|
||||||
const middleware = require('./_common/middleware');
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
// A list of commonly used ports.
|
// A list of commonly used ports.
|
||||||
const PORTS = [
|
const PORTS = [
|
||||||
@@ -34,7 +34,7 @@ async function checkPort(port, domain) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const handler = async (url, event, context) => {
|
const portsHandler = async (url, event, context) => {
|
||||||
const domain = url.replace(/(^\w+:|^)\/\//, '');
|
const domain = url.replace(/(^\w+:|^)\/\//, '');
|
||||||
|
|
||||||
const delay = ms => new Promise(res => setTimeout(res, ms));
|
const delay = ms => new Promise(res => setTimeout(res, ms));
|
||||||
@@ -73,17 +73,16 @@ const handler = async (url, event, context) => {
|
|||||||
return errorResponse('The function timed out before completing.');
|
return errorResponse('The function timed out before completing.');
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
// Sort openPorts and failedPorts before returning
|
||||||
statusCode: 200,
|
openPorts.sort((a, b) => a - b);
|
||||||
body: JSON.stringify({ openPorts, failedPorts }),
|
failedPorts.sort((a, b) => a - b);
|
||||||
};
|
|
||||||
|
return { openPorts, failedPorts };
|
||||||
};
|
};
|
||||||
|
|
||||||
const errorResponse = (message, statusCode = 444) => {
|
const errorResponse = (message, statusCode = 444) => {
|
||||||
return {
|
return { error: message };
|
||||||
statusCode: statusCode,
|
|
||||||
body: JSON.stringify({ error: message }),
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = middleware(handler);
|
export const handler = middleware(portsHandler);
|
||||||
|
export default handler;
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
const axios = require('axios');
|
import axios from 'axios';
|
||||||
const middleware = require('./_common/middleware');
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
const handler = async (url, event, context) => {
|
const qualityHandler = async (url, event, context) => {
|
||||||
const apiKey = process.env.GOOGLE_CLOUD_API_KEY;
|
const apiKey = process.env.GOOGLE_CLOUD_API_KEY;
|
||||||
|
|
||||||
if (!url) {
|
|
||||||
throw new Error('URL param is required');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
throw new Error('API key (GOOGLE_CLOUD_API_KEY) not set');
|
throw new Error(
|
||||||
|
'Missing Google API. You need to set the `GOOGLE_CLOUD_API_KEY` environment variable'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const endpoint = `https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=${encodeURIComponent(url)}&category=PERFORMANCE&category=ACCESSIBILITY&category=BEST_PRACTICES&category=SEO&category=PWA&strategy=mobile&key=${apiKey}`;
|
const endpoint = `https://www.googleapis.com/pagespeedonline/v5/runPagespeed?`
|
||||||
|
+ `url=${encodeURIComponent(url)}&category=PERFORMANCE&category=ACCESSIBILITY`
|
||||||
|
+ `&category=BEST_PRACTICES&category=SEO&category=PWA&strategy=mobile`
|
||||||
|
+ `&key=${apiKey}`;
|
||||||
|
|
||||||
const response = await axios.get(endpoint);
|
return (await axios.get(endpoint)).data;
|
||||||
|
|
||||||
return response.data;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = middleware(handler);
|
export const handler = middleware(qualityHandler);
|
||||||
|
export default handler;
|
||||||
|
|||||||
12
api/rank.js
@@ -1,7 +1,7 @@
|
|||||||
const axios = require('axios');
|
import axios from 'axios';
|
||||||
const middleware = require('./_common/middleware');
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
const handler = async (url) => {
|
const rankHandler = async (url) => {
|
||||||
const domain = url ? new URL(url).hostname : null;
|
const domain = url ? new URL(url).hostname : null;
|
||||||
if (!domain) throw new Error('Invalid URL');
|
if (!domain) throw new Error('Invalid URL');
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ const handler = async (url) => {
|
|||||||
{ auth: { username: process.env.TRANCO_USERNAME, password: process.env.TRANCO_API_KEY } }
|
{ auth: { username: process.env.TRANCO_USERNAME, password: process.env.TRANCO_API_KEY } }
|
||||||
: {};
|
: {};
|
||||||
const response = await axios.get(
|
const response = await axios.get(
|
||||||
`https://tranco-list.eu/api/ranks/domain/${domain}`, { timeout: 2000 }, auth,
|
`https://tranco-list.eu/api/ranks/domain/${domain}`, { timeout: 5000 }, auth,
|
||||||
);
|
);
|
||||||
if (!response.data || !response.data.ranks || response.data.ranks.length === 0) {
|
if (!response.data || !response.data.ranks || response.data.ranks.length === 0) {
|
||||||
return { skipped: `Skipping, as ${domain} isn't ranked in the top 100 million sites yet.`};
|
return { skipped: `Skipping, as ${domain} isn't ranked in the top 100 million sites yet.`};
|
||||||
@@ -21,4 +21,6 @@ const handler = async (url) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = middleware(handler);
|
export const handler = middleware(rankHandler);
|
||||||
|
export default handler;
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
const handler = async (url) => {
|
import got from 'got';
|
||||||
const redirects = [url];
|
import middleware from './_common/middleware.js';
|
||||||
const got = await import('got');
|
|
||||||
|
|
||||||
|
const redirectsHandler = async (url) => {
|
||||||
|
const redirects = [url];
|
||||||
try {
|
try {
|
||||||
await got.default(url, {
|
await got(url, {
|
||||||
followRedirect: true,
|
followRedirect: true,
|
||||||
maxRedirects: 12,
|
maxRedirects: 12,
|
||||||
hooks: {
|
hooks: {
|
||||||
@@ -23,5 +24,5 @@ const handler = async (url) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const middleware = require('./_common/middleware');
|
export const handler = middleware(redirectsHandler);
|
||||||
exports.handler = middleware(handler);
|
export default handler;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
const axios = require('axios');
|
import axios from 'axios';
|
||||||
const middleware = require('./_common/middleware');
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
const parseRobotsTxt = (content) => {
|
const parseRobotsTxt = (content) => {
|
||||||
const lines = content.split('\n');
|
const lines = content.split('\n');
|
||||||
@@ -31,7 +31,7 @@ const parseRobotsTxt = (content) => {
|
|||||||
return { robots: rules };
|
return { robots: rules };
|
||||||
}
|
}
|
||||||
|
|
||||||
const handler = async function(url) {
|
const robotsHandler = async function(url) {
|
||||||
let parsedURL;
|
let parsedURL;
|
||||||
try {
|
try {
|
||||||
parsedURL = new URL(url);
|
parsedURL = new URL(url);
|
||||||
@@ -67,4 +67,5 @@ const handler = async function(url) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = middleware(handler);
|
export const handler = middleware(robotsHandler);
|
||||||
|
export default handler;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const puppeteer = require('puppeteer-core');
|
import puppeteer from 'puppeteer-core';
|
||||||
const chromium = require('chrome-aws-lambda');
|
import chromium from 'chrome-aws-lambda';
|
||||||
const middleware = require('./_common/middleware');
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
const screenshotHandler = async (targetUrl) => {
|
const screenshotHandler = async (targetUrl) => {
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ const screenshotHandler = async (targetUrl) => {
|
|||||||
let browser = null;
|
let browser = null;
|
||||||
try {
|
try {
|
||||||
browser = await puppeteer.launch({
|
browser = await puppeteer.launch({
|
||||||
args: chromium.args,
|
args: [...chromium.args, '--no-sandbox'], // Add --no-sandbox flag
|
||||||
defaultViewport: { width: 800, height: 600 },
|
defaultViewport: { width: 800, height: 600 },
|
||||||
executablePath: process.env.CHROME_PATH || await chromium.executablePath,
|
executablePath: process.env.CHROME_PATH || await chromium.executablePath,
|
||||||
headless: chromium.headless,
|
headless: chromium.headless,
|
||||||
@@ -58,4 +58,5 @@ const screenshotHandler = async (targetUrl) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = middleware(screenshotHandler);
|
export const handler = middleware(screenshotHandler);
|
||||||
|
export default handler;
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
const { https } = require('follow-redirects');
|
import { URL } from 'url';
|
||||||
const { URL } = require('url');
|
import followRedirects from 'follow-redirects';
|
||||||
const middleware = require('./_common/middleware');
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
|
const { https } = followRedirects;
|
||||||
|
|
||||||
const SECURITY_TXT_PATHS = [
|
const SECURITY_TXT_PATHS = [
|
||||||
'/security.txt',
|
'/security.txt',
|
||||||
@@ -69,8 +71,6 @@ const securityTxtHandler = async (urlParam) => {
|
|||||||
return { isPresent: false };
|
return { isPresent: false };
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = middleware(securityTxtHandler);
|
|
||||||
|
|
||||||
async function fetchSecurityTxt(baseURL, path) {
|
async function fetchSecurityTxt(baseURL, path) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const url = new URL(path, baseURL);
|
const url = new URL(path, baseURL);
|
||||||
@@ -91,3 +91,6 @@ async function fetchSecurityTxt(baseURL, path) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const handler = middleware(securityTxtHandler);
|
||||||
|
export default handler;
|
||||||
|
|||||||
@@ -1,20 +1,21 @@
|
|||||||
const commonMiddleware = require('./_common/middleware');
|
import axios from 'axios';
|
||||||
|
import xml2js from 'xml2js';
|
||||||
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
const axios = require('axios');
|
const sitemapHandler = async (url) => {
|
||||||
const xml2js = require('xml2js');
|
|
||||||
|
|
||||||
const handler = async (url) => {
|
|
||||||
let sitemapUrl = `${url}/sitemap.xml`;
|
let sitemapUrl = `${url}/sitemap.xml`;
|
||||||
|
|
||||||
|
const hardTimeOut = 5000;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Try to fetch sitemap directly
|
// Try to fetch sitemap directly
|
||||||
let sitemapRes;
|
let sitemapRes;
|
||||||
try {
|
try {
|
||||||
sitemapRes = await axios.get(sitemapUrl, { timeout: 5000 });
|
sitemapRes = await axios.get(sitemapUrl, { timeout: hardTimeOut });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.response && error.response.status === 404) {
|
if (error.response && error.response.status === 404) {
|
||||||
// If sitemap not found, try to fetch it from robots.txt
|
// If sitemap not found, try to fetch it from robots.txt
|
||||||
const robotsRes = await axios.get(`${url}/robots.txt`, { timeout: 5000 });
|
const robotsRes = await axios.get(`${url}/robots.txt`, { timeout: hardTimeOut });
|
||||||
const robotsTxt = robotsRes.data.split('\n');
|
const robotsTxt = robotsRes.data.split('\n');
|
||||||
|
|
||||||
for (let line of robotsTxt) {
|
for (let line of robotsTxt) {
|
||||||
@@ -25,13 +26,10 @@ const handler = async (url) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!sitemapUrl) {
|
if (!sitemapUrl) {
|
||||||
return {
|
return { skipped: 'No sitemap found' };
|
||||||
statusCode: 404,
|
|
||||||
body: JSON.stringify({ skipped: 'No sitemap found' }),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sitemapRes = await axios.get(sitemapUrl, { timeout: 5000 });
|
sitemapRes = await axios.get(sitemapUrl, { timeout: hardTimeOut });
|
||||||
} else {
|
} else {
|
||||||
throw error; // If other error, throw it
|
throw error; // If other error, throw it
|
||||||
}
|
}
|
||||||
@@ -40,25 +38,16 @@ const handler = async (url) => {
|
|||||||
const parser = new xml2js.Parser();
|
const parser = new xml2js.Parser();
|
||||||
const sitemap = await parser.parseStringPromise(sitemapRes.data);
|
const sitemap = await parser.parseStringPromise(sitemapRes.data);
|
||||||
|
|
||||||
return {
|
return sitemap;
|
||||||
statusCode: 200,
|
|
||||||
body: JSON.stringify(sitemap),
|
|
||||||
};
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// If error occurs
|
|
||||||
console.log(error.message);
|
|
||||||
if (error.code === 'ECONNABORTED') {
|
if (error.code === 'ECONNABORTED') {
|
||||||
return {
|
return { error: `Request timed-out after ${hardTimeOut}ms` };
|
||||||
statusCode: 500,
|
|
||||||
body: JSON.stringify({ error: 'Request timed out' }),
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
return {
|
return { error: error.message };
|
||||||
statusCode: 500,
|
|
||||||
body: JSON.stringify({ error: error.message }),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = commonMiddleware(handler);
|
export const handler = middleware(sitemapHandler);
|
||||||
|
export default handler;
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
const commonMiddleware = require('./_common/middleware');
|
import axios from 'axios';
|
||||||
|
import cheerio from 'cheerio';
|
||||||
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
const axios = require('axios');
|
const socialTagsHandler = async (url) => {
|
||||||
const cheerio = require('cheerio');
|
|
||||||
|
|
||||||
const handler = async (url) => {
|
|
||||||
|
|
||||||
// Check if url includes protocol
|
// Check if url includes protocol
|
||||||
if (!url.startsWith('http://') && !url.startsWith('https://')) {
|
if (!url.startsWith('http://') && !url.startsWith('https://')) {
|
||||||
@@ -50,16 +49,9 @@ const handler = async (url) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (Object.keys(metadata).length === 0) {
|
if (Object.keys(metadata).length === 0) {
|
||||||
return {
|
return { skipped: 'No metadata found' };
|
||||||
statusCode: 200,
|
|
||||||
body: JSON.stringify({ skipped: 'No metadata found' }),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
return metadata;
|
||||||
return {
|
|
||||||
statusCode: 200,
|
|
||||||
body: JSON.stringify(metadata),
|
|
||||||
};
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return {
|
return {
|
||||||
statusCode: 500,
|
statusCode: 500,
|
||||||
@@ -68,4 +60,5 @@ const handler = async (url) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = commonMiddleware(handler);
|
export const handler = middleware(socialTagsHandler);
|
||||||
|
export default handler;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const tls = require('tls');
|
import tls from 'tls';
|
||||||
const middleware = require('./_common/middleware');
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
const fetchSiteCertificateHandler = async (urlString) => {
|
const sslHandler = async (urlString) => {
|
||||||
try {
|
try {
|
||||||
const parsedUrl = new URL(urlString);
|
const parsedUrl = new URL(urlString);
|
||||||
const options = {
|
const options = {
|
||||||
@@ -40,4 +40,5 @@ const fetchSiteCertificateHandler = async (urlString) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = middleware(fetchSiteCertificateHandler);
|
export const handler = middleware(sslHandler);
|
||||||
|
export default handler;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
const https = require('https');
|
import https from 'https';
|
||||||
const { performance, PerformanceObserver } = require('perf_hooks');
|
import { performance, PerformanceObserver } from 'perf_hooks';
|
||||||
const middleware = require('./_common/middleware');
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
const checkURLHandler = async (url) => {
|
const statusHandler = async (url) => {
|
||||||
if (!url) {
|
if (!url) {
|
||||||
throw new Error('You must provide a URL query parameter!');
|
throw new Error('You must provide a URL query parameter!');
|
||||||
}
|
}
|
||||||
@@ -55,4 +55,5 @@ const checkURLHandler = async (url) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = middleware(checkURLHandler);
|
export const handler = middleware(statusHandler);
|
||||||
|
export default handler;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const Wappalyzer = require('wappalyzer');
|
import Wappalyzer from 'wappalyzer';
|
||||||
const middleware = require('./_common/middleware');
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
const analyzeSiteTechnologies = async (url) => {
|
const techStackHandler = async (url) => {
|
||||||
const options = {};
|
const options = {};
|
||||||
|
|
||||||
const wappalyzer = new Wappalyzer(options);
|
const wappalyzer = new Wappalyzer(options);
|
||||||
@@ -27,4 +27,5 @@ const analyzeSiteTechnologies = async (url) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = middleware(analyzeSiteTechnologies);
|
export const handler = middleware(techStackHandler);
|
||||||
|
export default handler;
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
const axios = require('axios');
|
import axios from 'axios';
|
||||||
const xml2js = require('xml2js');
|
import xml2js from 'xml2js';
|
||||||
const middleware = require('./_common/middleware');
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
const getGoogleSafeBrowsingResult = async (url) => {
|
const getGoogleSafeBrowsingResult = async (url) => {
|
||||||
try {
|
try {
|
||||||
const apiKey = process.env.GOOGLE_CLOUD_API_KEY;
|
const apiKey = process.env.GOOGLE_CLOUD_API_KEY;
|
||||||
|
if (!apiKey) {
|
||||||
|
return { error: 'GOOGLE_CLOUD_API_KEY is required for the Google Safe Browsing check' };
|
||||||
|
}
|
||||||
const apiEndpoint = `https://safebrowsing.googleapis.com/v4/threatMatches:find?key=${apiKey}`;
|
const apiEndpoint = `https://safebrowsing.googleapis.com/v4/threatMatches:find?key=${apiKey}`;
|
||||||
|
|
||||||
const requestBody = {
|
const requestBody = {
|
||||||
@@ -63,11 +66,15 @@ const getPhishTankResult = async (url) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const getCloudmersiveResult = async (url) => {
|
const getCloudmersiveResult = async (url) => {
|
||||||
|
const apiKey = process.env.CLOUDMERSIVE_API_KEY;
|
||||||
|
if (!apiKey) {
|
||||||
|
return { error: 'CLOUDMERSIVE_API_KEY is required for the Cloudmersive check' };
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const endpoint = 'https://api.cloudmersive.com/virus/scan/website';
|
const endpoint = 'https://api.cloudmersive.com/virus/scan/website';
|
||||||
const headers = {
|
const headers = {
|
||||||
'Content-Type': 'application/x-www-form-urlencoded',
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
'Apikey': process.env.CLOUDMERSIVE_API_KEY,
|
'Apikey': apiKey,
|
||||||
};
|
};
|
||||||
const data = `Url=${encodeURIComponent(url)}`;
|
const data = `Url=${encodeURIComponent(url)}`;
|
||||||
const response = await axios.post(endpoint, data, { headers });
|
const response = await axios.post(endpoint, data, { headers });
|
||||||
@@ -77,7 +84,7 @@ const getCloudmersiveResult = async (url) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handler = async (url) => {
|
const threatsHandler = async (url) => {
|
||||||
try {
|
try {
|
||||||
const urlHaus = await getUrlHausResult(url);
|
const urlHaus = await getUrlHausResult(url);
|
||||||
const phishTank = await getPhishTankResult(url);
|
const phishTank = await getPhishTankResult(url);
|
||||||
@@ -92,4 +99,5 @@ const handler = async (url) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = middleware(handler);
|
export const handler = middleware(threatsHandler);
|
||||||
|
export default handler;
|
||||||
|
|||||||
13
api/tls.js
@@ -1,9 +1,9 @@
|
|||||||
const axios = require('axios');
|
import axios from 'axios';
|
||||||
const middleware = require('./_common/middleware');
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
const MOZILLA_TLS_OBSERVATORY_API = 'https://tls-observatory.services.mozilla.com/api/v1';
|
const MOZILLA_TLS_OBSERVATORY_API = 'https://tls-observatory.services.mozilla.com/api/v1';
|
||||||
|
|
||||||
const handler = async (url) => {
|
const tlsHandler = async (url) => {
|
||||||
try {
|
try {
|
||||||
const domain = new URL(url).hostname;
|
const domain = new URL(url).hostname;
|
||||||
const scanResponse = await axios.post(`${MOZILLA_TLS_OBSERVATORY_API}/scan?target=${domain}`);
|
const scanResponse = await axios.post(`${MOZILLA_TLS_OBSERVATORY_API}/scan?target=${domain}`);
|
||||||
@@ -12,17 +12,18 @@ const handler = async (url) => {
|
|||||||
if (typeof scanId !== 'number') {
|
if (typeof scanId !== 'number') {
|
||||||
return {
|
return {
|
||||||
statusCode: 500,
|
statusCode: 500,
|
||||||
body: JSON.stringify({ error: 'Failed to get scan_id from TLS Observatory' }),
|
body: { error: 'Failed to get scan_id from TLS Observatory' },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const resultResponse = await axios.get(`${MOZILLA_TLS_OBSERVATORY_API}/results?id=${scanId}`);
|
const resultResponse = await axios.get(`${MOZILLA_TLS_OBSERVATORY_API}/results?id=${scanId}`);
|
||||||
return {
|
return {
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
body: JSON.stringify(resultResponse.data),
|
body: resultResponse.data,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return { error: error.message };
|
return { error: error.message };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = middleware(handler);
|
export const handler = middleware(tlsHandler);
|
||||||
|
export default handler;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
const traceroute = require('traceroute');
|
import url from 'url';
|
||||||
const url = require('url');
|
import traceroute from 'traceroute';
|
||||||
const middleware = require('./_common/middleware');
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
const executeTraceroute = async (urlString, context) => {
|
const traceRouteHandler = async (urlString, context) => {
|
||||||
// Parse the URL and get the hostname
|
// Parse the URL and get the hostname
|
||||||
const urlObject = url.parse(urlString);
|
const urlObject = url.parse(urlString);
|
||||||
const host = urlObject.hostname;
|
const host = urlObject.hostname;
|
||||||
@@ -28,4 +28,5 @@ const executeTraceroute = async (urlString, context) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = middleware(executeTraceroute);
|
export const handler = middleware(traceRouteHandler);
|
||||||
|
export default handler;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const dns = require('dns').promises;
|
import dns from 'dns/promises';
|
||||||
const middleware = require('./_common/middleware');
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
const handler = async (url, event, context) => {
|
const txtRecordHandler = async (url, event, context) => {
|
||||||
try {
|
try {
|
||||||
const parsedUrl = new URL(url);
|
const parsedUrl = new URL(url);
|
||||||
|
|
||||||
@@ -29,4 +29,5 @@ const handler = async (url, event, context) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = middleware(handler);
|
export const handler = middleware(txtRecordHandler);
|
||||||
|
export default handler;
|
||||||
|
|||||||
14
api/whois.js
@@ -1,7 +1,7 @@
|
|||||||
const net = require('net');
|
import net from 'net';
|
||||||
const psl = require('psl');
|
import psl from 'psl';
|
||||||
const axios = require('axios');
|
import axios from 'axios';
|
||||||
const middleware = require('./_common/middleware');
|
import middleware from './_common/middleware.js';
|
||||||
|
|
||||||
const getBaseDomain = (url) => {
|
const getBaseDomain = (url) => {
|
||||||
let protocol = '';
|
let protocol = '';
|
||||||
@@ -83,7 +83,7 @@ const fetchFromMyAPI = async (hostname) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchWhoisData = async (url) => {
|
const whoisHandler = async (url) => {
|
||||||
if (!url.startsWith('http://') && !url.startsWith('https://')) {
|
if (!url.startsWith('http://') && !url.startsWith('https://')) {
|
||||||
url = 'http://' + url;
|
url = 'http://' + url;
|
||||||
}
|
}
|
||||||
@@ -106,4 +106,6 @@ const fetchWhoisData = async (url) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.handler = middleware(fetchWhoisData);
|
export const handler = middleware(whoisHandler);
|
||||||
|
export default handler;
|
||||||
|
|
||||||
|
|||||||
79
astro.config.mjs
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
import { defineConfig } from 'astro/config';
|
||||||
|
|
||||||
|
// Integrations
|
||||||
|
import svelte from '@astrojs/svelte';
|
||||||
|
import react from "@astrojs/react";
|
||||||
|
import partytown from '@astrojs/partytown';
|
||||||
|
import sitemap from '@astrojs/sitemap';
|
||||||
|
|
||||||
|
// Adapters
|
||||||
|
import vercelAdapter from '@astrojs/vercel/serverless';
|
||||||
|
import netlifyAdapter from '@astrojs/netlify';
|
||||||
|
import nodeAdapter from '@astrojs/node';
|
||||||
|
import cloudflareAdapter from '@astrojs/cloudflare';
|
||||||
|
|
||||||
|
// Helper function to unwrap both Vite and Node environment variables
|
||||||
|
const unwrapEnvVar = (varName, fallbackValue) => {
|
||||||
|
const classicEnvVar = process?.env && process.env[varName];
|
||||||
|
const viteEnvVar = import.meta.env[varName];
|
||||||
|
return classicEnvVar || viteEnvVar || fallbackValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the deploy target (vercel, netlify, cloudflare, node)
|
||||||
|
const deployTarget = unwrapEnvVar('PLATFORM', 'node').toLowerCase();
|
||||||
|
|
||||||
|
// Determine the output mode (server, hybrid or static)
|
||||||
|
const output = unwrapEnvVar('OUTPUT', 'hybrid');
|
||||||
|
|
||||||
|
// The FQDN of where the site is hosted (used for sitemaps & canonical URLs)
|
||||||
|
const site = unwrapEnvVar('SITE_URL', 'https://web-check.xyz');
|
||||||
|
|
||||||
|
// The base URL of the site (if serving from a subdirectory)
|
||||||
|
const base = unwrapEnvVar('BASE_URL', '/');
|
||||||
|
|
||||||
|
// Should run the app in boss-mode (requires extra configuration)
|
||||||
|
const isBossServer = unwrapEnvVar('BOSS_SERVER', false);
|
||||||
|
|
||||||
|
// Initialize Astro integrations
|
||||||
|
const integrations = [svelte(), react(), partytown(), sitemap()];
|
||||||
|
|
||||||
|
// Set the appropriate adapter, based on the deploy target
|
||||||
|
function getAdapter(target) {
|
||||||
|
switch(target) {
|
||||||
|
case 'vercel':
|
||||||
|
return vercelAdapter();
|
||||||
|
case 'netlify':
|
||||||
|
return netlifyAdapter();
|
||||||
|
case 'cloudflare':
|
||||||
|
return cloudflareAdapter();
|
||||||
|
case 'node':
|
||||||
|
return nodeAdapter({ mode: 'middleware' });
|
||||||
|
default:
|
||||||
|
throw new Error(`Unsupported deploy target: ${target}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const adapter = getAdapter(deployTarget);
|
||||||
|
|
||||||
|
// Print build information to console
|
||||||
|
console.log(
|
||||||
|
`\n\x1b[1m\x1b[35m Preparing to start build of Web Check.... \x1b[0m\n`,
|
||||||
|
`\x1b[35m\x1b[2mCompiling for "${deployTarget}" using "${output}" mode, `
|
||||||
|
+ `to deploy to "${site}" at "${base}"\x1b[0m\n`,
|
||||||
|
`\x1b[2m\x1b[36m🛟 For documentation and support, visit the GitHub repo: ` +
|
||||||
|
`https://github.com/lissy93/web-check \n`,
|
||||||
|
`💖 Found Web-Check useful? Consider sponsoring us on GitHub ` +
|
||||||
|
`to help fund maintenance & development.\x1b[0m\n`,
|
||||||
|
);
|
||||||
|
|
||||||
|
const redirects = {
|
||||||
|
'/about': '/check/about',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Skip the marketing homepage for self-hosted users
|
||||||
|
if (!isBossServer && isBossServer !== true) {
|
||||||
|
redirects['/'] = '/check';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Export Astro configuration
|
||||||
|
export default defineConfig({ output, base, integrations, site, adapter, redirects });
|
||||||
|
|
||||||
17
fly.toml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
app = 'web-check'
|
||||||
|
primary_region = 'lhr'
|
||||||
|
|
||||||
|
[build]
|
||||||
|
|
||||||
|
[http_service]
|
||||||
|
internal_port = 3000
|
||||||
|
force_https = true
|
||||||
|
auto_stop_machines = true
|
||||||
|
auto_start_machines = true
|
||||||
|
min_machines_running = 0
|
||||||
|
processes = ['app']
|
||||||
|
|
||||||
|
[[vm]]
|
||||||
|
memory = '1gb'
|
||||||
|
cpu_kind = 'shared'
|
||||||
|
cpus = 1
|
||||||
12
netlify.toml
@@ -2,11 +2,13 @@
|
|||||||
[build]
|
[build]
|
||||||
base = "/"
|
base = "/"
|
||||||
command = "yarn build"
|
command = "yarn build"
|
||||||
publish = "build"
|
publish = "dist"
|
||||||
functions = "api"
|
functions = "api"
|
||||||
|
|
||||||
# Environmental variables and optioanl secrets
|
# Environmental variables and optional secrets
|
||||||
[build.environment]
|
[build.environment]
|
||||||
|
PLATFORM = "netlify"
|
||||||
|
PUBLIC_API_ENDPOINT = "/.netlify/functions"
|
||||||
# Build configuration env vars (uncomment if you want to conigure these)
|
# Build configuration env vars (uncomment if you want to conigure these)
|
||||||
# CI="false" # Set CI to false, to prevent warnings from exiting the build
|
# CI="false" # Set CI to false, to prevent warnings from exiting the build
|
||||||
# CHROME_PATH='/usr/bin/chromium' # Path to Chromium binary
|
# CHROME_PATH='/usr/bin/chromium' # Path to Chromium binary
|
||||||
@@ -25,12 +27,6 @@
|
|||||||
status = 301
|
status = 301
|
||||||
force = true
|
force = true
|
||||||
|
|
||||||
# For router history mode, ensure pages land on index
|
|
||||||
[[redirects]]
|
|
||||||
from = "/*"
|
|
||||||
to = "/index.html"
|
|
||||||
status = 200
|
|
||||||
|
|
||||||
# Plugins
|
# Plugins
|
||||||
[[plugins]]
|
[[plugins]]
|
||||||
package = "netlify-plugin-chromium"
|
package = "netlify-plugin-chromium"
|
||||||
|
|||||||
133
package.json
@@ -1,100 +1,73 @@
|
|||||||
{
|
{
|
||||||
"name": "web-check",
|
"name": "web-check",
|
||||||
"version": "1.0.0",
|
"type": "module",
|
||||||
"private": false,
|
"version": "2.0.0",
|
||||||
"description": "All-in-one OSINT tool for analyzing any website",
|
"homepage": "https://web-check.xyz",
|
||||||
"repository": "github:lissy93/web-check",
|
|
||||||
"homepage": "https://web-check.as93.net",
|
|
||||||
"license": "MIT",
|
|
||||||
"author": {
|
|
||||||
"name": "Alicia Sykes",
|
|
||||||
"email": "alicia@omg.lol"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/Lissy93"
|
|
||||||
},
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "netlify dev",
|
"start": "node server",
|
||||||
"serve": "node server",
|
"start-pm": "pm2 start server.js -i max",
|
||||||
"start": "react-scripts start",
|
"build": "astro check && astro build",
|
||||||
"build": "react-scripts build",
|
"dev:vercel": "PLATFORM='vercel' npx vercel dev",
|
||||||
"test": "react-scripts test",
|
"dev:netlify": "PLATFORM='netlify' npx netlify dev",
|
||||||
"eject": "react-scripts eject"
|
"dev:api": "DISABLE_GUI='true' PORT='3001' nodemon server",
|
||||||
|
"dev:astro": "PUBLIC_API_ENDPOINT=http://localhost:3001/api astro dev",
|
||||||
|
"dev": "concurrently -c magenta,cyan -n backend,frontend 'yarn dev:api' 'yarn dev:astro'"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@netlify/functions": "^1.6.0",
|
"@astrojs/check": "^0.5.10",
|
||||||
"@sentry/react": "^7.60.0",
|
"@astrojs/react": "^3.3.2",
|
||||||
"@testing-library/jest-dom": "^5.17.0",
|
"@emotion/react": "^11.11.4",
|
||||||
"@testing-library/react": "^14.0.0",
|
"@emotion/styled": "^11.11.5",
|
||||||
"@testing-library/user-event": "^14.4.3",
|
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
||||||
"@types/jest": "^29.5.3",
|
"@fortawesome/free-brands-svg-icons": "^6.5.2",
|
||||||
"@types/node": "^20.4.4",
|
"@fortawesome/free-regular-svg-icons": "^6.5.2",
|
||||||
"@types/react": "^18.2.15",
|
"@fortawesome/free-solid-svg-icons": "^6.5.2",
|
||||||
"@types/react-dom": "^18.2.7",
|
"@fortawesome/svelte-fontawesome": "^0.2.2",
|
||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react": "^18.3.1",
|
||||||
"@types/react-simple-maps": "^3.0.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
"@types/styled-components": "^5.1.26",
|
"astro": "^4.7.1",
|
||||||
"aws-serverless-express": "^3.4.0",
|
"axios": "^1.4.8",
|
||||||
"axios": "^1.4.0",
|
|
||||||
"cheerio": "^1.0.0-rc.12",
|
"cheerio": "^1.0.0-rc.12",
|
||||||
"chrome-aws-lambda": "^10.1.0",
|
"chrome-aws-lambda": "^10.1.0",
|
||||||
"chromium": "^3.0.3",
|
"chromium": "^3.0.3",
|
||||||
"connect-history-api-fallback": "^2.0.0",
|
"connect-history-api-fallback": "^2.0.0",
|
||||||
|
"cors": "^2.8.5",
|
||||||
"csv-parser": "^3.0.0",
|
"csv-parser": "^3.0.0",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.4.5",
|
||||||
"flatted": "^3.2.7",
|
"express": "^4.19.2",
|
||||||
"follow-redirects": "^1.15.2",
|
"express-rate-limit": "^7.2.0",
|
||||||
"got": "^13.0.0",
|
"framer-motion": "^11.2.6",
|
||||||
"jest-styled-components": "^7.1.1",
|
"got": "^14.2.1",
|
||||||
"netlify-cli": "^15.9.1",
|
"pm2": "^5.3.1",
|
||||||
"perf_hooks": "^0.0.1",
|
|
||||||
"psl": "^1.9.0",
|
"psl": "^1.9.0",
|
||||||
"puppeteer": "^20.9.0",
|
"puppeteer": "^22.8.0",
|
||||||
"puppeteer-core": "^21.0.3",
|
"puppeteer-core": "^22.8.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.3.1",
|
||||||
"react-masonry-css": "^1.0.16",
|
"react-masonry-css": "^1.0.16",
|
||||||
"react-router-dom": "^6.14.2",
|
"react-router-dom": "^6.23.0",
|
||||||
"react-scripts": "5.0.1",
|
|
||||||
"react-simple-maps": "^3.0.0",
|
"react-simple-maps": "^3.0.0",
|
||||||
"react-toastify": "^9.1.3",
|
"react-toastify": "^10.0.5",
|
||||||
"recharts": "^2.7.3",
|
"recharts": "^2.12.6",
|
||||||
"styled-components": "^6.0.5",
|
"svelte": "^4.2.17",
|
||||||
"traceroute": "^1.0.0",
|
"traceroute": "^1.0.0",
|
||||||
"typescript": "^5.1.6",
|
"typescript": "^5.4.5",
|
||||||
"unzipper": "^0.10.14",
|
"unzipper": "^0.11.5",
|
||||||
|
"url-parse": "^1.5.10",
|
||||||
"wappalyzer": "^6.10.65",
|
"wappalyzer": "^6.10.65",
|
||||||
"web-vitals": "^3.4.0",
|
|
||||||
"xml2js": "^0.6.2"
|
"xml2js": "^0.6.2"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
|
||||||
"extends": [
|
|
||||||
"react-app",
|
|
||||||
"react-app/jest"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"browserslist": {
|
|
||||||
"production": [
|
|
||||||
">0.2%",
|
|
||||||
"not dead",
|
|
||||||
"not op_mini all"
|
|
||||||
],
|
|
||||||
"development": [
|
|
||||||
"last 1 chrome version",
|
|
||||||
"last 1 firefox version",
|
|
||||||
"last 1 safari version"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"compilerOptions": {
|
|
||||||
"allowJs": true,
|
|
||||||
"outDir": "./dist"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"serverless-domain-manager": "^7.1.1",
|
"@astrojs/cloudflare": "^10.2.5",
|
||||||
"serverless-offline": "^12.0.4",
|
"@astrojs/netlify": "^5.2.0",
|
||||||
"serverless-webpack": "^5.13.0",
|
"@astrojs/node": "^8.2.5",
|
||||||
"webpack": "^5.88.2",
|
"@astrojs/partytown": "^2.1.0",
|
||||||
"webpack-node-externals": "^3.0.0"
|
"@astrojs/sitemap": "^3.1.4",
|
||||||
|
"@astrojs/svelte": "^5.4.0",
|
||||||
|
"@astrojs/ts-plugin": "^1.6.1",
|
||||||
|
"@astrojs/vercel": "^7.5.4",
|
||||||
|
"concurrently": "^8.2.2",
|
||||||
|
"nodemon": "^3.1.0",
|
||||||
|
"sass": "^1.77.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1
public/assets/badges/dockerhub.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="205" height="20" role="img" aria-label="DockerHub: Lissy93/Web Check"><title>DockerHub: Lissy93/Web Check</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="205" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="88" height="20" fill="#1c1d28"/><rect x="88" width="117" height="20" fill="#1fb1f4"/><rect width="205" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSJ3aGl0ZSIgcm9sZT0iaW1nIiB2aWV3Qm94PSIwIDAgMjQgMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHRpdGxlPkRvY2tlcjwvdGl0bGU+PHBhdGggZD0iTTEzLjk4MyAxMS4wNzhoMi4xMTlhLjE4Ni4xODYgMCAwMC4xODYtLjE4NVY5LjAwNmEuMTg2LjE4NiAwIDAwLS4xODYtLjE4NmgtMi4xMTlhLjE4NS4xODUgMCAwMC0uMTg1LjE4NXYxLjg4OGMwIC4xMDIuMDgzLjE4NS4xODUuMTg1bS0yLjk1NC01LjQzaDIuMTE4YS4xODYuMTg2IDAgMDAuMTg2LS4xODZWMy41NzRhLjE4Ni4xODYgMCAwMC0uMTg2LS4xODVoLTIuMTE4YS4xODUuMTg1IDAgMDAtLjE4NS4xODV2MS44ODhjMCAuMTAyLjA4Mi4xODUuMTg1LjE4NW0wIDIuNzE2aDIuMTE4YS4xODcuMTg3IDAgMDAuMTg2LS4xODZWNi4yOWEuMTg2LjE4NiAwIDAwLS4xODYtLjE4NWgtMi4xMThhLjE4NS4xODUgMCAwMC0uMTg1LjE4NXYxLjg4N2MwIC4xMDIuMDgyLjE4NS4xODUuMTg2bS0yLjkzIDBoMi4xMmEuMTg2LjE4NiAwIDAwLjE4NC0uMTg2VjYuMjlhLjE4NS4xODUgMCAwMC0uMTg1LS4xODVIOC4xYS4xODUuMTg1IDAgMDAtLjE4NS4xODV2MS44ODdjMCAuMTAyLjA4My4xODUuMTg1LjE4Nm0tMi45NjQgMGgyLjExOWEuMTg2LjE4NiAwIDAwLjE4NS0uMTg2VjYuMjlhLjE4NS4xODUgMCAwMC0uMTg1LS4xODVINS4xMzZhLjE4Ni4xODYgMCAwMC0uMTg2LjE4NXYxLjg4N2MwIC4xMDIuMDg0LjE4NS4xODYuMTg2bTUuODkzIDIuNzE1aDIuMTE4YS4xODYuMTg2IDAgMDAuMTg2LS4xODVWOS4wMDZhLjE4Ni4xODYgMCAwMC0uMTg2LS4xODZoLTIuMTE4YS4xODUuMTg1IDAgMDAtLjE4NS4xODV2MS44ODhjMCAuMTAyLjA4Mi4xODUuMTg1LjE4NW0tMi45MyAwaDIuMTJhLjE4NS4xODUgMCAwMC4xODQtLjE4NVY5LjAwNmEuMTg1LjE4NSAwIDAwLS4xODQtLjE4NmgtMi4xMmEuMTg1LjE4NSAwIDAwLS4xODQuMTg1djEuODg4YzAgLjEwMi4wODMuMTg1LjE4NS4xODVtLTIuOTY0IDBoMi4xMTlhLjE4NS4xODUgMCAwMC4xODUtLjE4NVY5LjAwNmEuMTg1LjE4NSAwIDAwLS4xODQtLjE4NmgtMi4xMmEuMTg2LjE4NiAwIDAwLS4xODYuMTg2djEuODg3YzAgLjEwMi4wODQuMTg1LjE4Ni4xODVtLTIuOTIgMGgyLjEyYS4xODUuMTg1IDAgMDAuMTg0LS4xODVWOS4wMDZhLjE4NS4xODUgMCAwMC0uMTg0LS4xODZoLTIuMTJhLjE4NS4xODUgMCAwMC0uMTg0LjE4NXYxLjg4OGMwIC4xMDIuMDgyLjE4NS4xODUuMTg1TTIzLjc2MyA5Ljg5Yy0uMDY1LS4wNTEtLjY3Mi0uNTEtMS45NTQtLjUxLS4zMzguMDAxLS42NzYuMDMtMS4wMS4wODctLjI0OC0xLjctMS42NTMtMi41My0xLjcxNi0yLjU2NmwtLjM0NC0uMTk5LS4yMjYuMzI3Yy0uMjg0LjQzOC0uNDkuOTIyLS42MTIgMS40My0uMjMuOTctLjA5IDEuODgyLjQwMyAyLjY2MS0uNTk1LjMzMi0xLjU1LjQxMy0xLjc0NC40MkguNzUxYS43NTEuNzUxIDAgMDAtLjc1Ljc0OCAxMS4zNzYgMTEuMzc2IDAgMDAuNjkyIDQuMDYyYy41NDUgMS40MjggMS4zNTUgMi40OCAyLjQxIDMuMTI0IDEuMTguNzIzIDMuMSAxLjEzNyA1LjI3NSAxLjEzNy45ODMuMDAzIDEuOTYzLS4wODYgMi45My0uMjY2YTEyLjI0OCAxMi4yNDggMCAwMDMuODIzLTEuMzg5Yy45OC0uNTY3IDEuODYtMS4yODggMi42MS0yLjEzNiAxLjI1Mi0xLjQxOCAxLjk5OC0yLjk5NyAyLjU1My00LjRoLjIyMWMxLjM3MiAwIDIuMjE1LS41NDkgMi42OC0xLjAwOS4zMDktLjI5My41NS0uNjUuNzA3LTEuMDQ2bC4wOTgtLjI4OFoiLz48L3N2Zz4="/><text aria-hidden="true" x="535" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="610">DockerHub</text><text x="535" y="140" transform="scale(.1)" fill="#fff" textLength="610">DockerHub</text><text aria-hidden="true" x="1455" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="1070">Lissy93/Web Check</text><text x="1455" y="140" transform="scale(.1)" fill="#fff" textLength="1070">Lissy93/Web Check</text></g></svg>
|
||||||
|
After Width: | Height: | Size: 3.6 KiB |
1
public/assets/badges/github.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="181" height="20" role="img" aria-label="GitHub: Lissy93/Web Check"><title>GitHub: Lissy93/Web Check</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="181" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="64" height="20" fill="#1c1d28"/><rect x="64" width="117" height="20" fill="#a832fc"/><rect width="181" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSJ3aGl0ZSIgcm9sZT0iaW1nIiB2aWV3Qm94PSIwIDAgMjQgMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHRpdGxlPkdpdEh1YjwvdGl0bGU+PHBhdGggZD0iTTEyIC4yOTdjLTYuNjMgMC0xMiA1LjM3My0xMiAxMiAwIDUuMzAzIDMuNDM4IDkuOCA4LjIwNSAxMS4zODUuNi4xMTMuODItLjI1OC44Mi0uNTc3IDAtLjI4NS0uMDEtMS4wNC0uMDE1LTIuMDQtMy4zMzguNzI0LTQuMDQyLTEuNjEtNC4wNDItMS42MUM0LjQyMiAxOC4wNyAzLjYzMyAxNy43IDMuNjMzIDE3LjdjLTEuMDg3LS43NDQuMDg0LS43MjkuMDg0LS43MjkgMS4yMDUuMDg0IDEuODM4IDEuMjM2IDEuODM4IDEuMjM2IDEuMDcgMS44MzUgMi44MDkgMS4zMDUgMy40OTUuOTk4LjEwOC0uNzc2LjQxNy0xLjMwNS43Ni0xLjYwNS0yLjY2NS0uMy01LjQ2Ni0xLjMzMi01LjQ2Ni01LjkzIDAtMS4zMS40NjUtMi4zOCAxLjIzNS0zLjIyLS4xMzUtLjMwMy0uNTQtMS41MjMuMTA1LTMuMTc2IDAgMCAxLjAwNS0uMzIyIDMuMyAxLjIzLjk2LS4yNjcgMS45OC0uMzk5IDMtLjQwNSAxLjAyLjAwNiAyLjA0LjEzOCAzIC40MDUgMi4yOC0xLjU1MiAzLjI4NS0xLjIzIDMuMjg1LTEuMjMuNjQ1IDEuNjUzLjI0IDIuODczLjEyIDMuMTc2Ljc2NS44NCAxLjIzIDEuOTEgMS4yMyAzLjIyIDAgNC42MS0yLjgwNSA1LjYyNS01LjQ3NSA1LjkyLjQyLjM2LjgxIDEuMDk2LjgxIDIuMjIgMCAxLjYwNi0uMDE1IDIuODk2LS4wMTUgMy4yODYgMCAuMzE1LjIxLjY5LjgyNS41N0MyMC41NjUgMjIuMDkyIDI0IDE3LjU5MiAyNCAxMi4yOTdjMC02LjYyNy01LjM3My0xMi0xMi0xMiIvPjwvc3ZnPg=="/><text aria-hidden="true" x="415" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="370">GitHub</text><text x="415" y="140" transform="scale(.1)" fill="#fff" textLength="370">GitHub</text><text aria-hidden="true" x="1215" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="1070">Lissy93/Web Check</text><text x="1215" y="140" transform="scale(.1)" fill="#fff" textLength="1070">Lissy93/Web Check</text></g></svg>
|
||||||
|
After Width: | Height: | Size: 2.3 KiB |
1
public/assets/badges/sponsor.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="147" height="20" role="img" aria-label="Sponsor: Alicia Sykes"><title>Sponsor: Alicia Sykes</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="147" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="72" height="20" fill="#1c1d28"/><rect x="72" width="75" height="20" fill="#f2159a"/><rect width="147" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSJ3aGl0ZSIgcm9sZT0iaW1nIiB2aWV3Qm94PSIwIDAgMjQgMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHRpdGxlPkdpdEh1YiBTcG9uc29yczwvdGl0bGU+PHBhdGggZD0iTTE3LjYyNSAxLjQ5OWMtMi4zMiAwLTQuMzU0IDEuMjAzLTUuNjI1IDMuMDMtMS4yNzEtMS44MjctMy4zMDUtMy4wMy01LjYyNS0zLjAzQzMuMTI5IDEuNDk5IDAgNC4yNTMgMCA4LjI0OWMwIDQuMjc1IDMuMDY4IDcuODQ3IDUuODI4IDEwLjIyN2EzMy4xNCAzMy4xNCAwIDAgMCA1LjYxNiAzLjg3NmwuMDI4LjAxNy4wMDguMDAzLS4wMDEuMDAzYy4xNjMuMDg1LjM0Mi4xMjYuNTIxLjEyNS4xNzkuMDAxLjM1OC0uMDQxLjUyMS0uMTI1bC0uMDAxLS4wMDMuMDA4LS4wMDMuMDI4LS4wMTdhMzMuMTQgMzMuMTQgMCAwIDAgNS42MTYtMy44NzZDMjAuOTMyIDE2LjA5NiAyNCAxMi41MjQgMjQgOC4yNDljMC0zLjk5Ni0zLjEyOS02Ljc1LTYuMzc1LTYuNzV6bS0uOTE5IDE1LjI3NWEzMC43NjYgMzAuNzY2IDAgMCAxLTQuNzAzIDMuMzE2bC0uMDA0LS4wMDItLjAwNC4wMDJhMzAuOTU1IDMwLjk1NSAwIDAgMS00LjcwMy0zLjMxNmMtMi42NzctMi4zMDctNS4wNDctNS4yOTgtNS4wNDctOC41MjMgMC0yLjc1NCAyLjEyMS00LjUgNC4xMjUtNC41IDIuMDYgMCAzLjkxNCAxLjQ3OSA0LjU0NCAzLjY4NC4xNDMuNDk1LjU5Ni43OTcgMS4wODYuNzk2LjQ5LjAwMS45NDMtLjMwMiAxLjA4NS0uNzk2LjYzLTIuMjA1IDIuNDg0LTMuNjg0IDQuNTQ0LTMuNjg0IDIuMDA0IDAgNC4xMjUgMS43NDYgNC4xMjUgNC41IDAgMy4yMjUtMi4zNyA2LjIxNi01LjA0OCA4LjUyM3oiLz48L3N2Zz4="/><text aria-hidden="true" x="455" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="450">Sponsor</text><text x="455" y="140" transform="scale(.1)" fill="#fff" textLength="450">Sponsor</text><text aria-hidden="true" x="1085" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="650">Alicia Sykes</text><text x="1085" y="140" transform="scale(.1)" fill="#fff" textLength="650">Alicia Sykes</text></g></svg>
|
||||||
|
After Width: | Height: | Size: 2.3 KiB |
1
public/assets/badges/webcheck.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="155" height="20" role="img" aria-label="Website: web-check.zyz"><title>Website: web-check.zyz</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="155" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="70" height="20" fill="#1c1d28"/><rect x="70" width="85" height="20" fill="#9fef00"/><rect width="155" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSJ3aGl0ZSIgcm9sZT0iaW1nIiB2aWV3Qm94PSIwIDAgMjQgMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHRpdGxlPkdvb2dsZSBDbG91ZCBTdG9yYWdlPC90aXRsZT48cGF0aCBkPSJNMjQgMi40djguNGgtMi40VjIuNEgyNHpNMCAxMC44aDIuNFYyLjRIMHY4LjR6bTMtOC40aDE4djguNEgzVjIuNHptMTIuNiA0LjJhMS44IDEuOCAwIDEgMCAzLjYgMCAxLjggMS44IDAgMCAwLTMuNiAwem0tMTAuOC42SDEyVjZINC44djEuMnptMTYuOCAxNC40SDI0di04LjRoLTIuNHY4LjR6TTAgMjEuNmgyLjR2LTguNEgwdjguNHptMy04LjRoMTh2OC40SDN2LTguNHptMTIuNiA0LjJhMS44IDEuOCAwIDEgMCAzLjYgMCAxLjggMS44IDAgMCAwLTMuNiAwek00LjggMThIMTJ2LTEuMkg0LjhWMTh6Ii8+PC9zdmc+"/><text aria-hidden="true" x="445" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">Website</text><text x="445" y="140" transform="scale(.1)" fill="#fff" textLength="430">Website</text><text aria-hidden="true" x="1115" y="150" fill="#ccc" fill-opacity=".3" transform="scale(.1)" textLength="750">web-check.zyz</text><text x="1115" y="140" transform="scale(.1)" fill="#333" textLength="750">webcheck.zyz</text></g></svg>
|
||||||
|
After Width: | Height: | Size: 1.8 KiB |
9
public/assets/images/background-dots.svg
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<defs>
|
||||||
|
<pattern id="a" patternUnits="userSpaceOnUse" width="30" height="30">
|
||||||
|
<rect width="100%" height="100%" fill="var(--background, #111211)" />
|
||||||
|
<circle cx="5" cy="5" r="1.75" fill="var(--background-lighter, #3A3B3A)" opacity="0.3" />
|
||||||
|
</pattern>
|
||||||
|
</defs>
|
||||||
|
<rect width="100%" height="100%" fill="url(#a)" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 408 B |
1
public/assets/images/docker.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Docker</title><path d="M13.983 11.078h2.119a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.119a.185.185 0 00-.185.185v1.888c0 .102.083.185.185.185m-2.954-5.43h2.118a.186.186 0 00.186-.186V3.574a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m0 2.716h2.118a.187.187 0 00.186-.186V6.29a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.887c0 .102.082.185.185.186m-2.93 0h2.12a.186.186 0 00.184-.186V6.29a.185.185 0 00-.185-.185H8.1a.185.185 0 00-.185.185v1.887c0 .102.083.185.185.186m-2.964 0h2.119a.186.186 0 00.185-.186V6.29a.185.185 0 00-.185-.185H5.136a.186.186 0 00-.186.185v1.887c0 .102.084.185.186.186m5.893 2.715h2.118a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m-2.93 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.083.185.185.185m-2.964 0h2.119a.185.185 0 00.185-.185V9.006a.185.185 0 00-.184-.186h-2.12a.186.186 0 00-.186.186v1.887c0 .102.084.185.186.185m-2.92 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.082.185.185.185M23.763 9.89c-.065-.051-.672-.51-1.954-.51-.338.001-.676.03-1.01.087-.248-1.7-1.653-2.53-1.716-2.566l-.344-.199-.226.327c-.284.438-.49.922-.612 1.43-.23.97-.09 1.882.403 2.661-.595.332-1.55.413-1.744.42H.751a.751.751 0 00-.75.748 11.376 11.376 0 00.692 4.062c.545 1.428 1.355 2.48 2.41 3.124 1.18.723 3.1 1.137 5.275 1.137.983.003 1.963-.086 2.93-.266a12.248 12.248 0 003.823-1.389c.98-.567 1.86-1.288 2.61-2.136 1.252-1.418 1.998-2.997 2.553-4.4h.221c1.372 0 2.215-.549 2.68-1.009.309-.293.55-.65.707-1.046l.098-.288Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.7 KiB |
1
public/assets/images/fly.svg
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
1
public/assets/images/github.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>
|
||||||
|
After Width: | Height: | Size: 823 B |
1
public/assets/images/netlify.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Netlify</title><path d="M6.49 19.04h-.23L5.13 17.9v-.23l1.73-1.71h1.2l.15.15v1.2L6.5 19.04ZM5.13 6.31V6.1l1.13-1.13h.23L8.2 6.68v1.2l-.15.15h-1.2L5.13 6.31Zm9.96 9.09h-1.65l-.14-.13v-3.83c0-.68-.27-1.2-1.1-1.23-.42 0-.9 0-1.43.02l-.07.08v4.96l-.14.14H8.9l-.13-.14V8.73l.13-.14h3.7a2.6 2.6 0 0 1 2.61 2.6v4.08l-.13.14Zm-8.37-2.44H.14L0 12.82v-1.64l.14-.14h6.58l.14.14v1.64l-.14.14Zm17.14 0h-6.58l-.14-.14v-1.64l.14-.14h6.58l.14.14v1.64l-.14.14ZM11.05 6.55V1.64l.14-.14h1.65l.14.14v4.9l-.14.14h-1.65l-.14-.13Zm0 15.81v-4.9l.14-.14h1.65l.14.13v4.91l-.14.14h-1.65l-.14-.14Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 657 B |
1
public/assets/images/swagger.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Swagger</title><path d="M12 0C5.383 0 0 5.383 0 12s5.383 12 12 12c6.616 0 12-5.383 12-12S18.616 0 12 0zm0 1.144c5.995 0 10.856 4.86 10.856 10.856 0 5.995-4.86 10.856-10.856 10.856-5.996 0-10.856-4.86-10.856-10.856C1.144 6.004 6.004 1.144 12 1.144zM8.37 5.868a6.707 6.707 0 0 0-.423.005c-.983.056-1.573.517-1.735 1.472-.115.665-.096 1.348-.143 2.017-.013.35-.05.697-.115 1.038-.134.609-.397.798-1.016.83a2.65 2.65 0 0 0-.244.042v1.463c1.126.055 1.278.452 1.37 1.629.033.429-.013.858.015 1.287.018.406.073.808.156 1.2.259 1.075 1.307 1.435 2.575 1.218v-1.283c-.203 0-.383.005-.558 0-.43-.013-.591-.12-.632-.535-.056-.535-.042-1.08-.075-1.62-.064-1.001-.175-1.988-1.153-2.625.503-.37.868-.812.983-1.398.083-.41.134-.821.166-1.237.028-.415-.023-.84.014-1.25.06-.665.102-.937.9-.91.12 0 .235-.017.369-.027v-1.31c-.16 0-.31-.004-.454-.006zm7.593.009a4.247 4.247 0 0 0-.813.06v1.274c.245 0 .434 0 .623.005.328.004.577.13.61.494.032.332.031.669.064 1.006.065.669.101 1.347.217 2.007.102.544.475.95.941 1.283-.817.549-1.057 1.333-1.098 2.215-.023.604-.037 1.213-.069 1.822-.028.554-.222.734-.78.748-.157.004-.31.018-.484.028v1.305c.327 0 .627.019.927 0 .932-.055 1.495-.507 1.68-1.412.078-.498.124-1 .138-1.504.032-.461.028-.927.074-1.384.069-.715.397-1.01 1.112-1.057a.972.972 0 0 0 .199-.046v-1.463c-.12-.014-.204-.027-.291-.032-.536-.023-.804-.203-.937-.71a5.146 5.146 0 0 1-.152-.993c-.037-.618-.033-1.241-.074-1.86-.08-1.192-.794-1.753-1.887-1.786zm-6.89 5.28a.844.844 0 0 0-.083 1.684h.055a.83.83 0 0 0 .877-.78v-.046a.845.845 0 0 0-.83-.858zm2.911 0a.808.808 0 0 0-.834.78c0 .027 0 .05.004.078 0 .503.342.826.859.826.507 0 .826-.332.826-.853-.005-.503-.342-.836-.855-.831zm2.963 0a.861.861 0 0 0-.876.835c0 .47.378.849.849.849h.009c.425.074.853-.337.881-.83.023-.457-.392-.854-.863-.854z"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.8 KiB |
1
public/assets/images/vercel.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Vercel</title><path d="M24 22.525H0l12-21.05 12 21.05z"/></svg>
|
||||||
|
After Width: | Height: | Size: 142 B |
1
public/assets/images/webauthn.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>WebAuthn</title><path d="M15.2872 3.641a8.407 8.407 0 00-8.05 7.593h.55a7.805 7.805 0 012.24-4.713 5.825 5.825 0 00.923.695c-.608 1.177-.98 2.556-1.082 4.018h.135c.105-1.467.485-2.819 1.065-3.947.745.434 1.623.754 2.577.94a27.83 27.83 0 00-.25 3.763h-.847v.135h.847c.003 1.334.09 2.617.25 3.764-.954.185-1.832.506-2.577.94a9.997 9.997 0 01-.978-3.137h-.137c.164 1.16.502 2.25.997 3.208a5.825 5.825 0 00-.924.695 7.805 7.805 0 01-2.255-4.875h-.55a8.407 8.407 0 0016.779-.675 8.398 8.398 0 00-.689-3.333 8.407 8.407 0 00-8.025-5.072zm.315.546c.155 0 .31.005.464.014.365.34.708 1.07.983 2.114a16.518 16.518 0 01.357 1.79 10.173 10.173 0 01-1.804.16 10.173 10.173 0 01-1.805-.16 16.519 16.519 0 01.357-1.79c.275-1.045.618-1.775.983-2.114a7.97 7.97 0 01.465-.014zm-.665.028c-.345.392-.658 1.093-.913 2.065a16.639 16.639 0 00-.36 1.8c-.939-.183-1.802-.498-2.533-.926.686-1.283 1.635-2.264 2.73-2.775a7.874 7.874 0 011.076-.164zm1.33 0a7.856 7.856 0 011.084.168c1.092.513 2.037 1.492 2.721 2.771-.73.428-1.594.743-2.533.927a16.64 16.64 0 00-.36-1.8c-.255-.972-.568-1.673-.912-2.066zm-2.972.314c-.655.407-1.257.989-1.776 1.73a8.166 8.166 0 00-.506.825 5.69 5.69 0 01-.89-.67 7.814 7.814 0 013.172-1.885zm4.624.006a7.862 7.862 0 013.164 1.877 5.692 5.692 0 01-.893.672 8.166 8.166 0 00-.506-.825c-.516-.738-1.115-1.318-1.765-1.724zm3.26 1.985a7.858 7.858 0 011.638 2.419 7.802 7.802 0 01.642 3.051h-2.095c-.01-1.74-.398-3.396-1.11-4.774a5.823 5.823 0 00.925-.696zm-1.044.767c.68 1.32 1.084 2.945 1.094 4.703h-3.42a27.863 27.863 0 00-.25-3.763c.953-.186 1.832-.506 2.576-.94zm-6.357.965a10.299 10.299 0 001.824.16 10.299 10.299 0 001.823-.16c.16 1.138.246 2.413.25 3.738h-1.179a1.03 1.03 0 01-.093.135h1.27a27.71 27.71 0 01-.248 3.739 10.397 10.397 0 00-3.647 0 27.733 27.733 0 01-.248-3.739h1.294a.99.99 0 01-.09-.135h-1.204c.003-1.325.088-2.6.248-3.738zm-11.22 1.129a2.585 2.585 0 00-2.547 2.35c-.142 1.541 1.064 2.842 2.566 2.842 1.26 0 2.312-.917 2.533-2.124h4.44v.972h.946v-.972h.837v1.431h.945v-2.376h-7.168a2.586 2.586 0 00-2.552-2.123zm-.058.965a1.639 1.639 0 011.707 1.637 1.64 1.64 0 01-1.639 1.638 1.639 1.639 0 01-.068-3.275zm13.09.388a.75.75 0 00-.345 1.404l-.383 1.958h1.5l-.383-1.958a.75.75 0 00.384-.654.75.75 0 00-.773-.75zm2.218 1.391h3.421c-.01 1.758-.415 3.384-1.094 4.704-.744-.434-1.623-.755-2.577-.94a27.81 27.81 0 00.25-3.764zm3.556 0h2.095a7.805 7.805 0 01-2.28 5.47 5.825 5.825 0 00-.925-.696c.712-1.378 1.1-3.033 1.11-4.774zm-5.52 3.703a10.284 10.284 0 011.562.156 16.518 16.518 0 01-.357 1.791c-.275 1.045-.618 1.774-.982 2.114a7.972 7.972 0 01-.93 0c-.365-.34-.708-1.07-.983-2.114a16.519 16.519 0 01-.357-1.79 10.284 10.284 0 012.048-.157zm1.695.181c.94.184 1.803.5 2.533.926-.686 1.284-1.635 2.265-2.73 2.776a7.874 7.874 0 01-1.075.164c.344-.393.657-1.094.913-2.065a16.64 16.64 0 00.36-1.8zm-3.874 0a16.648 16.648 0 00.36 1.8c.254.973.567 1.674.912 2.066a7.873 7.873 0 01-1.075-.164c-1.096-.511-2.045-1.492-2.73-2.775.73-.428 1.593-.743 2.533-.927zm-2.652.997a8.16 8.16 0 00.506.825c.52.741 1.121 1.323 1.776 1.73a7.814 7.814 0 01-3.174-1.884 5.694 5.694 0 01.892-.67zm9.178 0a5.694 5.694 0 01.891.67 7.814 7.814 0 01-3.173 1.885c.654-.407 1.256-.989 1.775-1.73a8.16 8.16 0 00.507-.825z"/></svg>
|
||||||
|
After Width: | Height: | Size: 3.2 KiB |
39
public/error.html
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Web-Check</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<section>
|
||||||
|
<a class="t" href="/"><h1><img src="https://i.ibb.co/q1gZN2p/web-check-logo.png" width="48" />Web-Check</h1></a>
|
||||||
|
<p class="moji">😪</p>
|
||||||
|
<p>There was an error finding this route.</p>
|
||||||
|
<span>Docs and Source: <a href="https://github.com/lissy93/web-check">github.com/lissy93/web-check</a></span>
|
||||||
|
</section>
|
||||||
|
<style>
|
||||||
|
body { background: #141d2b; color: #fff; }
|
||||||
|
h1 {
|
||||||
|
color: #9fef00; text-shadow: #0f1620 2px 2px 0px;
|
||||||
|
font-size: 3rem; margin: 1rem auto; flex-wrap: wrap;
|
||||||
|
display: flex; align-items: flex-start; gap: 1rem;
|
||||||
|
}
|
||||||
|
section {
|
||||||
|
display: flex; flex-direction: column; align-items: center; margin: 1rem; gap: 0.5rem;
|
||||||
|
background: #1a2332; box-shadow: #0f1620 4px 4px 0px; border-radius: 8px; padding: 1rem;
|
||||||
|
max-width: 800px; margin: 1rem auto;
|
||||||
|
}
|
||||||
|
p { font-size: 1.2rem; }
|
||||||
|
a { color: #9fef00; font-family: monospace; }
|
||||||
|
a.t { text-decoration: none; margin: 0;}
|
||||||
|
span { opacity: 0.8; font-size: 0.85rem; }
|
||||||
|
h1 {
|
||||||
|
font-family: PTMono, Ubuntu, Fira Sans, Helvetica, sans-serif;
|
||||||
|
}
|
||||||
|
p, span, a, section, div { font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; }
|
||||||
|
code { color: #9fef00cc;}
|
||||||
|
.moji { font-size: 8rem; margin: 0; }
|
||||||
|
</style>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
6
public/favicon.svg
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="8.424 15.685618729096989 38.844 37.92642140468227" style="max-height: 500px" width="38.844" height="37.92642140468227">
|
||||||
|
<path stroke-linejoin="round" stroke-linecap="round" stroke-width="2.8" stroke="white" d="M43.3 30.1V20.3C43.3 19.9287 43.1525 19.5726 42.89 19.31C42.6274 19.0475 42.2713 18.9 41.9 18.9H13.9C13.5287 18.9 13.1726 19.0475 12.9101 19.31C12.6475 19.5726 12.5 19.9287 12.5 20.3V30.1C12.5 46.9 27.9 51.1 27.9 51.1C27.9 51.1 43.3 46.9 43.3 30.1Z"/>
|
||||||
|
<path stroke-linejoin="round" stroke-linecap="round" stroke-width="2.8" stroke="#D6FB41" d="M20.8999 34.3L25.0999 38.5L34.8999 28.7"/>
|
||||||
|
<path fill="white" d="M60.07 45.5L55.78 23.63H61.6L63.76 37.82L64.12 40.28H64.36L67.66 23.63H73.7801L77.08 40.28H77.35L77.62 38.21L79.7801 23.63H85.63L81.4001 45.5H73.72L71.1701 33.05L70.84 31.22H70.63L70.3 33.05L67.72 45.5H60.07ZM94.42 45.8C92.58 45.8 91.05 45.45 89.83 44.75C88.63 44.05 87.72 43.08 87.1 41.84C86.5 40.58 86.2 39.12 86.2 37.46V37.13C86.2 35.39 86.53 33.91 87.19 32.69C87.85 31.47 88.76 30.54 89.92 29.9C91.1 29.26 92.45 28.94 93.97 28.94C95.67 28.94 97.11 29.26 98.29 29.9C99.49 30.52 100.4 31.4 101.02 32.54C101.64 33.68 101.95 35 101.95 36.5V38.72H91.57V39.47C91.57 40.17 91.82 40.74 92.32 41.18C92.82 41.6 93.46 41.81 94.24 41.81C94.94 41.81 95.51 41.67 95.95 41.39C96.39 41.09 96.65 40.7 96.73 40.22H101.77C101.71 41.34 101.36 42.32 100.72 43.16C100.08 43.98 99.22 44.63 98.14 45.11C97.06 45.57 95.82 45.8 94.42 45.8ZM91.57 35.36V35.51H96.73V35.36C96.73 34.5 96.49 33.87 96.01 33.47C95.55 33.05 94.93 32.84 94.15 32.84C93.39 32.84 92.77 33.06 92.29 33.5C91.81 33.92 91.57 34.54 91.57 35.36ZM114.879 45.8C113.859 45.8 112.929 45.58 112.089 45.14C111.269 44.7 110.659 44.08 110.259 43.28H110.019L109.719 45.5H104.709V23.63H110.019V31.49H110.259C110.659 30.69 111.269 30.07 112.089 29.63C112.929 29.17 113.859 28.94 114.879 28.94C116.359 28.94 117.549 29.28 118.449 29.96C119.349 30.62 120.009 31.55 120.429 32.75C120.849 33.95 121.059 35.36 121.059 36.98V37.76C121.059 40.62 120.499 42.68 119.379 43.94C118.259 45.18 116.759 45.8 114.879 45.8ZM112.719 41.51C113.579 41.51 114.239 41.27 114.699 40.79C115.179 40.29 115.419 39.6 115.419 38.72V36.05C115.419 35.17 115.179 34.48 114.699 33.98C114.239 33.48 113.579 33.23 112.719 33.23C111.899 33.23 111.249 33.48 110.769 33.98C110.289 34.46 110.049 35.15 110.049 36.05V38.69C110.049 39.61 110.289 40.31 110.769 40.79C111.249 41.27 111.899 41.51 112.719 41.51Z"/>
|
||||||
|
<path fill="#D6FB41" d="M133.77 45.8C131.61 45.8 129.77 45.41 128.25 44.63C126.73 43.83 125.56 42.71 124.74 41.27C123.94 39.83 123.54 38.15 123.54 36.23V35.96C123.54 33.38 123.99 31.15 124.89 29.27C125.79 27.37 127.1 25.91 128.82 24.89C130.54 23.85 132.61 23.33 135.03 23.33C136.99 23.33 138.71 23.67 140.19 24.35C141.67 25.01 142.83 25.94 143.67 27.14C144.51 28.34 144.96 29.75 145.02 31.37H139.17C139.05 30.41 138.59 29.64 137.79 29.06C137.01 28.48 136.02 28.19 134.82 28.19C133.4 28.19 132.27 28.52 131.43 29.18C130.59 29.82 130.05 30.83 129.81 32.21L129.24 35.36C128.94 37.1 129.21 38.47 130.05 39.47C130.89 40.45 132.13 40.94 133.77 40.94C134.99 40.94 135.97 40.69 136.71 40.19C137.47 39.67 137.97 38.97 138.21 38.09H144C143.7 39.73 143.08 41.13 142.14 42.29C141.2 43.43 140.01 44.3 138.57 44.9C137.13 45.5 135.53 45.8 133.77 45.8ZM145.633 45.5L149.503 23.63H154.873L153.553 31.19H153.883C154.343 30.49 154.973 29.95 155.773 29.57C156.593 29.17 157.463 28.97 158.383 28.97C160.283 28.97 161.693 29.62 162.613 30.92C163.553 32.2 163.813 34.02 163.393 36.38L161.773 45.5H156.373L157.963 36.47C158.163 35.41 158.063 34.6 157.663 34.04C157.263 33.48 156.603 33.2 155.683 33.2C154.843 33.2 154.173 33.47 153.673 34.01C153.173 34.53 152.843 35.22 152.683 36.08L151.063 45.5H145.633ZM173.599 45.8C171.219 45.8 169.339 45.14 167.959 43.82C166.599 42.5 165.919 40.67 165.919 38.33V38.09C165.919 36.25 166.249 34.65 166.909 33.29C167.569 31.91 168.539 30.85 169.819 30.11C171.099 29.35 172.639 28.97 174.439 28.97C176.179 28.97 177.649 29.32 178.849 30.02C180.069 30.7 180.949 31.67 181.489 32.93C182.049 34.17 182.209 35.63 181.969 37.31L181.759 38.72H171.049C171.049 38.78 171.039 38.85 171.019 38.93C171.019 38.99 171.019 39.06 171.019 39.14C170.899 39.94 171.099 40.59 171.619 41.09C172.139 41.57 172.849 41.81 173.749 41.81C174.429 41.81 174.999 41.68 175.459 41.42C175.939 41.16 176.259 40.78 176.419 40.28H181.489C181.209 41.98 180.379 43.33 178.999 44.33C177.619 45.31 175.819 45.8 173.599 45.8ZM171.679 35.21L171.619 35.51H176.989C177.049 34.63 176.849 33.97 176.389 33.53C175.949 33.07 175.299 32.84 174.439 32.84C173.579 32.84 172.929 33.07 172.489 33.53C172.049 33.97 171.779 34.53 171.679 35.21ZM191.498 45.8C189.098 45.8 187.218 45.14 185.858 43.82C184.518 42.5 183.848 40.75 183.848 38.57V38.33C183.848 36.43 184.178 34.78 184.838 33.38C185.518 31.98 186.488 30.9 187.748 30.14C189.028 29.36 190.568 28.97 192.368 28.97C194.648 28.97 196.478 29.55 197.858 30.71C199.258 31.87 199.988 33.44 200.048 35.42H194.918C194.878 34.68 194.618 34.14 194.138 33.8C193.678 33.46 193.088 33.29 192.368 33.29C191.528 33.29 190.878 33.51 190.418 33.95C189.958 34.37 189.668 34.97 189.548 35.75L189.158 38.15C188.978 39.21 189.118 40.03 189.578 40.61C190.038 41.19 190.738 41.48 191.678 41.48C192.378 41.48 192.958 41.3 193.418 40.94C193.878 40.58 194.178 40.1 194.318 39.5H199.478C199.398 40.76 199.008 41.86 198.308 42.8C197.628 43.74 196.708 44.48 195.548 45.02C194.388 45.54 193.038 45.8 191.498 45.8ZM201.092 45.5L204.932 23.63H210.332L208.232 35.42L214.622 29.27H221.222L214.052 35.69L218.402 45.5H212.552L209.852 38.96L207.212 41.27L206.462 45.5H201.092Z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 5.5 KiB |
BIN
public/fonts/Hubot-Sans/Hubot-Sans.ttf
Normal file
BIN
public/fonts/Hubot-Sans/Hubot-Sans.woff2
Normal file
93
public/fonts/Hubot-Sans/LICENSE
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
Copyright (c) 2022, GitHub https://github.com/github/hubot-sans
|
||||||
|
with Reserved Font Name "Hubot Sans"
|
||||||
|
|
||||||
|
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||||
|
This license is copied below, and is also available with a FAQ at:
|
||||||
|
http://scripts.sil.org/OFL
|
||||||
|
|
||||||
|
-----------------------------------------------------------
|
||||||
|
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||||
|
development of collaborative font projects, to support the font creation
|
||||||
|
efforts of academic and linguistic communities, and to provide a free and
|
||||||
|
open framework in which fonts may be shared and improved in partnership
|
||||||
|
with others.
|
||||||
|
|
||||||
|
The OFL allows the licensed fonts to be used, studied, modified and
|
||||||
|
redistributed freely as long as they are not sold by themselves. The
|
||||||
|
fonts, including any derivative works, can be bundled, embedded,
|
||||||
|
redistributed and/or sold with any software provided that any reserved
|
||||||
|
names are not used by derivative works. The fonts and derivatives,
|
||||||
|
however, cannot be released under any other type of license. The
|
||||||
|
requirement for fonts to remain under this license does not apply
|
||||||
|
to any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
"Font Software" refers to the set of files released by the Copyright
|
||||||
|
Holder(s) under this license and clearly marked as such. This may
|
||||||
|
include source files, build scripts and documentation.
|
||||||
|
|
||||||
|
"Reserved Font Name" refers to any names specified as such after the
|
||||||
|
copyright statement(s).
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software components as
|
||||||
|
distributed by the Copyright Holder(s).
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||||
|
or substituting — in part or in whole — any of the components of the
|
||||||
|
Original Version, by changing formats or by porting the Font Software to a
|
||||||
|
new environment.
|
||||||
|
|
||||||
|
"Author" refers to any designer, engineer, programmer, technical
|
||||||
|
writer or other person who contributed to the Font Software.
|
||||||
|
|
||||||
|
PERMISSION & CONDITIONS
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||||
|
redistribute, and sell modified and unmodified copies of the Font
|
||||||
|
Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1) Neither the Font Software nor any of its individual components,
|
||||||
|
in Original or Modified Versions, may be sold by itself.
|
||||||
|
|
||||||
|
2) Original or Modified Versions of the Font Software may be bundled,
|
||||||
|
redistributed and/or sold with any software, provided that each copy
|
||||||
|
contains the above copyright notice and this license. These can be
|
||||||
|
included either as stand-alone text files, human-readable headers or
|
||||||
|
in the appropriate machine-readable metadata fields within text or
|
||||||
|
binary files as long as those fields can be easily viewed by the user.
|
||||||
|
|
||||||
|
3) No Modified Version of the Font Software may use the Reserved Font
|
||||||
|
Name(s) unless explicit written permission is granted by the corresponding
|
||||||
|
Copyright Holder. This restriction only applies to the primary font name as
|
||||||
|
presented to the users.
|
||||||
|
|
||||||
|
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||||
|
Software shall not be used to promote, endorse or advertise any
|
||||||
|
Modified Version, except to acknowledge the contribution(s) of the
|
||||||
|
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
5) The Font Software, modified or unmodified, in part or in whole,
|
||||||
|
must be distributed entirely under this license, and must not be
|
||||||
|
distributed under any other license. The requirement for fonts to
|
||||||
|
remain under this license does not apply to any document created
|
||||||
|
using the Font Software.
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
This license becomes null and void if any of the above conditions are
|
||||||
|
not met.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||||
|
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||||
|
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||||
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||||