Skip to content

Commit

Permalink
Feat 增加小程序入口
Browse files Browse the repository at this point in the history
  • Loading branch information
Misaka-1314 committed Jan 6, 2025
1 parent eda7bb7 commit b7b34f4
Show file tree
Hide file tree
Showing 14 changed files with 669 additions and 1 deletion.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ tmp
.vscode
.DS_Store

*.html
*yml
*.log
*.sh
Expand Down
1 change: 1 addition & 0 deletions web/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.sh
24 changes: 24 additions & 0 deletions web/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
FROM python:3.12-alpine

RUN apk add tzdata && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo Asia/Shanghai > /etc/timezone && apk add ca-certificates

RUN apk add --update --no-cache python3 py3-pip nginx \
&& mkdir -p /run/nginx \
&& rm -rf /var/cache/apk/*

WORKDIR /app

COPY ./requirements.txt /app/requirements.txt

RUN pip config set global.index-url http://mirrors.cloud.tencent.com/pypi/simple \
&& pip config set global.trusted-host mirrors.cloud.tencent.com \
&& pip install --upgrade pip --break-system-packages \
&& pip install --user -r requirements.txt --break-system-packages

COPY nginx.conf /etc/nginx/nginx.conf

COPY . /app

EXPOSE 80

CMD ["sh", "-c", "python3 app.py & nginx -g 'daemon off;'"]
23 changes: 23 additions & 0 deletions web/Dockerfile.zh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
FROM docker.proxy.yangrucheng.top/python:3.12-alpine

RUN apk add tzdata && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo Asia/Shanghai > /etc/timezone && apk add ca-certificates

RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tencent.com/g' /etc/apk/repositories \
&& apk add --update --no-cache python3 py3-pip nginx \
&& mkdir -p /run/nginx \
&& rm -rf /var/cache/apk/*

WORKDIR /app

COPY ./requirements.txt /app/requirements.txt

RUN pip config set global.index-url http://mirrors.cloud.tencent.com/pypi/simple \
&& pip config set global.trusted-host mirrors.cloud.tencent.com \
&& pip install --upgrade pip --break-system-packages \
&& pip install --user -r requirements.txt --break-system-packages

COPY nginx.conf /etc/nginx/nginx.conf

COPY . /app

CMD ["sh", "-c", "python3 app.py & nginx -g 'daemon off;'"]
3 changes: 3 additions & 0 deletions web/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# 小程序的网页入口

> 为了减少小程序被封风险而添加的网页入口,没有任何功能
140 changes: 140 additions & 0 deletions web/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@

from fastapi.responses import JSONResponse, RedirectResponse, Response
from fastapi import FastAPI, Body, APIRouter, Request
from fastapi.exceptions import RequestValidationError
from starlette.exceptions import HTTPException
from fastapi.staticfiles import StaticFiles
from contextlib import asynccontextmanager
import datetime
import uvicorn
import socket
import httpx


@asynccontextmanager
async def lifespan(app: FastAPI):
yield

app = FastAPI(lifespan=lifespan, redoc_url=None, docs_url=None)


@app.get("/api/login")
async def login(request: Request, username: str, password: str):
""" 登录 """
async with httpx.AsyncClient() as client:
resp = await client.get("https://passport2-api.chaoxing.com/v11/loginregister", params={
"cx_xxt_passport": "json",
"roleSelect": "true",
"uname": username,
"code": password,
"loginType": "1",
})
resp2 = JSONResponse(resp.json())
for key, value in resp.cookies.items():
resp2.set_cookie(key, value, max_age=3600*24*7)
return resp2


@app.get("/api/get_courses")
async def get_courses(request: Request):
""" 获取课程列表 """
async with httpx.AsyncClient(cookies=dict(request.cookies)) as client:
resp = await client.get("https://mooc1-api.chaoxing.com/mycourse/backclazzdata", params={
'view': 'json',
'rss': '1',
})
return JSONResponse(resp.json())


app.mount("/", StaticFiles(directory="public"), name="public")


@app.exception_handler(HTTPException)
async def http_exception_handler(request: Request, exc: HTTPException):
if exc.status_code == 404:
return RedirectResponse("/index.html", status_code=302)
else:
return JSONResponse({
"status": -1,
"msg": exc.detail,
"data": None,
"time": int(datetime.datetime.now().timestamp()),
}, status_code=exc.status_code)


@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
return JSONResponse({
"status": -1,
"msg": "参数错误, 请检查参数",
"data": {
"body": exc.body,
"query": {
"raw": str(request.query_params),
"parsed": dict(request.query_params),
},
"error": exc.errors(),
},
"time": int(datetime.datetime.now().timestamp()),
}, status_code=422)


@app.exception_handler(Exception)
async def exception_handler(request: Request, exc: Exception):
return JSONResponse({
"status": -1,
"msg": "服务器内部错误, 请联系管理员! 邮箱: [email protected]",
"time": int(datetime.datetime.now().timestamp()),
}, status_code=500)


@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
starttime = datetime.datetime.now()
response: Response = await call_next(request)
endtime = datetime.datetime.now()
response.headers["X-Process-Time"] = str(
int((endtime - starttime).total_seconds()))
response.headers["X-Client-Host"] = request.client.host
return response


def get_localhost():
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
ip = s.getsockname()[0]
except Exception as e:
return None
else:
return ip
finally:
s.close()


if __name__ == "__main__":
starttime = datetime.datetime.now().strftime(r"%Y-%m-%d %H:%M:%S")
from utils.logger import set_log_formatter
set_log_formatter()
import logging as lg
logging = lg.getLogger("uvicorn")
try:
logging.info(f"服务已启动, 请访问 http://{get_localhost()}:8080")
uvicorn.run(
app="app:app",
host="0.0.0.0",
port=8080,
reload=False,
forwarded_allow_ips="*",
log_config=None,
workers=1,
headers=[
("Server", "Misaka Network Distributed Server"),
("X-Powered-By", "Misaka Network Studio"),
("X-Statement", "This service is provided by Misaka Network Studio. For complaints/cooperation, please email [email protected]"),
("X-Copyright", "© 2024 Misaka Network Studio. All rights reserved."),
("X-Server-Start-Time", starttime),
],
)
except KeyboardInterrupt:
logging.info("Ctrl+C 终止服务")
37 changes: 37 additions & 0 deletions web/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
user nginx;
worker_processes auto;

error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
set_real_ip_from 0.0.0.0/0;
real_ip_header X-Forwarded-For;
server_tokens off;
real_ip_recursive on;

server {
listen 80;
server_name localhost;

location / {
root /app/public;
index index.html;
}

location /api {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
Binary file added web/public/favicon.ico
Binary file not shown.
Loading

0 comments on commit b7b34f4

Please sign in to comment.