Merge branch 'main' of https://github.com/wuyuhanzijin/UpTimeFlare
commit
1aa524e182
|
|
@ -0,0 +1,56 @@
|
||||||
|
<div align="right">
|
||||||
|
<a title="English" href="README.md"><img src="https://img.shields.io/badge/-English-A31F34?style=for-the-badge" alt="English" /></a>
|
||||||
|
<a title="简体中文" href="README_zh-CN.md"><img src="https://img.shields.io/badge/-%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87-545759?style=for-the-badge" alt="简体中文"></a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
# ✔[UptimeFlare](https://github.com/lyc8503/UptimeFlare)
|
||||||
|
|
||||||
|
A more advanced, serverless, and free uptime monitoring & status page solution, powered by Cloudflare Workers, complete with a user-friendly interface.
|
||||||
|
|
||||||
|
## ⭐Features
|
||||||
|
- Open-source, easy to deploy (in under 10 minutes, no local tools required), and free
|
||||||
|
- Monitoring capabilities
|
||||||
|
- Up to 50 checks at 1-minute intervals
|
||||||
|
- Geo-specific checks from over [310 cities](https://www.cloudflare.com/network/) worldwide
|
||||||
|
- Support for HTTP/HTTPS/TCP port monitoring
|
||||||
|
- Up to 90-day uptime history and uptime percentage tracking
|
||||||
|
- Customizable request methods, headers, and body for HTTP(s)
|
||||||
|
- Custom status code & keyword checks for HTTP(s)
|
||||||
|
- Downtime notification supporting [100+ notification channels](https://github.com/caronc/apprise/wiki)
|
||||||
|
- Customizable Webhook
|
||||||
|
- Status page
|
||||||
|
- Interactive ping (response time) chart for all types of monitors
|
||||||
|
- Responsive UI that adapts to your system theme
|
||||||
|
- Customizable status page
|
||||||
|
- Use your own domain with CNAME
|
||||||
|
- Optional password authentication (private status page)
|
||||||
|
- JSON API for fetching realtime status data
|
||||||
|
|
||||||
|
## 👀Demo
|
||||||
|
|
||||||
|
My status page (Online demo): https://uptimeflare.pages.dev/
|
||||||
|
|
||||||
|
Some screenshots:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## ⚡Quickstart / 📄Documentation
|
||||||
|
|
||||||
|
Please refer to [Wiki](https://github.com/lyc8503/UptimeFlare/wiki)
|
||||||
|
|
||||||
|
## New features (TODOs)
|
||||||
|
|
||||||
|
- [x] Specify region for monitors
|
||||||
|
- [x] TCP `opened` promise
|
||||||
|
- [x] Use apprise to support various notification channels
|
||||||
|
- [x] ~~Telegram example~~
|
||||||
|
- [x] ~~[Bark](https://bark.day.app) example~~
|
||||||
|
- [x] ~~Email notification via Cloudflare Email Workers~~
|
||||||
|
- [x] Improve docs by providing simple examples
|
||||||
|
- [x] Notification grace period
|
||||||
|
- [ ] SSL certificate checks
|
||||||
|
- [ ] Self-host Dockerfile
|
||||||
|
- [ ] Incident timeline
|
||||||
|
- [ ] Improve `checkLocationWorkerRoute` and fix possible `proxy failed`
|
||||||
|
- [ ] Groups
|
||||||
|
- [x] Remove old incidents
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
<div align="right">
|
||||||
|
<a title="English" href="README.md"><img src="https://img.shields.io/badge/-English-545759?style=for-the-badge" alt="English"></a>
|
||||||
|
<a title="简体中文" href="README_zh-CN.md"><img src="https://img.shields.io/badge/-%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87-A31F34?style=for-the-badge" alt="简体中文"></a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
# ✔[UptimeFlare](https://github.com/lyc8503/UptimeFlare)
|
||||||
|
|
||||||
|
一个由 Cloudflare Workers 驱动的功能丰富、Serverless 且免费的 Uptime 监控及状态页面。
|
||||||
|
|
||||||
|
## ⭐功能
|
||||||
|
- 开源,易于部署(全程无需本地工具,耗时不到 10 分钟),且完全免费
|
||||||
|
- 监控功能
|
||||||
|
- 最多支持 50 个 1 分钟精度的检查
|
||||||
|
- 支持指定全球 [310+ 个城市](https://www.cloudflare.com/network/) 的监控节点
|
||||||
|
- 支持 HTTP/HTTPS/TCP 端口监控
|
||||||
|
- 最多 90 天的 uptime 历史记录和 uptime 百分比跟踪
|
||||||
|
- 可自定义的 HTTP(s) 请求方法、头和主体
|
||||||
|
- 可自定义的 HTTP(s) 状态码和关键字检查
|
||||||
|
- 支持 [100 多个通知渠道](https://github.com/caronc/apprise/wiki) 的宕机消息通知
|
||||||
|
- 可自定义的 Webhook
|
||||||
|
- 状态页面
|
||||||
|
- 所有类型监控的交互式 ping(响应时间)图表
|
||||||
|
- 响应式 UI,自适应PC/手机屏幕,及亮色/暗色系统主题
|
||||||
|
- 配置选项丰富的状态页面
|
||||||
|
- 可使用您自己的域名与 CNAME
|
||||||
|
- 可选的密码认证(私人状态页面)
|
||||||
|
- 用于获取实时状态数据的 JSON API
|
||||||
|
|
||||||
|
## 👀演示
|
||||||
|
|
||||||
|
我自己的状态页面(在线演示):https://uptimeflare.pages.dev/
|
||||||
|
|
||||||
|
一些截图:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## ⚡快速入门 / 📄文档
|
||||||
|
|
||||||
|
请参阅 [Wiki](https://github.com/lyc8503/UptimeFlare/wiki)
|
||||||
|
|
@ -47,12 +47,13 @@ export default function DetailBar({
|
||||||
<Tooltip
|
<Tooltip
|
||||||
multiline
|
multiline
|
||||||
key={i}
|
key={i}
|
||||||
|
events={{ hover: true, focus: false, touch: true }}
|
||||||
label={
|
label={
|
||||||
Number.isNaN(Number(dayPercent)) ? (
|
Number.isNaN(Number(dayPercent)) ? (
|
||||||
'无数据'
|
'无数据'
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div>{dayPercent + '%'}</div>
|
<div>{dayPercent + '% at ' + new Date(dayStart * 1000).toLocaleDateString()}</div>
|
||||||
{dayDownTime > 0 && (
|
{dayDownTime > 0 && (
|
||||||
<div>{`Down for ${moment.preciseDiff(moment(0), moment(dayDownTime * 1000))}`}</div>
|
<div>{`Down for ${moment.preciseDiff(moment(0), moment(dayDownTime * 1000))}`}</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ export default function MonitorDetail({
|
||||||
const monitorNameElement = (
|
const monitorNameElement = (
|
||||||
<Text mt="sm" fw={700} style={{ display: 'inline-flex', alignItems: 'center' }}>
|
<Text mt="sm" fw={700} style={{ display: 'inline-flex', alignItems: 'center' }}>
|
||||||
{monitor.statusPageLink ? (
|
{monitor.statusPageLink ? (
|
||||||
<a href={monitor.statusPageLink} target="_blank" style={{ display: 'inline-flex', alignItems: 'center', color: 'inherit', textDecoration: 'none' }}>
|
<a href={monitor.statusPageLink} target="_blank" style={{ display: 'inline-flex', alignItems: 'center', color: 'inherit' }}>
|
||||||
{statusIcon} {monitor.name}
|
{statusIcon} {monitor.name}
|
||||||
</a>
|
</a>
|
||||||
) : (
|
) : (
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { NextResponse } from 'next/server'
|
||||||
|
import type { NextRequest } from 'next/server'
|
||||||
|
import { workerConfig } from './uptime.config'
|
||||||
|
|
||||||
|
export async function middleware(request: NextRequest) {
|
||||||
|
// @ts-ignore
|
||||||
|
const passwordProtection = workerConfig.passwordProtection
|
||||||
|
if (passwordProtection) {
|
||||||
|
const authHeader = request.headers.get('Authorization')
|
||||||
|
let authenticated = false
|
||||||
|
const expected = 'Basic ' + btoa(passwordProtection)
|
||||||
|
|
||||||
|
if (authHeader && authHeader.length === expected.length) {
|
||||||
|
// a simple timing-safe compare
|
||||||
|
authenticated = true;
|
||||||
|
for (let i = 0; i < authHeader.length; i++) {
|
||||||
|
if (authHeader[i] !== expected[i]) authenticated = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!authenticated) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ code: 401, message: "Not authenticated" }, { status: 401, headers: { 'WWW-Authenticate': 'Basic' } }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue