# CryskuraHTTP
<div align="center">
<img src="https://github.com/HofNature/CryskuraHTTP/raw/main/CryskuraHTTP.png" alt="CryskuraHTTP Logo" width="500">
CryskuraHTTP is a lightweight, customizable HTTP(s) server implemented in Python that supports basic HTTP(s) functionalities, including serving files and handling errors, with support for custom services, API calls, and authentication.
</div>
## Features
CryskuraHTTP is an extension of Python's built-in `http.server`, with minimal dependencies. You can leverage it to implement Python HTTP services without needing to install large software or libraries. It can also be used as a file sharing tool, supporting file serving and uploading through the browser, and can be launched from the Windows right-click menu.
- **Customizable Services**: Easily add custom services by extending the `BaseService` class.
- **Customizable API Calls**: Define custom API calls with the `APIService` class.
- **Error Handling**: Customizable error handling via the `ErrorService` class.
- **File Serving**: Serve files from a specified directory via the `FileService` class.
- **File Uploading**: Handle file uploads via POST requests with the `FileService` class.
- **WebPage Serving**: Serve web pages without allowing directory listing via the `PageService` class.
- **Customizable Routes**: Define custom routes for your services with the `Route` class.
- **Customizable Authentication**: Implement custom authentication for your services.
- **Auto uPnP Port Forwarding**: Automatically forward ports using uPnP.
- **Request Handling**: Handle GET, POST, HEAD requests.
- **Resumable Downloads**: Supports resumable downloads for large files when serving files.
- **Redirects**: Supports 301 and 308 redirects.
- **SSL Support**: Optionally enable SSL by providing a certificate file.
- **Threaded Server**: Supports multi-threaded request handling for better performance.
- **Command-Line Interface**: Run the server from the command line with custom settings.
- **Right Click Support**: Supports right-click context menu for launching the server on Windows.
This project is not designed to replace full-scale, production-grade HTTP servers. Instead, it is ideal for small-scale web UI development or for use alongside tools like `pywebview` and `qtwebengine`. So don't expect it to handle thousands of concurrent connections or to have advanced features like load balancing or caching.
## Requirements
- Python 3.x
- `psutil` library
## Installation
1. Install the package using pip:
```sh
pip install cryskura
```
2. You can also download whl file from [GitHub Releases](https://github.com/HofNature/CryskuraHTTP/releases) and install it using pip:
```sh
pip install cryskura-1.0-py3-none-any.wh
```
3. Clone the repository and install manually if you want to modify the source code:
```sh
git clone https://github.com/HofNature/CryskuraHTTP.git
cd CryskuraHTTP
python setup.py install
```
## Quick Start
### Starting the Server
To start the server with default settings:
```python
from cryskura import Server
server = HTTPServer(interface="127.0.0.1", port=8080)
server.start()
```
This will start the server on `localhost` at port `8080` and serve files from the current directory.
Or you can run the server from the command line:
```sh
cryskura --interface 127.0.0.1 --port 8080 --path /path/to/serve
```
This will start the server on `localhost` at port `8080` and serve files from `/path/to/serve`.
### Register to Right-Click Menu
You can add the server to the right-click context menu on Windows by running:
```sh
cryskura --addRightClick # You can also use -ar as a short form
```
> **Note**: If arguments like `--interface`, `--port`, `--browser`, etc., are provided, the server will start with the specified settings when launched from the right-click menu.
If you want to remove it from the right-click menu, run:
```sh
cryskura --removeRightClick # You can also use -rr as a short form
```
> **Note**: This feature is only available on Windows. For Windows 11 24h2 and above, if Sudo is enabled, it will be called automatically; otherwise, you need to run it manually with administrator privileges.
### Stopping the Server
When using the Python API, you can stop the server by calling the `stop()` method:
```python
server.stop()
```
> **Note**: Only the threaded server can be stopped using this method. The non-threaded server will block the thread, so it cannot be stopped by calling the `stop()` method. You can stop the non-threaded server by pressing `Ctrl+C` in the terminal.
When using the command line, you can stop the server by pressing `Ctrl+C` in the terminal.
## Command-Line Interface
You can get help on the command-line interface by running:
```sh
cryskura --help
```
This will show the available options:
- `-h, --help`: Show help message and exit.
- `-u, --uPnP`: Enable uPnP port forwarding.
- `-v, --version`: Show program's version number and exit.
- `-b, --browser`: Open the browser after starting the server.
- `-ba, --browserAddress`: The address to open in the browser.
- `-w, --webMode`: Enable web mode, which means only files can be accessed, not directories.
- `-f, --forcePort`: Force to use the specified port even if it is already in use.
- `-t, --allowUpload`: Allow file upload.
- `-r, --allowResume`: Allow resume download.
- `-ar, --addRightClick`: Add to right-click menu.
- `-rr, --removeRightClick`: Remove from right-click menu.
- `-d PATH, --path PATH`: The path to the directory to serve.
- `-n NAME, --name NAME`: The name of the server.
- `-p PORT, --port PORT`: The port to listen on.
- `-c CERTFILE, --certfile CERTFILE`: The path to the certificate file.
- `-i INTERFACE, --interface INTERFACE`: The interface to listen on.
- `-j HTTP_TO_HTTPS, --http_to_https HTTP_TO_HTTPS`: Port to redirect HTTP requests to HTTPS.
## Using as a Python Module
### Custom Configuration
You can customize the server by providing different parameters:
```python
from cryskura import Server
from cryskura.Services import FileService,PageService,RedirectService,APIService
# Create services
fs=FileService(r"/path/to/file","/Files",allowResume=True,allowUpload=True)
rs=RedirectService("/Redirect","https://www.google.com")
ps=PageService(r"/path/to/html","/")
# Define the API function
def APIFunc(request, path, args, headers, content, method):
"""
A sample API function for handling API requests.
Parameters:
- request: The HTTP request object.
- path: The sub-path of the request URL after the API endpoint.
- args: The query parameters from the URL as a dictionary.
- headers: The headers from the request as a dictionary.
- content: The body content of the request as bytes.
- method: The HTTP method used (e.g., "GET", "POST").
Returns:
- code: An integer HTTP status code (e.g., 200 for success).
- response_headers: A dictionary of headers to include in the response.
- response_content: The body content to send in the response as bytes.
"""
print(f"API {method} {path} {args}")
# Process the request and generate a response
code = 200 # HTTP status code
response_headers = {"Content-Type": "text/plain"} # Response headers
response_content = b"API Call" # Response body content
return code, response_headers, response_content
# Create API service
api=APIService("/API",func=APIFunc)
# Start the server
server=Server(services=[fs,rs,api,ps],certfile="/path/to/cert.pem",uPnP=True)
server.start()
```
This will start the server with the following services:
- FileService: Serves files from `/path/to/file` at the `/Files` endpoint, allowing resumable downloads and file uploads.
- RedirectService: Redirects requests from `/Redirect` to `https://www.google.com`.
- PageService: Serves web pages from `/path/to/html` at the root endpoint `/`.
- APIService: Handles API calls at the `/API` endpoint, printing request details and responding with a plain text message.
And with the following settings:
- SSL Support: Uses the certificate file located at `/path/to/cert.pem` for SSL encryption.
- uPnP Port Forwarding: Automatically forwards ports using uPnP.
### Route Priority
If multiple services have conflicting routes, the priority is determined by the order in which the services are listed in the `services` parameter. The service listed first will have the highest priority, and so on.
For example:
```python
from cryskura import Server
from cryskura.Services import FileService, PageService
fs = FileService(r"/path/to/files", "/files")
ps = PageService(r"/path/to/pages", "/")
server = Server(services=[fs,ps])
server.start()
```
In this case, `FileService` will have priority over `PageService` for routes that conflict between the two services. So if a request is made to `/files/index.html`, it will be handled by `FileService` and not `PageService`.
### Authentication
To implement custom authentication, you need to define an authentication function and pass it to the service that requires authentication. The authentication function should accept four parameters: `cookies`, `path`, `args`, and `operation`. It should return `True` if the authentication is successful, and `False` otherwise.
Here is an example of how to implement custom authentication:
```python
from cryskura import Server
from cryskura.Services import FileService
# Define authentication function
def AUTHFunc(cookies, path, args, operation):
print(f"AUTH {operation} {path} {args}")
if args.get('passwd') == "passwd" and operation == "GET":
return True
elif args.get('passwd') == "admin" and operation == "POST":
return True
return False
# Create a file service with authentication
fs = FileService(r"/path/to/files", "/files", allowResume=True, auth_func=AUTHFunc)
# Start the server
server = Server(services=[fs])
server.start()
```
In this example, the `AUTHFunc` function checks the `passwd` parameter in the request arguments to authenticate GET and POST requests. If the `passwd` parameter is `passwd` for GET requests or `admin` for POST requests, the authentication is successful. Otherwise, the authentication fails.
You can customize the `AUTHFunc` function to implement your own authentication logic, such as checking cookies, headers, or other request parameters.
### Custom Services
To create a custom service, extend the `BaseService` class and implement the required methods:
```python
from cryskura.Services import BaseService, Route
class MyService(BaseService):
def __init__(self):
routes = [Route("/myservice", ["GET"], "exact")]
super().__init__(routes)
def handle_GET(self, request, path, args):
request.send_response(200)
request.send_header("Content-Type", "text/plain")
request.end_headers()
request.wfile.write(b"Hello from MyService!")
```
## Using the uPnP Client
CryskuraHTTP includes a built-in uPnP client to facilitate automatic port forwarding. This can be particularly useful when running the server behind a router or firewall.
### Enabling uPnP
To enable uPnP port forwarding, you can use the `--uPnP` flag when starting the server from the command line:
```sh
cryskura --interface 0.0.0.0 --port 8080 --path /path/to/serve --uPnP
```
### Using uPnP in Python
You can also enable uPnP port forwarding when starting the server using the Python API:
```python
from cryskura import Server
server = Server(interface="0.0.0.0", port=8080, uPnP=True)
server.start()
```
### Custom uPnP Configuration
The built-in uPnP client can be used independently for custom port forwarding needs. Here’s how you can use the `uPnPClient` class directly in your Python code:
#### Initializing the uPnP Client
First, you need to initialize the `uPnPClient` with the desired network interface:
```python
from cryskura import uPnP
# Initialize uPnP client for a specific interface
upnp_client = uPnP(interface="0.0.0.0")
# Use 0.0.0.0 for all IPv4 interfaces
if upnp_client.available:
print("uPnP client initialized successfully.")
else:
print("uPnP client is not available.")
```
#### Adding a Port Mapping
To add a port mapping, use the `add_port_mapping` method:
```python
if upnp_client.available:
success, mappings = upnp_client.add_port_mapping(
remote_port=8080,
local_port=8080,
protocol="TCP",
description="CryskuraHTTP Server"
)
if success:
print("Port mapping added successfully.")
for mapping in mappings:
print(f"Service is available at {mapping[0]}:{mapping[1]}")
else:
print("Failed to add port mapping.")
```
This will add a port mapping for port `8080` on the remote device to port `8080` on the local device using the TCP protocol. The description is just a label for the mapping, which can be used to identify it later.
#### Removing All Port Mappings
To remove port mappings, use the `remove_port_mapping` method:
```python
if upnp_client.available:
upnp_client.remove_port_mapping()
print("Port mapping removed.")
```
This will remove all port mappings that were added by the client. It's a good practice to remove port mappings when they are no longer needed. You can place this code in a cleanup section of your script or in an exception handler to ensure that the mappings are removed even if an error occurs. For example:
```python
try:
Your code here...
except Exception as exception:
upnp_client.remove_port_mapping()
raise exception
```
This will ensure that the port mappings are removed even if an exception occurs during the execution of your code.
### Troubleshooting uPnP
If you encounter issues with uPnP, ensure that:
- Your router **supports** uPnP and has it **enabled**.
- The `upnpclient` library is installed. You can install it using:
```sh
pip install upnpclient
```
or install the `cryskura` package with the `upnp` extra:
```sh
pip install cryskura[upnp]
```
- The network interface specified is correct and accessible.
For more detailed information on the `uPnPClient` class and its methods, refer to the source code in the `uPnP.py` file.
## License
This project is licensed under the MIT License. See the [LICENSE](https://github.com/HofNature/CryskuraHTTP/blob/main/LICENSE) file for details.
## Contributing
Contributions are welcome! Please open an issue or submit a pull request.
## Contact
For any questions or suggestions, please open an issue here on [GitHub](https://github.com/HofNature/CryskuraHTTP/issues).
---
Enjoy using CryskuraHTTP!
# CryskuraHTTP
<div align="center">
<img src="https://github.com/HofNature/CryskuraHTTP/raw/main/CryskuraHTTP.png" alt="CryskuraHTTP Logo" width="500">
CryskuraHTTP 是一个用 Python 实现的轻量级、可定制的 HTTP(s) 服务器,支持基本的 HTTP(s) 功能,包括文件服务和错误处理,并支持自定义服务和鉴权。
</div>
## 特性
CryskuraHTTP 是 Python 内置 `http.server` 的扩展,具有很少的依赖。您可以利用它实现 Python HTTP 服务,而无需安装大型软件或库。它还可以用作文件共享工具,支持通过浏览器进行文件下载和上传,并可通过 Windows 右键菜单启动。
- **可定制服务**:通过扩展 `BaseService` 类轻松添加自定义服务。
- **可定制 API 调用**:使用 `APIService` 类定义自定义 API 调用。
- **错误处理**:通过 `ErrorService` 类实现可定制的错误处理。
- **文件服务**:通过 `FileService` 类从指定目录提供文件服务。
- **文件上传**:通过 `FileService` 类处理通过 POST 请求的文件上传。
- **网页服务**:通过 `PageService` 类提供网页服务,而不允许用户查看目录列表。
- **可定制路由**:使用 `Route` 类为您的服务定义自定义路由。
- **可定制身份验证**:为您的服务实现自定义身份验证。
- **自动 uPnP 端口转发**:使用 uPnP 自动转发端口。
- **请求处理**:处理 GET、POST、HEAD 请求。
- **可续传下载**:在提供文件服务时支持大文件的可续传下载。
- **重定向**:支持 301 和 308 重定向。
- **SSL 支持**:通过提供证书文件可选启用 SSL。
- **多线程服务器**:支持多线程请求处理以提高性能。
- **命令行界面**:通过命令行运行服务器并进行自定义设置。
- **右键支持**:支持在 Windows 上通过右键菜单启动服务器。
该项目并非设计用于替代全规模、生产级 HTTP 服务器。它更适合小规模的 Web UI 开发或与 `pywebview` 和 `qtwebengine` 等工具一起使用。因此,不要期望它能处理数千个并发连接或具有负载均衡或缓存等高级功能。
## 要求
- Python 3.x
- `psutil` 库
## 安装
1. 使用 pip 安装包:
```sh
pip install cryskura
```
2. 您也可以从 [GitHub Releases](https://github.com/HofNature/CryskuraHTTP/releases) 下载 whl 文件并使用 pip 安装:
```sh
pip install cryskura-1.0-py3-none-any.whl
```
3. 如果您想修改源代码,可以克隆仓库并手动安装:
```sh
git clone https://github.com/HofNature/CryskuraHTTP.git
cd CryskuraHTTP
python setup.py install
```
## 快速开始
### 启动服务器
使用默认设置启动服务器:
```python
from cryskura import Server
server = HTTPServer(interface="127.0.0.1", port=8080)
server.start()
```
这将在 `localhost` 上的端口 `8080` 启动服务器,并从当前目录提供文件服务。
或者,您可以从命令行运行服务器:
```sh
cryskura --interface 127.0.0.1 --port 8080 --path /path/to/serve
```
这将在 `localhost` 上的端口 `8080` 启动服务器,并从 `/path/to/serve` 提供文件服务。
### 注册到右键菜单
您可以通过运行以下命令将服务器添加到 Windows 的右键菜单:
```sh
cryskura --addRightClick # 您也可以使用 -ar 作为简写
```
> **注意**:如果提供了 `--interface`、`--port`、`--browser` 等参数,当从右键菜单启动服务器时,将使用指定的设置。
如果您想从右键菜单中移除它,请运行:
```sh
cryskura --removeRightClick # 您也可以使用 -rr 作为简写
```
> **注意**:此功能仅在 Windows 上可用。对于 Windows 11 24h2 及以上版本,如果启用了 Sudo,它将自动调用;否则,您需要手动以管理员权限运行。
### 停止服务器
使用 Python API 时,您可以通过调用 `stop()` 方法停止服务器:
```python
server.stop()
```
> **注意**:只有多线程服务器可以使用此方法停止。非多线程服务器将阻塞线程,因此无法通过调用 `stop()` 方法停止。您可以通过在终端中按 `Ctrl+C` 停止非多线程服务器。
使用命令行时,您可以通过在终端中按 `Ctrl+C` 停止服务器。
## 命令行界面
您可以通过运行以下命令获取命令行界面的帮助:
```sh
cryskura --help
```
这将显示可用选项:
- `-h, --help`:显示帮助信息并退出。
- `-u, --uPnP`:启用 uPnP 端口转发。
- `-v, --version`:显示程序的版本号并退出。
- `-b, --browser`:启动服务器后打开浏览器。
- `-ba, --browserAddress`:浏览器打开的地址。
- `-w, --webMode`:启用 Web 模式,这意味着只能访问文件,不能访问目录。
- `-f, --forcePort`:强制使用指定端口,即使该端口已被占用。
- `-t, --allowUpload`:允许文件上传。
- `-r, --allowResume`:允许续传下载。
- `-ar, --addRightClick`:添加到右键菜单。
- `-rr, --removeRightClick`:从右键菜单中移除。
- `-d PATH, --path PATH`:要提供服务的目录路径。
- `-n NAME, --name NAME`:服务器的名称。
- `-p PORT, --port PORT`:监听的端口。
- `-c CERTFILE, --certfile CERTFILE`:证书文件的路径。
- `-i INTERFACE, --interface INTERFACE`:监听的接口。
- `-j HTTP_TO_HTTPS, --http_to_https HTTP_TO_HTTPS`:将 HTTP 请求重定向到 HTTPS 的端口。
## 作为 Python 模块使用
### 自定义配置
您可以通过提供不同的参数来自定义服务器:
```python
from cryskura import Server
from cryskura.Services import FileService, PageService, RedirectService, APIService
# 创建服务
fs = FileService(r"/path/to/file", "/Files", allowResume=True, allowUpload=True)
rs = RedirectService("/Redirect", "https://www.google.com")
ps = PageService(r"/path/to/html", "/")
# 定义 API 函数
def APIFunc(request, path, args, headers, content, method):
"""
用于处理 API 请求的示例函数。
参数:
- request:HTTP 请求对象。
- path:API 端点之后的请求 URL 子路径。
- args:URL 中的查询参数,字典形式。
- headers:请求头,字典形式。
- content:请求的主体内容,字节类型。
- method:使用的 HTTP 方法(例如 "GET"、"POST")。
返回:
- code:整数类型的 HTTP 状态码(例如 200 表示成功)。
- response_headers:要包含在响应中的头信息,字典形式。
- response_content:响应的主体内容,字节类型。
"""
# 为演示目的,我们将简单返回一个 200 OK 状态和一个纯文本消息。
code = 200
response_headers = {"Content-Type": "text/plain"}
response_content = b"API 调用"
return code, response_headers, response_content
# 创建 API 服务
api = APIService("/API", func=APIFunc)
# 启动服务器
server = Server(services=[fs, rs, api, ps], certfile="/path/to/cert.pem", uPnP=True)
server.start()
```
这将启动具有以下服务的服务器:
- FileService:在 `/Files` 端点提供 `/path/to/file` 的文件服务,允许续传下载和文件上传。
- RedirectService:将 `/Redirect` 的请求重定向到 `https://www.google.com`。
- PageService:在根端点 `/` 提供 `/path/to/html` 的网页服务。
- APIService:在 `/API` 端点处理 API 调用,打印请求详情并响应纯文本消息。
以及以下设置:
- SSL 支持:使用位于 `/path/to/cert.pem` 的证书文件进行 SSL 加密。
- uPnP 端口转发:使用 uPnP 自动转发端口。
### 路由优先级
如果多个服务有冲突的路由,优先级由 `services` 参数中服务的顺序决定。列在前面的服务优先级最高,依此类推。
例如:
```python
from cryskura import Server
from cryskura.Services import FileService, PageService
fs = FileService(r"/path/to/files", "/files")
ps = PageService(r"/path/to/pages", "/")
server = Server(services=[fs, ps])
server.start()
```
在这种情况下,对于 `FileService` 和 `PageService` 之间冲突的路由,`FileService` 将优先处理。因此,如果请求 `/files/index.html`,将由 `FileService` 处理,而不是 `PageService`。
### 身份验证
要实现自定义身份验证,您需要定义一个身份验证函数并将其传递给需要身份验证的服务。身份验证函数应接受四个参数:`cookies`、`path`、`args` 和 `operation`。如果身份验证成功,应返回 `True`,否则返回 `False`。
以下是如何实现自定义身份验证的示例:
```python
from cryskura import Server
from cryskura.Services import FileService
# 定义身份验证函数
def AUTHFunc(cookies, path, args, operation):
print(f"AUTH {operation} {path} {args}")
if args.get('passwd') == "passwd" and operation == "GET":
return True
elif args.get('passwd') == "admin" and operation == "POST":
return True
return False
# 创建带有身份验证的文件服务
fs = FileService(r"/path/to/files", "/files", allowResume=True, auth_func=AUTHFunc)
# 启动服务器
server = Server(services=[fs])
server.start()
```
在此示例中,`AUTHFunc` 函数检查请求参数中的 `passwd` 参数以验证 GET 和 POST 请求。如果 `passwd` 参数为 GET 请求的 `passwd` 或 POST 请求的 `admin`,则身份验证成功。否则,身份验证失败。
您可以自定义 `AUTHFunc` 函数以实现自己的身份验证逻辑,例如检查 cookies、头信息或其他请求参数。
### 自定义服务
要创建自定义服务,请扩展 `BaseService` 类并实现所需的方法:
```python
from cryskura.Services import BaseService, Route
class MyService(BaseService):
def __init__(self):
routes = [Route("/myservice", ["GET"], "exact")]
super().__init__(routes)
def handle_GET(self, request, path, args):
request.send_response(200)
request.send_header("Content-Type", "text/plain")
request.end_headers()
request.wfile.write(b"Hello from MyService!")
```
## 使用 uPnP 客户端
CryskuraHTTP 包含一个内置的 uPnP 客户端,以便自动端口转发。这在路由器或防火墙后运行服务器时特别有用。
### 启用 uPnP
要启用 uPnP 端口转发,您可以在从命令行启动服务器时使用 `--uPnP` 标志:
```sh
cryskura --interface 0.0.0.0 --port 8080 --path /path/to/serve --uPnP
```
### 在 Python 中使用 uPnP
您还可以在使用 Python API 启动服务器时启用 uPnP 端口转发:
```python
from cryskura import Server
server = Server(interface="0.0.0.0", port=8080, uPnP=True)
server.start()
```
### 自定义 uPnP 配置
内置的 uPnP 客户端可以独立使用以满足自定义端口转发需求。以下是如何在 Python 代码中直接使用 `uPnPClient` 类:
#### 初始化 uPnP 客户端
首先,您需要使用所需的网络接口初始化 `uPnPClient`:
```python
from cryskura import uPnP
# 为特定接口初始化 uPnP 客户端
upnp_client = uPnP(interface="0.0.0.0")
# 使用 0.0.0.0 表示所有 IPv4 接口
if upnp_client.available:
print("uPnP 客户端初始化成功。")
else:
print("uPnP 客户端不可用。")
```
#### 添加端口映射
要添加端口映射,请使用 `add_port_mapping` 方法:
```python
if upnp_client.available:
success, mappings = upnp_client.add_port_mapping(
remote_port=8080,
description="CryskuraHTTP Server"
)
if success:
print("端口映射添加成功。")
else:
print("添加端口映射失败。")
```
这将在远程设备的端口 `8080` 上添加到本地设备端口 `8080` 的端口映射,使用 TCP 协议。描述只是映射的标签,可以用于以后识别它。
#### 移除所有端口映射
要移除端口映射,请使用 `remove_port_mapping` 方法:
```python
if upnp_client.available:
upnp_client.remove_port_mapping()
print("端口映射已移除。")
```
这将移除客户端添加的所有端口映射。最好在不再需要时移除端口映射。您可以将此代码放在脚本的清理部分或异常处理程序中,以确保即使发生错误也能移除映射。例如:
```python
try:
# 您的代码...
except Exception as exception:
upnp_client.remove_port_mapping()
raise exception
```
这将确保即使在代码执行期间发生异常,也能移除端口映射。
### uPnP 故障排除
如果遇到 uPnP 问题,请确保:
- 您的路由器 **支持** uPnP 并且已 **启用**。
- 安装了 `upnpclient` 库。您可以使用以下命令安装它:
```sh
pip install upnpclient
```
- 指定的网络接口是正确且可访问的。
有关 `uPnPClient` 类及其方法的详细信息,请参阅 `uPnP.py` 文件中的源代码。
## 许可证
本项目采用 MIT 许可证。有关详细信息,请参阅 [LICENSE](https://github.com/HofNature/CryskuraHTTP/blob/main/LICENSE) 文件。
## 贡献
欢迎贡献!请提交问题或拉取请求。
## 联系方式
如有任何问题或建议,请在 [GitHub](https://github.com/HofNature/CryskuraHTTP/issues) 上提交问题。
---
享受使用 CryskuraHTTP 吧!
Raw data
{
"_id": null,
"home_page": "https://github.com/HofNature/CryskuraHTTP",
"name": "cryskura",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": null,
"keywords": "http, https, server, web, http server, https server",
"author": "HofNature",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/3d/ec/e44a76492d786f813b113828806bf97d394ebeeb88bba74079780e12a827/cryskura-1.0b6.tar.gz",
"platform": null,
"description": "# CryskuraHTTP\r\n\r\n<div align=\"center\">\r\n <img src=\"https://github.com/HofNature/CryskuraHTTP/raw/main/CryskuraHTTP.png\" alt=\"CryskuraHTTP Logo\" width=\"500\">\r\n\r\n\r\n\r\nCryskuraHTTP is a lightweight, customizable HTTP(s) server implemented in Python that supports basic HTTP(s) functionalities, including serving files and handling errors, with support for custom services, API calls, and authentication.\r\n\r\n</div>\r\n\r\n## Features\r\n\r\nCryskuraHTTP is an extension of Python's built-in `http.server`, with minimal dependencies. You can leverage it to implement Python HTTP services without needing to install large software or libraries. It can also be used as a file sharing tool, supporting file serving and uploading through the browser, and can be launched from the Windows right-click menu.\r\n\r\n- **Customizable Services**: Easily add custom services by extending the `BaseService` class.\r\n- **Customizable API Calls**: Define custom API calls with the `APIService` class.\r\n- **Error Handling**: Customizable error handling via the `ErrorService` class.\r\n- **File Serving**: Serve files from a specified directory via the `FileService` class.\r\n- **File Uploading**: Handle file uploads via POST requests with the `FileService` class.\r\n- **WebPage Serving**: Serve web pages without allowing directory listing via the `PageService` class.\r\n- **Customizable Routes**: Define custom routes for your services with the `Route` class.\r\n- **Customizable Authentication**: Implement custom authentication for your services.\r\n- **Auto uPnP Port Forwarding**: Automatically forward ports using uPnP.\r\n- **Request Handling**: Handle GET, POST, HEAD requests.\r\n- **Resumable Downloads**: Supports resumable downloads for large files when serving files.\r\n- **Redirects**: Supports 301 and 308 redirects.\r\n- **SSL Support**: Optionally enable SSL by providing a certificate file.\r\n- **Threaded Server**: Supports multi-threaded request handling for better performance.\r\n- **Command-Line Interface**: Run the server from the command line with custom settings.\r\n- **Right Click Support**: Supports right-click context menu for launching the server on Windows.\r\n\r\nThis project is not designed to replace full-scale, production-grade HTTP servers. Instead, it is ideal for small-scale web UI development or for use alongside tools like `pywebview` and `qtwebengine`. So don't expect it to handle thousands of concurrent connections or to have advanced features like load balancing or caching.\r\n\r\n## Requirements\r\n\r\n- Python 3.x\r\n- `psutil` library\r\n\r\n## Installation\r\n\r\n1. Install the package using pip:\r\n\r\n ```sh\r\n pip install cryskura\r\n ```\r\n\r\n2. You can also download whl file from [GitHub Releases](https://github.com/HofNature/CryskuraHTTP/releases) and install it using pip:\r\n\r\n ```sh\r\n pip install cryskura-1.0-py3-none-any.wh\r\n ```\r\n\r\n3. Clone the repository and install manually if you want to modify the source code:\r\n\r\n ```sh\r\n git clone https://github.com/HofNature/CryskuraHTTP.git\r\n cd CryskuraHTTP\r\n python setup.py install\r\n ```\r\n\r\n## Quick Start\r\n\r\n### Starting the Server\r\n\r\nTo start the server with default settings:\r\n\r\n```python\r\nfrom cryskura import Server\r\nserver = HTTPServer(interface=\"127.0.0.1\", port=8080)\r\nserver.start()\r\n```\r\n\r\nThis will start the server on `localhost` at port `8080` and serve files from the current directory.\r\n\r\nOr you can run the server from the command line:\r\n\r\n```sh\r\ncryskura --interface 127.0.0.1 --port 8080 --path /path/to/serve\r\n```\r\n\r\nThis will start the server on `localhost` at port `8080` and serve files from `/path/to/serve`.\r\n\r\n### Register to Right-Click Menu\r\n\r\nYou can add the server to the right-click context menu on Windows by running:\r\n\r\n```sh\r\ncryskura --addRightClick # You can also use -ar as a short form\r\n```\r\n\r\n> **Note**: If arguments like `--interface`, `--port`, `--browser`, etc., are provided, the server will start with the specified settings when launched from the right-click menu.\r\n\r\nIf you want to remove it from the right-click menu, run:\r\n\r\n```sh\r\ncryskura --removeRightClick # You can also use -rr as a short form\r\n```\r\n\r\n> **Note**: This feature is only available on Windows. For Windows 11 24h2 and above, if Sudo is enabled, it will be called automatically; otherwise, you need to run it manually with administrator privileges.\r\n\r\n### Stopping the Server\r\n\r\nWhen using the Python API, you can stop the server by calling the `stop()` method:\r\n\r\n```python\r\nserver.stop()\r\n```\r\n\r\n> **Note**: Only the threaded server can be stopped using this method. The non-threaded server will block the thread, so it cannot be stopped by calling the `stop()` method. You can stop the non-threaded server by pressing `Ctrl+C` in the terminal.\r\n\r\nWhen using the command line, you can stop the server by pressing `Ctrl+C` in the terminal.\r\n\r\n## Command-Line Interface\r\n\r\nYou can get help on the command-line interface by running:\r\n\r\n```sh\r\ncryskura --help\r\n```\r\n\r\nThis will show the available options:\r\n\r\n- `-h, --help`: Show help message and exit.\r\n- `-u, --uPnP`: Enable uPnP port forwarding.\r\n- `-v, --version`: Show program's version number and exit.\r\n- `-b, --browser`: Open the browser after starting the server.\r\n- `-ba, --browserAddress`: The address to open in the browser.\r\n- `-w, --webMode`: Enable web mode, which means only files can be accessed, not directories.\r\n- `-f, --forcePort`: Force to use the specified port even if it is already in use.\r\n- `-t, --allowUpload`: Allow file upload.\r\n- `-r, --allowResume`: Allow resume download.\r\n- `-ar, --addRightClick`: Add to right-click menu.\r\n- `-rr, --removeRightClick`: Remove from right-click menu.\r\n- `-d PATH, --path PATH`: The path to the directory to serve.\r\n- `-n NAME, --name NAME`: The name of the server.\r\n- `-p PORT, --port PORT`: The port to listen on.\r\n- `-c CERTFILE, --certfile CERTFILE`: The path to the certificate file.\r\n- `-i INTERFACE, --interface INTERFACE`: The interface to listen on.\r\n- `-j HTTP_TO_HTTPS, --http_to_https HTTP_TO_HTTPS`: Port to redirect HTTP requests to HTTPS.\r\n\r\n## Using as a Python Module\r\n\r\n### Custom Configuration\r\n\r\nYou can customize the server by providing different parameters:\r\n\r\n```python\r\nfrom cryskura import Server\r\nfrom cryskura.Services import FileService,PageService,RedirectService,APIService\r\n\r\n# Create services\r\nfs=FileService(r\"/path/to/file\",\"/Files\",allowResume=True,allowUpload=True)\r\nrs=RedirectService(\"/Redirect\",\"https://www.google.com\")\r\nps=PageService(r\"/path/to/html\",\"/\")\r\n\r\n# Define the API function\r\ndef APIFunc(request, path, args, headers, content, method):\r\n \"\"\"\r\n A sample API function for handling API requests.\r\n\r\n Parameters:\r\n - request: The HTTP request object.\r\n - path: The sub-path of the request URL after the API endpoint.\r\n - args: The query parameters from the URL as a dictionary.\r\n - headers: The headers from the request as a dictionary.\r\n - content: The body content of the request as bytes.\r\n - method: The HTTP method used (e.g., \"GET\", \"POST\").\r\n\r\n Returns:\r\n - code: An integer HTTP status code (e.g., 200 for success).\r\n - response_headers: A dictionary of headers to include in the response.\r\n - response_content: The body content to send in the response as bytes.\r\n \"\"\"\r\n print(f\"API {method} {path} {args}\")\r\n # Process the request and generate a response\r\n code = 200 # HTTP status code\r\n response_headers = {\"Content-Type\": \"text/plain\"} # Response headers\r\n response_content = b\"API Call\" # Response body content\r\n return code, response_headers, response_content\r\n\r\n# Create API service\r\napi=APIService(\"/API\",func=APIFunc)\r\n\r\n# Start the server\r\nserver=Server(services=[fs,rs,api,ps],certfile=\"/path/to/cert.pem\",uPnP=True)\r\nserver.start()\r\n```\r\n\r\nThis will start the server with the following services:\r\n\r\n- FileService: Serves files from `/path/to/file` at the `/Files` endpoint, allowing resumable downloads and file uploads.\r\n- RedirectService: Redirects requests from `/Redirect` to `https://www.google.com`.\r\n- PageService: Serves web pages from `/path/to/html` at the root endpoint `/`.\r\n- APIService: Handles API calls at the `/API` endpoint, printing request details and responding with a plain text message.\r\n\r\nAnd with the following settings:\r\n\r\n- SSL Support: Uses the certificate file located at `/path/to/cert.pem` for SSL encryption.\r\n- uPnP Port Forwarding: Automatically forwards ports using uPnP.\r\n\r\n### Route Priority\r\n\r\nIf multiple services have conflicting routes, the priority is determined by the order in which the services are listed in the `services` parameter. The service listed first will have the highest priority, and so on.\r\n\r\nFor example:\r\n\r\n```python\r\nfrom cryskura import Server\r\nfrom cryskura.Services import FileService, PageService\r\n\r\nfs = FileService(r\"/path/to/files\", \"/files\")\r\nps = PageService(r\"/path/to/pages\", \"/\")\r\n\r\nserver = Server(services=[fs,ps])\r\nserver.start()\r\n```\r\n\r\nIn this case, `FileService` will have priority over `PageService` for routes that conflict between the two services. So if a request is made to `/files/index.html`, it will be handled by `FileService` and not `PageService`.\r\n\r\n### Authentication\r\n\r\nTo implement custom authentication, you need to define an authentication function and pass it to the service that requires authentication. The authentication function should accept four parameters: `cookies`, `path`, `args`, and `operation`. It should return `True` if the authentication is successful, and `False` otherwise.\r\n\r\nHere is an example of how to implement custom authentication:\r\n\r\n```python\r\nfrom cryskura import Server\r\nfrom cryskura.Services import FileService\r\n\r\n# Define authentication function\r\ndef AUTHFunc(cookies, path, args, operation):\r\n print(f\"AUTH {operation} {path} {args}\")\r\n if args.get('passwd') == \"passwd\" and operation == \"GET\":\r\n return True\r\n elif args.get('passwd') == \"admin\" and operation == \"POST\":\r\n return True\r\n return False\r\n\r\n# Create a file service with authentication\r\nfs = FileService(r\"/path/to/files\", \"/files\", allowResume=True, auth_func=AUTHFunc)\r\n\r\n# Start the server\r\nserver = Server(services=[fs])\r\nserver.start()\r\n```\r\n\r\nIn this example, the `AUTHFunc` function checks the `passwd` parameter in the request arguments to authenticate GET and POST requests. If the `passwd` parameter is `passwd` for GET requests or `admin` for POST requests, the authentication is successful. Otherwise, the authentication fails. \r\n\r\nYou can customize the `AUTHFunc` function to implement your own authentication logic, such as checking cookies, headers, or other request parameters.\r\n\r\n### Custom Services\r\n\r\nTo create a custom service, extend the `BaseService` class and implement the required methods:\r\n\r\n```python\r\nfrom cryskura.Services import BaseService, Route\r\n\r\nclass MyService(BaseService):\r\n def __init__(self):\r\n routes = [Route(\"/myservice\", [\"GET\"], \"exact\")]\r\n super().__init__(routes)\r\n\r\n def handle_GET(self, request, path, args):\r\n request.send_response(200)\r\n request.send_header(\"Content-Type\", \"text/plain\")\r\n request.end_headers()\r\n request.wfile.write(b\"Hello from MyService!\")\r\n```\r\n\r\n## Using the uPnP Client\r\n\r\nCryskuraHTTP includes a built-in uPnP client to facilitate automatic port forwarding. This can be particularly useful when running the server behind a router or firewall.\r\n\r\n### Enabling uPnP\r\n\r\nTo enable uPnP port forwarding, you can use the `--uPnP` flag when starting the server from the command line:\r\n\r\n```sh\r\ncryskura --interface 0.0.0.0 --port 8080 --path /path/to/serve --uPnP\r\n```\r\n\r\n### Using uPnP in Python\r\n\r\nYou can also enable uPnP port forwarding when starting the server using the Python API:\r\n\r\n```python\r\nfrom cryskura import Server\r\n\r\nserver = Server(interface=\"0.0.0.0\", port=8080, uPnP=True)\r\nserver.start()\r\n```\r\n\r\n### Custom uPnP Configuration\r\n\r\nThe built-in uPnP client can be used independently for custom port forwarding needs. Here\u2019s how you can use the `uPnPClient` class directly in your Python code:\r\n\r\n#### Initializing the uPnP Client\r\n\r\nFirst, you need to initialize the `uPnPClient` with the desired network interface:\r\n\r\n```python\r\nfrom cryskura import uPnP\r\n\r\n# Initialize uPnP client for a specific interface\r\nupnp_client = uPnP(interface=\"0.0.0.0\")\r\n# Use 0.0.0.0 for all IPv4 interfaces\r\n\r\nif upnp_client.available:\r\n print(\"uPnP client initialized successfully.\")\r\nelse:\r\n print(\"uPnP client is not available.\")\r\n```\r\n\r\n#### Adding a Port Mapping\r\n\r\nTo add a port mapping, use the `add_port_mapping` method:\r\n\r\n```python\r\nif upnp_client.available:\r\n success, mappings = upnp_client.add_port_mapping(\r\n remote_port=8080, \r\n local_port=8080, \r\n protocol=\"TCP\", \r\n description=\"CryskuraHTTP Server\"\r\n )\r\n if success:\r\n print(\"Port mapping added successfully.\")\r\n for mapping in mappings:\r\n print(f\"Service is available at {mapping[0]}:{mapping[1]}\")\r\n else:\r\n print(\"Failed to add port mapping.\")\r\n```\r\n\r\nThis will add a port mapping for port `8080` on the remote device to port `8080` on the local device using the TCP protocol. The description is just a label for the mapping, which can be used to identify it later.\r\n\r\n#### Removing All Port Mappings\r\n\r\nTo remove port mappings, use the `remove_port_mapping` method:\r\n\r\n```python\r\nif upnp_client.available:\r\n upnp_client.remove_port_mapping()\r\n print(\"Port mapping removed.\")\r\n```\r\n\r\nThis will remove all port mappings that were added by the client. It's a good practice to remove port mappings when they are no longer needed. You can place this code in a cleanup section of your script or in an exception handler to ensure that the mappings are removed even if an error occurs. For example:\r\n\r\n```python\r\ntry:\r\n Your code here...\r\nexcept Exception as exception:\r\n upnp_client.remove_port_mapping()\r\n raise exception\r\n```\r\n\r\nThis will ensure that the port mappings are removed even if an exception occurs during the execution of your code.\r\n\r\n### Troubleshooting uPnP\r\n\r\nIf you encounter issues with uPnP, ensure that:\r\n\r\n- Your router **supports** uPnP and has it **enabled**.\r\n- The `upnpclient` library is installed. You can install it using:\r\n\r\n ```sh\r\n pip install upnpclient\r\n ```\r\n\r\n or install the `cryskura` package with the `upnp` extra:\r\n\r\n ```sh\r\n pip install cryskura[upnp]\r\n ```\r\n\r\n- The network interface specified is correct and accessible.\r\n\r\nFor more detailed information on the `uPnPClient` class and its methods, refer to the source code in the `uPnP.py` file.\r\n\r\n## License\r\n\r\nThis project is licensed under the MIT License. See the [LICENSE](https://github.com/HofNature/CryskuraHTTP/blob/main/LICENSE) file for details.\r\n\r\n## Contributing\r\n\r\nContributions are welcome! Please open an issue or submit a pull request.\r\n\r\n## Contact\r\n\r\nFor any questions or suggestions, please open an issue here on [GitHub](https://github.com/HofNature/CryskuraHTTP/issues).\r\n\r\n---\r\n\r\nEnjoy using CryskuraHTTP!\r\n# CryskuraHTTP\r\n\r\n<div align=\"center\">\r\n <img src=\"https://github.com/HofNature/CryskuraHTTP/raw/main/CryskuraHTTP.png\" alt=\"CryskuraHTTP Logo\" width=\"500\">\r\n\r\n\r\n\r\nCryskuraHTTP \u662f\u4e00\u4e2a\u7528 Python \u5b9e\u73b0\u7684\u8f7b\u91cf\u7ea7\u3001\u53ef\u5b9a\u5236\u7684 HTTP(s) \u670d\u52a1\u5668\uff0c\u652f\u6301\u57fa\u672c\u7684 HTTP(s) \u529f\u80fd\uff0c\u5305\u62ec\u6587\u4ef6\u670d\u52a1\u548c\u9519\u8bef\u5904\u7406\uff0c\u5e76\u652f\u6301\u81ea\u5b9a\u4e49\u670d\u52a1\u548c\u9274\u6743\u3002\r\n\r\n</div>\r\n\r\n## \u7279\u6027\r\n\r\nCryskuraHTTP \u662f Python \u5185\u7f6e `http.server` \u7684\u6269\u5c55\uff0c\u5177\u6709\u5f88\u5c11\u7684\u4f9d\u8d56\u3002\u60a8\u53ef\u4ee5\u5229\u7528\u5b83\u5b9e\u73b0 Python HTTP \u670d\u52a1\uff0c\u800c\u65e0\u9700\u5b89\u88c5\u5927\u578b\u8f6f\u4ef6\u6216\u5e93\u3002\u5b83\u8fd8\u53ef\u4ee5\u7528\u4f5c\u6587\u4ef6\u5171\u4eab\u5de5\u5177\uff0c\u652f\u6301\u901a\u8fc7\u6d4f\u89c8\u5668\u8fdb\u884c\u6587\u4ef6\u4e0b\u8f7d\u548c\u4e0a\u4f20\uff0c\u5e76\u53ef\u901a\u8fc7 Windows \u53f3\u952e\u83dc\u5355\u542f\u52a8\u3002\r\n\r\n- **\u53ef\u5b9a\u5236\u670d\u52a1**\uff1a\u901a\u8fc7\u6269\u5c55 `BaseService` \u7c7b\u8f7b\u677e\u6dfb\u52a0\u81ea\u5b9a\u4e49\u670d\u52a1\u3002\r\n- **\u53ef\u5b9a\u5236 API \u8c03\u7528**\uff1a\u4f7f\u7528 `APIService` \u7c7b\u5b9a\u4e49\u81ea\u5b9a\u4e49 API \u8c03\u7528\u3002\r\n- **\u9519\u8bef\u5904\u7406**\uff1a\u901a\u8fc7 `ErrorService` \u7c7b\u5b9e\u73b0\u53ef\u5b9a\u5236\u7684\u9519\u8bef\u5904\u7406\u3002\r\n- **\u6587\u4ef6\u670d\u52a1**\uff1a\u901a\u8fc7 `FileService` \u7c7b\u4ece\u6307\u5b9a\u76ee\u5f55\u63d0\u4f9b\u6587\u4ef6\u670d\u52a1\u3002\r\n- **\u6587\u4ef6\u4e0a\u4f20**\uff1a\u901a\u8fc7 `FileService` \u7c7b\u5904\u7406\u901a\u8fc7 POST \u8bf7\u6c42\u7684\u6587\u4ef6\u4e0a\u4f20\u3002\r\n- **\u7f51\u9875\u670d\u52a1**\uff1a\u901a\u8fc7 `PageService` \u7c7b\u63d0\u4f9b\u7f51\u9875\u670d\u52a1\uff0c\u800c\u4e0d\u5141\u8bb8\u7528\u6237\u67e5\u770b\u76ee\u5f55\u5217\u8868\u3002\r\n- **\u53ef\u5b9a\u5236\u8def\u7531**\uff1a\u4f7f\u7528 `Route` \u7c7b\u4e3a\u60a8\u7684\u670d\u52a1\u5b9a\u4e49\u81ea\u5b9a\u4e49\u8def\u7531\u3002\r\n- **\u53ef\u5b9a\u5236\u8eab\u4efd\u9a8c\u8bc1**\uff1a\u4e3a\u60a8\u7684\u670d\u52a1\u5b9e\u73b0\u81ea\u5b9a\u4e49\u8eab\u4efd\u9a8c\u8bc1\u3002\r\n- **\u81ea\u52a8 uPnP \u7aef\u53e3\u8f6c\u53d1**\uff1a\u4f7f\u7528 uPnP \u81ea\u52a8\u8f6c\u53d1\u7aef\u53e3\u3002\r\n- **\u8bf7\u6c42\u5904\u7406**\uff1a\u5904\u7406 GET\u3001POST\u3001HEAD \u8bf7\u6c42\u3002\r\n- **\u53ef\u7eed\u4f20\u4e0b\u8f7d**\uff1a\u5728\u63d0\u4f9b\u6587\u4ef6\u670d\u52a1\u65f6\u652f\u6301\u5927\u6587\u4ef6\u7684\u53ef\u7eed\u4f20\u4e0b\u8f7d\u3002\r\n- **\u91cd\u5b9a\u5411**\uff1a\u652f\u6301 301 \u548c 308 \u91cd\u5b9a\u5411\u3002\r\n- **SSL \u652f\u6301**\uff1a\u901a\u8fc7\u63d0\u4f9b\u8bc1\u4e66\u6587\u4ef6\u53ef\u9009\u542f\u7528 SSL\u3002\r\n- **\u591a\u7ebf\u7a0b\u670d\u52a1\u5668**\uff1a\u652f\u6301\u591a\u7ebf\u7a0b\u8bf7\u6c42\u5904\u7406\u4ee5\u63d0\u9ad8\u6027\u80fd\u3002\r\n- **\u547d\u4ee4\u884c\u754c\u9762**\uff1a\u901a\u8fc7\u547d\u4ee4\u884c\u8fd0\u884c\u670d\u52a1\u5668\u5e76\u8fdb\u884c\u81ea\u5b9a\u4e49\u8bbe\u7f6e\u3002\r\n- **\u53f3\u952e\u652f\u6301**\uff1a\u652f\u6301\u5728 Windows \u4e0a\u901a\u8fc7\u53f3\u952e\u83dc\u5355\u542f\u52a8\u670d\u52a1\u5668\u3002\r\n\r\n\u8be5\u9879\u76ee\u5e76\u975e\u8bbe\u8ba1\u7528\u4e8e\u66ff\u4ee3\u5168\u89c4\u6a21\u3001\u751f\u4ea7\u7ea7 HTTP \u670d\u52a1\u5668\u3002\u5b83\u66f4\u9002\u5408\u5c0f\u89c4\u6a21\u7684 Web UI \u5f00\u53d1\u6216\u4e0e `pywebview` \u548c `qtwebengine` \u7b49\u5de5\u5177\u4e00\u8d77\u4f7f\u7528\u3002\u56e0\u6b64\uff0c\u4e0d\u8981\u671f\u671b\u5b83\u80fd\u5904\u7406\u6570\u5343\u4e2a\u5e76\u53d1\u8fde\u63a5\u6216\u5177\u6709\u8d1f\u8f7d\u5747\u8861\u6216\u7f13\u5b58\u7b49\u9ad8\u7ea7\u529f\u80fd\u3002\r\n\r\n## \u8981\u6c42\r\n\r\n- Python 3.x\r\n- `psutil` \u5e93\r\n\r\n## \u5b89\u88c5\r\n\r\n1. \u4f7f\u7528 pip \u5b89\u88c5\u5305\uff1a\r\n\r\n ```sh\r\n pip install cryskura\r\n ```\r\n\r\n2. \u60a8\u4e5f\u53ef\u4ee5\u4ece [GitHub Releases](https://github.com/HofNature/CryskuraHTTP/releases) \u4e0b\u8f7d whl \u6587\u4ef6\u5e76\u4f7f\u7528 pip \u5b89\u88c5\uff1a\r\n\r\n ```sh\r\n pip install cryskura-1.0-py3-none-any.whl\r\n ```\r\n\r\n3. \u5982\u679c\u60a8\u60f3\u4fee\u6539\u6e90\u4ee3\u7801\uff0c\u53ef\u4ee5\u514b\u9686\u4ed3\u5e93\u5e76\u624b\u52a8\u5b89\u88c5\uff1a\r\n\r\n ```sh\r\n git clone https://github.com/HofNature/CryskuraHTTP.git\r\n cd CryskuraHTTP\r\n python setup.py install\r\n ```\r\n\r\n## \u5feb\u901f\u5f00\u59cb\r\n\r\n### \u542f\u52a8\u670d\u52a1\u5668\r\n\r\n\u4f7f\u7528\u9ed8\u8ba4\u8bbe\u7f6e\u542f\u52a8\u670d\u52a1\u5668\uff1a\r\n\r\n```python\r\nfrom cryskura import Server\r\nserver = HTTPServer(interface=\"127.0.0.1\", port=8080)\r\nserver.start()\r\n```\r\n\r\n\u8fd9\u5c06\u5728 `localhost` \u4e0a\u7684\u7aef\u53e3 `8080` \u542f\u52a8\u670d\u52a1\u5668\uff0c\u5e76\u4ece\u5f53\u524d\u76ee\u5f55\u63d0\u4f9b\u6587\u4ef6\u670d\u52a1\u3002\r\n\r\n\u6216\u8005\uff0c\u60a8\u53ef\u4ee5\u4ece\u547d\u4ee4\u884c\u8fd0\u884c\u670d\u52a1\u5668\uff1a\r\n\r\n```sh\r\ncryskura --interface 127.0.0.1 --port 8080 --path /path/to/serve\r\n```\r\n\r\n\u8fd9\u5c06\u5728 `localhost` \u4e0a\u7684\u7aef\u53e3 `8080` \u542f\u52a8\u670d\u52a1\u5668\uff0c\u5e76\u4ece `/path/to/serve` \u63d0\u4f9b\u6587\u4ef6\u670d\u52a1\u3002\r\n\r\n### \u6ce8\u518c\u5230\u53f3\u952e\u83dc\u5355\r\n\r\n\u60a8\u53ef\u4ee5\u901a\u8fc7\u8fd0\u884c\u4ee5\u4e0b\u547d\u4ee4\u5c06\u670d\u52a1\u5668\u6dfb\u52a0\u5230 Windows \u7684\u53f3\u952e\u83dc\u5355\uff1a\r\n\r\n```sh\r\ncryskura --addRightClick # \u60a8\u4e5f\u53ef\u4ee5\u4f7f\u7528 -ar \u4f5c\u4e3a\u7b80\u5199\r\n```\r\n\r\n> **\u6ce8\u610f**\uff1a\u5982\u679c\u63d0\u4f9b\u4e86 `--interface`\u3001`--port`\u3001`--browser` \u7b49\u53c2\u6570\uff0c\u5f53\u4ece\u53f3\u952e\u83dc\u5355\u542f\u52a8\u670d\u52a1\u5668\u65f6\uff0c\u5c06\u4f7f\u7528\u6307\u5b9a\u7684\u8bbe\u7f6e\u3002\r\n\r\n\u5982\u679c\u60a8\u60f3\u4ece\u53f3\u952e\u83dc\u5355\u4e2d\u79fb\u9664\u5b83\uff0c\u8bf7\u8fd0\u884c\uff1a\r\n\r\n```sh\r\ncryskura --removeRightClick # \u60a8\u4e5f\u53ef\u4ee5\u4f7f\u7528 -rr \u4f5c\u4e3a\u7b80\u5199\r\n```\r\n\r\n> **\u6ce8\u610f**\uff1a\u6b64\u529f\u80fd\u4ec5\u5728 Windows \u4e0a\u53ef\u7528\u3002\u5bf9\u4e8e Windows 11 24h2 \u53ca\u4ee5\u4e0a\u7248\u672c\uff0c\u5982\u679c\u542f\u7528\u4e86 Sudo\uff0c\u5b83\u5c06\u81ea\u52a8\u8c03\u7528\uff1b\u5426\u5219\uff0c\u60a8\u9700\u8981\u624b\u52a8\u4ee5\u7ba1\u7406\u5458\u6743\u9650\u8fd0\u884c\u3002\r\n\r\n### \u505c\u6b62\u670d\u52a1\u5668\r\n\r\n\u4f7f\u7528 Python API \u65f6\uff0c\u60a8\u53ef\u4ee5\u901a\u8fc7\u8c03\u7528 `stop()` \u65b9\u6cd5\u505c\u6b62\u670d\u52a1\u5668\uff1a\r\n\r\n```python\r\nserver.stop()\r\n```\r\n\r\n> **\u6ce8\u610f**\uff1a\u53ea\u6709\u591a\u7ebf\u7a0b\u670d\u52a1\u5668\u53ef\u4ee5\u4f7f\u7528\u6b64\u65b9\u6cd5\u505c\u6b62\u3002\u975e\u591a\u7ebf\u7a0b\u670d\u52a1\u5668\u5c06\u963b\u585e\u7ebf\u7a0b\uff0c\u56e0\u6b64\u65e0\u6cd5\u901a\u8fc7\u8c03\u7528 `stop()` \u65b9\u6cd5\u505c\u6b62\u3002\u60a8\u53ef\u4ee5\u901a\u8fc7\u5728\u7ec8\u7aef\u4e2d\u6309 `Ctrl+C` \u505c\u6b62\u975e\u591a\u7ebf\u7a0b\u670d\u52a1\u5668\u3002\r\n\r\n\u4f7f\u7528\u547d\u4ee4\u884c\u65f6\uff0c\u60a8\u53ef\u4ee5\u901a\u8fc7\u5728\u7ec8\u7aef\u4e2d\u6309 `Ctrl+C` \u505c\u6b62\u670d\u52a1\u5668\u3002\r\n\r\n## \u547d\u4ee4\u884c\u754c\u9762\r\n\r\n\u60a8\u53ef\u4ee5\u901a\u8fc7\u8fd0\u884c\u4ee5\u4e0b\u547d\u4ee4\u83b7\u53d6\u547d\u4ee4\u884c\u754c\u9762\u7684\u5e2e\u52a9\uff1a\r\n\r\n```sh\r\ncryskura --help\r\n```\r\n\r\n\u8fd9\u5c06\u663e\u793a\u53ef\u7528\u9009\u9879\uff1a\r\n\r\n- `-h, --help`\uff1a\u663e\u793a\u5e2e\u52a9\u4fe1\u606f\u5e76\u9000\u51fa\u3002\r\n- `-u, --uPnP`\uff1a\u542f\u7528 uPnP \u7aef\u53e3\u8f6c\u53d1\u3002\r\n- `-v, --version`\uff1a\u663e\u793a\u7a0b\u5e8f\u7684\u7248\u672c\u53f7\u5e76\u9000\u51fa\u3002\r\n- `-b, --browser`\uff1a\u542f\u52a8\u670d\u52a1\u5668\u540e\u6253\u5f00\u6d4f\u89c8\u5668\u3002\r\n- `-ba, --browserAddress`\uff1a\u6d4f\u89c8\u5668\u6253\u5f00\u7684\u5730\u5740\u3002\r\n- `-w, --webMode`\uff1a\u542f\u7528 Web \u6a21\u5f0f\uff0c\u8fd9\u610f\u5473\u7740\u53ea\u80fd\u8bbf\u95ee\u6587\u4ef6\uff0c\u4e0d\u80fd\u8bbf\u95ee\u76ee\u5f55\u3002\r\n- `-f, --forcePort`\uff1a\u5f3a\u5236\u4f7f\u7528\u6307\u5b9a\u7aef\u53e3\uff0c\u5373\u4f7f\u8be5\u7aef\u53e3\u5df2\u88ab\u5360\u7528\u3002\r\n- `-t, --allowUpload`\uff1a\u5141\u8bb8\u6587\u4ef6\u4e0a\u4f20\u3002\r\n- `-r, --allowResume`\uff1a\u5141\u8bb8\u7eed\u4f20\u4e0b\u8f7d\u3002\r\n- `-ar, --addRightClick`\uff1a\u6dfb\u52a0\u5230\u53f3\u952e\u83dc\u5355\u3002\r\n- `-rr, --removeRightClick`\uff1a\u4ece\u53f3\u952e\u83dc\u5355\u4e2d\u79fb\u9664\u3002\r\n- `-d PATH, --path PATH`\uff1a\u8981\u63d0\u4f9b\u670d\u52a1\u7684\u76ee\u5f55\u8def\u5f84\u3002\r\n- `-n NAME, --name NAME`\uff1a\u670d\u52a1\u5668\u7684\u540d\u79f0\u3002\r\n- `-p PORT, --port PORT`\uff1a\u76d1\u542c\u7684\u7aef\u53e3\u3002\r\n- `-c CERTFILE, --certfile CERTFILE`\uff1a\u8bc1\u4e66\u6587\u4ef6\u7684\u8def\u5f84\u3002\r\n- `-i INTERFACE, --interface INTERFACE`\uff1a\u76d1\u542c\u7684\u63a5\u53e3\u3002\r\n- `-j HTTP_TO_HTTPS, --http_to_https HTTP_TO_HTTPS`\uff1a\u5c06 HTTP \u8bf7\u6c42\u91cd\u5b9a\u5411\u5230 HTTPS \u7684\u7aef\u53e3\u3002\r\n\r\n## \u4f5c\u4e3a Python \u6a21\u5757\u4f7f\u7528\r\n\r\n### \u81ea\u5b9a\u4e49\u914d\u7f6e\r\n\r\n\u60a8\u53ef\u4ee5\u901a\u8fc7\u63d0\u4f9b\u4e0d\u540c\u7684\u53c2\u6570\u6765\u81ea\u5b9a\u4e49\u670d\u52a1\u5668\uff1a\r\n\r\n```python\r\nfrom cryskura import Server\r\nfrom cryskura.Services import FileService, PageService, RedirectService, APIService\r\n\r\n# \u521b\u5efa\u670d\u52a1\r\nfs = FileService(r\"/path/to/file\", \"/Files\", allowResume=True, allowUpload=True)\r\nrs = RedirectService(\"/Redirect\", \"https://www.google.com\")\r\nps = PageService(r\"/path/to/html\", \"/\")\r\n\r\n# \u5b9a\u4e49 API \u51fd\u6570\r\ndef APIFunc(request, path, args, headers, content, method):\r\n \"\"\"\r\n \u7528\u4e8e\u5904\u7406 API \u8bf7\u6c42\u7684\u793a\u4f8b\u51fd\u6570\u3002\r\n\r\n \u53c2\u6570\uff1a\r\n - request\uff1aHTTP \u8bf7\u6c42\u5bf9\u8c61\u3002\r\n - path\uff1aAPI \u7aef\u70b9\u4e4b\u540e\u7684\u8bf7\u6c42 URL \u5b50\u8def\u5f84\u3002\r\n - args\uff1aURL \u4e2d\u7684\u67e5\u8be2\u53c2\u6570\uff0c\u5b57\u5178\u5f62\u5f0f\u3002\r\n - headers\uff1a\u8bf7\u6c42\u5934\uff0c\u5b57\u5178\u5f62\u5f0f\u3002\r\n - content\uff1a\u8bf7\u6c42\u7684\u4e3b\u4f53\u5185\u5bb9\uff0c\u5b57\u8282\u7c7b\u578b\u3002\r\n - method\uff1a\u4f7f\u7528\u7684 HTTP \u65b9\u6cd5\uff08\u4f8b\u5982 \"GET\"\u3001\"POST\"\uff09\u3002\r\n\r\n \u8fd4\u56de\uff1a\r\n - code\uff1a\u6574\u6570\u7c7b\u578b\u7684 HTTP \u72b6\u6001\u7801\uff08\u4f8b\u5982 200 \u8868\u793a\u6210\u529f\uff09\u3002\r\n - response_headers\uff1a\u8981\u5305\u542b\u5728\u54cd\u5e94\u4e2d\u7684\u5934\u4fe1\u606f\uff0c\u5b57\u5178\u5f62\u5f0f\u3002\r\n - response_content\uff1a\u54cd\u5e94\u7684\u4e3b\u4f53\u5185\u5bb9\uff0c\u5b57\u8282\u7c7b\u578b\u3002\r\n\r\n \"\"\"\r\n # \u4e3a\u6f14\u793a\u76ee\u7684\uff0c\u6211\u4eec\u5c06\u7b80\u5355\u8fd4\u56de\u4e00\u4e2a 200 OK \u72b6\u6001\u548c\u4e00\u4e2a\u7eaf\u6587\u672c\u6d88\u606f\u3002\r\n code = 200\r\n response_headers = {\"Content-Type\": \"text/plain\"}\r\n response_content = b\"API \u8c03\u7528\"\r\n\r\n return code, response_headers, response_content\r\n\r\n# \u521b\u5efa API \u670d\u52a1\r\napi = APIService(\"/API\", func=APIFunc)\r\n\r\n# \u542f\u52a8\u670d\u52a1\u5668\r\nserver = Server(services=[fs, rs, api, ps], certfile=\"/path/to/cert.pem\", uPnP=True)\r\nserver.start()\r\n```\r\n\r\n\u8fd9\u5c06\u542f\u52a8\u5177\u6709\u4ee5\u4e0b\u670d\u52a1\u7684\u670d\u52a1\u5668\uff1a\r\n\r\n- FileService\uff1a\u5728 `/Files` \u7aef\u70b9\u63d0\u4f9b `/path/to/file` \u7684\u6587\u4ef6\u670d\u52a1\uff0c\u5141\u8bb8\u7eed\u4f20\u4e0b\u8f7d\u548c\u6587\u4ef6\u4e0a\u4f20\u3002\r\n- RedirectService\uff1a\u5c06 `/Redirect` \u7684\u8bf7\u6c42\u91cd\u5b9a\u5411\u5230 `https://www.google.com`\u3002\r\n- PageService\uff1a\u5728\u6839\u7aef\u70b9 `/` \u63d0\u4f9b `/path/to/html` \u7684\u7f51\u9875\u670d\u52a1\u3002\r\n- APIService\uff1a\u5728 `/API` \u7aef\u70b9\u5904\u7406 API \u8c03\u7528\uff0c\u6253\u5370\u8bf7\u6c42\u8be6\u60c5\u5e76\u54cd\u5e94\u7eaf\u6587\u672c\u6d88\u606f\u3002\r\n\r\n\u4ee5\u53ca\u4ee5\u4e0b\u8bbe\u7f6e\uff1a\r\n\r\n- SSL \u652f\u6301\uff1a\u4f7f\u7528\u4f4d\u4e8e `/path/to/cert.pem` \u7684\u8bc1\u4e66\u6587\u4ef6\u8fdb\u884c SSL \u52a0\u5bc6\u3002\r\n- uPnP \u7aef\u53e3\u8f6c\u53d1\uff1a\u4f7f\u7528 uPnP \u81ea\u52a8\u8f6c\u53d1\u7aef\u53e3\u3002\r\n\r\n### \u8def\u7531\u4f18\u5148\u7ea7\r\n\r\n\u5982\u679c\u591a\u4e2a\u670d\u52a1\u6709\u51b2\u7a81\u7684\u8def\u7531\uff0c\u4f18\u5148\u7ea7\u7531 `services` \u53c2\u6570\u4e2d\u670d\u52a1\u7684\u987a\u5e8f\u51b3\u5b9a\u3002\u5217\u5728\u524d\u9762\u7684\u670d\u52a1\u4f18\u5148\u7ea7\u6700\u9ad8\uff0c\u4f9d\u6b64\u7c7b\u63a8\u3002\r\n\r\n\u4f8b\u5982\uff1a\r\n\r\n```python\r\nfrom cryskura import Server\r\nfrom cryskura.Services import FileService, PageService\r\n\r\nfs = FileService(r\"/path/to/files\", \"/files\")\r\nps = PageService(r\"/path/to/pages\", \"/\")\r\n\r\nserver = Server(services=[fs, ps])\r\nserver.start()\r\n```\r\n\r\n\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u5bf9\u4e8e `FileService` \u548c `PageService` \u4e4b\u95f4\u51b2\u7a81\u7684\u8def\u7531\uff0c`FileService` \u5c06\u4f18\u5148\u5904\u7406\u3002\u56e0\u6b64\uff0c\u5982\u679c\u8bf7\u6c42 `/files/index.html`\uff0c\u5c06\u7531 `FileService` \u5904\u7406\uff0c\u800c\u4e0d\u662f `PageService`\u3002\r\n\r\n### \u8eab\u4efd\u9a8c\u8bc1\r\n\r\n\u8981\u5b9e\u73b0\u81ea\u5b9a\u4e49\u8eab\u4efd\u9a8c\u8bc1\uff0c\u60a8\u9700\u8981\u5b9a\u4e49\u4e00\u4e2a\u8eab\u4efd\u9a8c\u8bc1\u51fd\u6570\u5e76\u5c06\u5176\u4f20\u9012\u7ed9\u9700\u8981\u8eab\u4efd\u9a8c\u8bc1\u7684\u670d\u52a1\u3002\u8eab\u4efd\u9a8c\u8bc1\u51fd\u6570\u5e94\u63a5\u53d7\u56db\u4e2a\u53c2\u6570\uff1a`cookies`\u3001`path`\u3001`args` \u548c `operation`\u3002\u5982\u679c\u8eab\u4efd\u9a8c\u8bc1\u6210\u529f\uff0c\u5e94\u8fd4\u56de `True`\uff0c\u5426\u5219\u8fd4\u56de `False`\u3002\r\n\r\n\u4ee5\u4e0b\u662f\u5982\u4f55\u5b9e\u73b0\u81ea\u5b9a\u4e49\u8eab\u4efd\u9a8c\u8bc1\u7684\u793a\u4f8b\uff1a\r\n\r\n```python\r\nfrom cryskura import Server\r\nfrom cryskura.Services import FileService\r\n\r\n# \u5b9a\u4e49\u8eab\u4efd\u9a8c\u8bc1\u51fd\u6570\r\ndef AUTHFunc(cookies, path, args, operation):\r\n print(f\"AUTH {operation} {path} {args}\")\r\n if args.get('passwd') == \"passwd\" and operation == \"GET\":\r\n return True\r\n elif args.get('passwd') == \"admin\" and operation == \"POST\":\r\n return True\r\n return False\r\n\r\n# \u521b\u5efa\u5e26\u6709\u8eab\u4efd\u9a8c\u8bc1\u7684\u6587\u4ef6\u670d\u52a1\r\nfs = FileService(r\"/path/to/files\", \"/files\", allowResume=True, auth_func=AUTHFunc)\r\n\r\n# \u542f\u52a8\u670d\u52a1\u5668\r\nserver = Server(services=[fs])\r\nserver.start()\r\n```\r\n\r\n\u5728\u6b64\u793a\u4f8b\u4e2d\uff0c`AUTHFunc` \u51fd\u6570\u68c0\u67e5\u8bf7\u6c42\u53c2\u6570\u4e2d\u7684 `passwd` \u53c2\u6570\u4ee5\u9a8c\u8bc1 GET \u548c POST \u8bf7\u6c42\u3002\u5982\u679c `passwd` \u53c2\u6570\u4e3a GET \u8bf7\u6c42\u7684 `passwd` \u6216 POST \u8bf7\u6c42\u7684 `admin`\uff0c\u5219\u8eab\u4efd\u9a8c\u8bc1\u6210\u529f\u3002\u5426\u5219\uff0c\u8eab\u4efd\u9a8c\u8bc1\u5931\u8d25\u3002\r\n\r\n\u60a8\u53ef\u4ee5\u81ea\u5b9a\u4e49 `AUTHFunc` \u51fd\u6570\u4ee5\u5b9e\u73b0\u81ea\u5df1\u7684\u8eab\u4efd\u9a8c\u8bc1\u903b\u8f91\uff0c\u4f8b\u5982\u68c0\u67e5 cookies\u3001\u5934\u4fe1\u606f\u6216\u5176\u4ed6\u8bf7\u6c42\u53c2\u6570\u3002\r\n\r\n### \u81ea\u5b9a\u4e49\u670d\u52a1\r\n\r\n\u8981\u521b\u5efa\u81ea\u5b9a\u4e49\u670d\u52a1\uff0c\u8bf7\u6269\u5c55 `BaseService` \u7c7b\u5e76\u5b9e\u73b0\u6240\u9700\u7684\u65b9\u6cd5\uff1a\r\n\r\n```python\r\nfrom cryskura.Services import BaseService, Route\r\n\r\nclass MyService(BaseService):\r\n def __init__(self):\r\n routes = [Route(\"/myservice\", [\"GET\"], \"exact\")]\r\n super().__init__(routes)\r\n\r\n def handle_GET(self, request, path, args):\r\n request.send_response(200)\r\n request.send_header(\"Content-Type\", \"text/plain\")\r\n request.end_headers()\r\n request.wfile.write(b\"Hello from MyService!\")\r\n```\r\n\r\n## \u4f7f\u7528 uPnP \u5ba2\u6237\u7aef\r\n\r\nCryskuraHTTP \u5305\u542b\u4e00\u4e2a\u5185\u7f6e\u7684 uPnP \u5ba2\u6237\u7aef\uff0c\u4ee5\u4fbf\u81ea\u52a8\u7aef\u53e3\u8f6c\u53d1\u3002\u8fd9\u5728\u8def\u7531\u5668\u6216\u9632\u706b\u5899\u540e\u8fd0\u884c\u670d\u52a1\u5668\u65f6\u7279\u522b\u6709\u7528\u3002\r\n\r\n### \u542f\u7528 uPnP\r\n\r\n\u8981\u542f\u7528 uPnP \u7aef\u53e3\u8f6c\u53d1\uff0c\u60a8\u53ef\u4ee5\u5728\u4ece\u547d\u4ee4\u884c\u542f\u52a8\u670d\u52a1\u5668\u65f6\u4f7f\u7528 `--uPnP` \u6807\u5fd7\uff1a\r\n\r\n```sh\r\ncryskura --interface 0.0.0.0 --port 8080 --path /path/to/serve --uPnP\r\n```\r\n\r\n### \u5728 Python \u4e2d\u4f7f\u7528 uPnP\r\n\r\n\u60a8\u8fd8\u53ef\u4ee5\u5728\u4f7f\u7528 Python API \u542f\u52a8\u670d\u52a1\u5668\u65f6\u542f\u7528 uPnP \u7aef\u53e3\u8f6c\u53d1\uff1a\r\n\r\n```python\r\nfrom cryskura import Server\r\n\r\nserver = Server(interface=\"0.0.0.0\", port=8080, uPnP=True)\r\nserver.start()\r\n```\r\n\r\n### \u81ea\u5b9a\u4e49 uPnP \u914d\u7f6e\r\n\r\n\u5185\u7f6e\u7684 uPnP \u5ba2\u6237\u7aef\u53ef\u4ee5\u72ec\u7acb\u4f7f\u7528\u4ee5\u6ee1\u8db3\u81ea\u5b9a\u4e49\u7aef\u53e3\u8f6c\u53d1\u9700\u6c42\u3002\u4ee5\u4e0b\u662f\u5982\u4f55\u5728 Python \u4ee3\u7801\u4e2d\u76f4\u63a5\u4f7f\u7528 `uPnPClient` \u7c7b\uff1a\r\n\r\n#### \u521d\u59cb\u5316 uPnP \u5ba2\u6237\u7aef\r\n\r\n\u9996\u5148\uff0c\u60a8\u9700\u8981\u4f7f\u7528\u6240\u9700\u7684\u7f51\u7edc\u63a5\u53e3\u521d\u59cb\u5316 `uPnPClient`\uff1a\r\n\r\n```python\r\nfrom cryskura import uPnP\r\n\r\n# \u4e3a\u7279\u5b9a\u63a5\u53e3\u521d\u59cb\u5316 uPnP \u5ba2\u6237\u7aef\r\nupnp_client = uPnP(interface=\"0.0.0.0\")\r\n# \u4f7f\u7528 0.0.0.0 \u8868\u793a\u6240\u6709 IPv4 \u63a5\u53e3\r\n\r\nif upnp_client.available:\r\n print(\"uPnP \u5ba2\u6237\u7aef\u521d\u59cb\u5316\u6210\u529f\u3002\")\r\nelse:\r\n print(\"uPnP \u5ba2\u6237\u7aef\u4e0d\u53ef\u7528\u3002\")\r\n```\r\n\r\n#### \u6dfb\u52a0\u7aef\u53e3\u6620\u5c04\r\n\r\n\u8981\u6dfb\u52a0\u7aef\u53e3\u6620\u5c04\uff0c\u8bf7\u4f7f\u7528 `add_port_mapping` \u65b9\u6cd5\uff1a\r\n\r\n```python\r\nif upnp_client.available:\r\n success, mappings = upnp_client.add_port_mapping(\r\n remote_port=8080, \r\n description=\"CryskuraHTTP Server\"\r\n )\r\n if success:\r\n print(\"\u7aef\u53e3\u6620\u5c04\u6dfb\u52a0\u6210\u529f\u3002\")\r\n else:\r\n print(\"\u6dfb\u52a0\u7aef\u53e3\u6620\u5c04\u5931\u8d25\u3002\")\r\n```\r\n\r\n\u8fd9\u5c06\u5728\u8fdc\u7a0b\u8bbe\u5907\u7684\u7aef\u53e3 `8080` \u4e0a\u6dfb\u52a0\u5230\u672c\u5730\u8bbe\u5907\u7aef\u53e3 `8080` \u7684\u7aef\u53e3\u6620\u5c04\uff0c\u4f7f\u7528 TCP \u534f\u8bae\u3002\u63cf\u8ff0\u53ea\u662f\u6620\u5c04\u7684\u6807\u7b7e\uff0c\u53ef\u4ee5\u7528\u4e8e\u4ee5\u540e\u8bc6\u522b\u5b83\u3002\r\n\r\n#### \u79fb\u9664\u6240\u6709\u7aef\u53e3\u6620\u5c04\r\n\r\n\u8981\u79fb\u9664\u7aef\u53e3\u6620\u5c04\uff0c\u8bf7\u4f7f\u7528 `remove_port_mapping` \u65b9\u6cd5\uff1a\r\n\r\n```python\r\nif upnp_client.available:\r\n upnp_client.remove_port_mapping()\r\n print(\"\u7aef\u53e3\u6620\u5c04\u5df2\u79fb\u9664\u3002\")\r\n```\r\n\r\n\u8fd9\u5c06\u79fb\u9664\u5ba2\u6237\u7aef\u6dfb\u52a0\u7684\u6240\u6709\u7aef\u53e3\u6620\u5c04\u3002\u6700\u597d\u5728\u4e0d\u518d\u9700\u8981\u65f6\u79fb\u9664\u7aef\u53e3\u6620\u5c04\u3002\u60a8\u53ef\u4ee5\u5c06\u6b64\u4ee3\u7801\u653e\u5728\u811a\u672c\u7684\u6e05\u7406\u90e8\u5206\u6216\u5f02\u5e38\u5904\u7406\u7a0b\u5e8f\u4e2d\uff0c\u4ee5\u786e\u4fdd\u5373\u4f7f\u53d1\u751f\u9519\u8bef\u4e5f\u80fd\u79fb\u9664\u6620\u5c04\u3002\u4f8b\u5982\uff1a\r\n\r\n```python\r\ntry:\r\n # \u60a8\u7684\u4ee3\u7801...\r\nexcept Exception as exception:\r\n upnp_client.remove_port_mapping()\r\n raise exception\r\n```\r\n\r\n\u8fd9\u5c06\u786e\u4fdd\u5373\u4f7f\u5728\u4ee3\u7801\u6267\u884c\u671f\u95f4\u53d1\u751f\u5f02\u5e38\uff0c\u4e5f\u80fd\u79fb\u9664\u7aef\u53e3\u6620\u5c04\u3002\r\n\r\n### uPnP \u6545\u969c\u6392\u9664\r\n\r\n\u5982\u679c\u9047\u5230 uPnP \u95ee\u9898\uff0c\u8bf7\u786e\u4fdd\uff1a\r\n\r\n- \u60a8\u7684\u8def\u7531\u5668 **\u652f\u6301** uPnP \u5e76\u4e14\u5df2 **\u542f\u7528**\u3002\r\n- \u5b89\u88c5\u4e86 `upnpclient` \u5e93\u3002\u60a8\u53ef\u4ee5\u4f7f\u7528\u4ee5\u4e0b\u547d\u4ee4\u5b89\u88c5\u5b83\uff1a\r\n\r\n ```sh\r\n pip install upnpclient\r\n ```\r\n\r\n- \u6307\u5b9a\u7684\u7f51\u7edc\u63a5\u53e3\u662f\u6b63\u786e\u4e14\u53ef\u8bbf\u95ee\u7684\u3002\r\n\r\n\u6709\u5173 `uPnPClient` \u7c7b\u53ca\u5176\u65b9\u6cd5\u7684\u8be6\u7ec6\u4fe1\u606f\uff0c\u8bf7\u53c2\u9605 `uPnP.py` \u6587\u4ef6\u4e2d\u7684\u6e90\u4ee3\u7801\u3002\r\n\r\n## \u8bb8\u53ef\u8bc1\r\n\r\n\u672c\u9879\u76ee\u91c7\u7528 MIT \u8bb8\u53ef\u8bc1\u3002\u6709\u5173\u8be6\u7ec6\u4fe1\u606f\uff0c\u8bf7\u53c2\u9605 [LICENSE](https://github.com/HofNature/CryskuraHTTP/blob/main/LICENSE) \u6587\u4ef6\u3002\r\n\r\n## \u8d21\u732e\r\n\r\n\u6b22\u8fce\u8d21\u732e\uff01\u8bf7\u63d0\u4ea4\u95ee\u9898\u6216\u62c9\u53d6\u8bf7\u6c42\u3002\r\n\r\n## \u8054\u7cfb\u65b9\u5f0f\r\n\r\n\u5982\u6709\u4efb\u4f55\u95ee\u9898\u6216\u5efa\u8bae\uff0c\u8bf7\u5728 [GitHub](https://github.com/HofNature/CryskuraHTTP/issues) \u4e0a\u63d0\u4ea4\u95ee\u9898\u3002\r\n\r\n---\r\n\r\n\u4eab\u53d7\u4f7f\u7528 CryskuraHTTP \u5427\uff01\r\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A straightforward Python package that functions as an HTTP(s) server",
"version": "1.0b6",
"project_urls": {
"Homepage": "https://github.com/HofNature/CryskuraHTTP"
},
"split_keywords": [
"http",
" https",
" server",
" web",
" http server",
" https server"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "5ec9ca9b3d4309a84482949255c37296c31dc1678a63c633d1fe0343826f360e",
"md5": "6ad0c4ae76b1f2a6a3246b20bbb89478",
"sha256": "4b3949350f2edc7ffd1c7fe3c67901c727ede66b2aa65d418adf153a66e6341f"
},
"downloads": -1,
"filename": "cryskura-1.0b6-py3-none-any.whl",
"has_sig": false,
"md5_digest": "6ad0c4ae76b1f2a6a3246b20bbb89478",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 167036,
"upload_time": "2024-12-15T16:48:55",
"upload_time_iso_8601": "2024-12-15T16:48:55.309017Z",
"url": "https://files.pythonhosted.org/packages/5e/c9/ca9b3d4309a84482949255c37296c31dc1678a63c633d1fe0343826f360e/cryskura-1.0b6-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "3dece44a76492d786f813b113828806bf97d394ebeeb88bba74079780e12a827",
"md5": "d7ac6d65542ba765fa6750beeb7d8f8d",
"sha256": "cbc92bc70f0ef76db7630be3c503fa209fcbdb26f2a85aa32d9ac7fc5a2e6b90"
},
"downloads": -1,
"filename": "cryskura-1.0b6.tar.gz",
"has_sig": false,
"md5_digest": "d7ac6d65542ba765fa6750beeb7d8f8d",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 172702,
"upload_time": "2024-12-15T16:48:58",
"upload_time_iso_8601": "2024-12-15T16:48:58.020465Z",
"url": "https://files.pythonhosted.org/packages/3d/ec/e44a76492d786f813b113828806bf97d394ebeeb88bba74079780e12a827/cryskura-1.0b6.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-12-15 16:48:58",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "HofNature",
"github_project": "CryskuraHTTP",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "cryskura"
}