Parsing $_SERVER['PATH_INFO']

本文探讨了如何通过解析PHP全局变量$_SERVER['PATH_INFO']来优化网站的URL结构,使其更加美观且对搜索引擎友好。文章提供了一段示例代码,展示了如何根据不同路径加载相应的页面文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一下转自:http://blog.affien.com/archives/2004/12/12/parsing-_serverpath_info/

The PHP global variable $_SERVER['PATH_INFO'] contains the path suffixed to a PHP script, if I would call the URL:

http://domain.ext/path/to/script.php/foo/bar.htm?a=b&c=d

Then $_SERVER['PATH_INFO'] would contain:

/foo/bar.htm

Traditionaly the $_GET variables are used for certain parameters like a page to display:

http://domain.ext/page.php?page=about.htm

This method is easy to program, but not only looks strange, but also is very search engine unfriendly. Most searchengines ignore the QueryString (the part of the URL after the ?). And therefor would index the first page.php?page=x they would find and ignore the rest.
Some searchengines like Google do not ignore the query string, but would give a page without using a querystring for different content a way higher ranking.

Parsing the $_SERVER['PATH_INFO'] is relatively easy, this code would do most of the stuff just fine:

if (!isset($_SERVER['PATH_INFO'])){
	$pathbits= array('');
}else{
	$pathbits = explode("/",  $_SERVER['PATH_INFO']);
}

The $pathbits array would always contain / as first element if a path info was provided, otherwise it will be an empty array.

Here is a quite simple example which parses the path info to decide which file to include:

<?php
if (!isset($_SERVER['PATH_INFO'])){
	$pathbits= array('');
}else{
	$pathbits = explode("/",  $_SERVER['PATH_INFO']);
}
if (!isset($pathbits[1]) || $pathbits[1] == ""){
	$page = "default"
}else{
	$page = basename($pathbits[1]);
}
$file = "./pages/{$page}.php";
if (!is_file($file)){
	echo "File not found";
}else{
	require $file;
}
?>

#!/usr/bin/env bash set -e # ----------------------------------------------------------------------------- # Usage and command-line argument parsing # ----------------------------------------------------------------------------- function usage() { echo "Usage: $0 [--disable-webserver] [--disable-taskexecutor] [--consumer-no-beg=<num>] [--consumer-no-end=<num>] [--workers=<num>] [--host-id=<string>]" echo echo " --disable-webserver Disables the web server (nginx + ragflow_server)." echo " --disable-taskexecutor Disables task executor workers." echo " --enable-mcpserver Enables the MCP server." echo " --consumer-no-beg=<num> Start range for consumers (if using range-based)." echo " --consumer-no-end=<num> End range for consumers (if using range-based)." echo " --workers=<num> Number of task executors to run (if range is not used)." echo " --host-id=<string> Unique ID for the host (defaults to \`hostname\`)." echo echo "Examples:" echo " $0 --disable-taskexecutor" echo " $0 --disable-webserver --consumer-no-beg=0 --consumer-no-end=5" echo " $0 --disable-webserver --workers=2 --host-id=myhost123" echo " $0 --enable-mcpserver" exit 1 } ENABLE_WEBSERVER=1 # Default to enable web server ENABLE_TASKEXECUTOR=1 # Default to enable task executor ENABLE_MCP_SERVER=0 CONSUMER_NO_BEG=0 CONSUMER_NO_END=0 WORKERS=1 MCP_HOST="127.0.0.1" MCP_PORT=9382 MCP_BASE_URL="http://127.0.0.1:9380" MCP_SCRIPT_PATH="/ragflow/mcp/server/server.py" MCP_MODE="self-host" MCP_HOST_API_KEY="" # ----------------------------------------------------------------------------- # Host ID logic: # 1. By default, use the system hostname if length <= 32 # 2. Otherwise, use the full MD5 hash of the hostname (32 hex chars) # ----------------------------------------------------------------------------- CURRENT_HOSTNAME="$(hostname)" if [ ${#CURRENT_HOSTNAME} -le 32 ]; then DEFAULT_HOST_ID="$CURRENT_HOSTNAME" else DEFAULT_HOST_ID="$(echo -n "$CURRENT_HOSTNAME" | md5sum | cut -d ' ' -f 1)" fi HOST_ID="$DEFAULT_HOST_ID" # Parse arguments for arg in "$@"; do case $arg in --disable-webserver) ENABLE_WEBSERVER=0 shift ;; --disable-taskexecutor) ENABLE_TASKEXECUTOR=0 shift ;; --enable-mcpserver) ENABLE_MCP_SERVER=1 shift ;; --mcp-host=*) MCP_HOST="${arg#*=}" shift ;; --mcp-port=*) MCP_PORT="${arg#*=}" shift ;; --mcp-base-url=*) MCP_BASE_URL="${arg#*=}" shift ;; --mcp-mode=*) MCP_MODE="${arg#*=}" shift ;; --mcp-host-api-key=*) MCP_HOST_API_KEY="${arg#*=}" shift ;; --mcp-script-path=*) MCP_SCRIPT_PATH="${arg#*=}" shift ;; --consumer-no-beg=*) CONSUMER_NO_BEG="${arg#*=}" shift ;; --consumer-no-end=*) CONSUMER_NO_END="${arg#*=}" shift ;; --workers=*) WORKERS="${arg#*=}" shift ;; --host-id=*) HOST_ID="${arg#*=}" shift ;; *) usage ;; esac done # ----------------------------------------------------------------------------- # Replace env variables in the service_conf.yaml file # ----------------------------------------------------------------------------- CONF_DIR="/Users/congcong/programfile/ragflow/conf" TEMPLATE_FILE="${CONF_DIR}/service_conf.yaml.template" CONF_FILE="${CONF_DIR}/service_conf.yaml" rm -f "${CONF_FILE}" while IFS= read -r line || [[ -n "$line" ]]; do eval "echo \"$line\"" >> "${CONF_FILE}" done < "${TEMPLATE_FILE}" export LD_LIBRARY_PATH="/usr/lib/x86_64-linux-gnu/" PY=python3 # ----------------------------------------------------------------------------- # Function(s) # ----------------------------------------------------------------------------- function task_exe() { local consumer_id="$1" local host_id="$2" JEMALLOC_PATH="$(pkg-config --variable=libdir jemalloc)/libjemalloc.so" while true; do LD_PRELOAD="$JEMALLOC_PATH" \ "$PY" rag/svr/task_executor.py "${host_id}_${consumer_id}" done } function start_mcp_server() { echo "Starting MCP Server on ${MCP_HOST}:${MCP_PORT} with base URL ${MCP_BASE_URL}..." "$PY" "${MCP_SCRIPT_PATH}" \ --host="${MCP_HOST}" \ --port="${MCP_PORT}" \ --base_url="${MCP_BASE_URL}" \ --mode="${MCP_MODE}" \ --api_key="${MCP_HOST_API_KEY}" & } # ----------------------------------------------------------------------------- # Start components based on flags # ----------------------------------------------------------------------------- if [[ "${ENABLE_WEBSERVER}" -eq 1 ]]; then echo "Starting nginx..." #/usr/sbin/nginx echo "Starting ragflow_server..." while true; do "$PY" /Users/congcong/programfile/ragflow/api/ragflow_server.py done & fi if [[ "${ENABLE_MCP_SERVER}" -eq 1 ]]; then start_mcp_server fi if [[ "${ENABLE_TASKEXECUTOR}" -eq 1 ]]; then if [[ "${CONSUMER_NO_END}" -gt "${CONSUMER_NO_BEG}" ]]; then echo "Starting task executors on host '${HOST_ID}' for IDs in [${CONSUMER_NO_BEG}, ${CONSUMER_NO_END})..." for (( i=CONSUMER_NO_BEG; i<CONSUMER_NO_END; i++ )) do task_exe "${i}" "${HOST_ID}" & done else # Otherwise, start a fixed number of workers echo "Starting ${WORKERS} task executor(s) on host '${HOST_ID}'..." for (( i=0; i<WORKERS; i++ )) do task_exe "${i}" "${HOST_ID}" & done fi fi wait
06-03
# -*- coding: utf-8 -*- import tkinter as tk from tkinter import ttk, filedialog, messagebox import socket import threading import os from datetime import datetime from tkinter.font import Font # 移除默认端口号定义,因为端口号将由用户输入 BUFFER_SIZE = 8192 # File transfer buffer size class P2PApp: def __init__(self): self.root = tk.Tk() self.root.title("P2P Communication Tool v1.1") self.encoding = 'utf-8' # Unified encoding # Set the font that supports Chinese # self.root.option_add("*Font", "NSimSun 10") self.system_font = Font(family="WenQuanYi Micro Hei", size=10) # 网络参数设置 self.local_ip = self.get_local_ip()#获取并存储本地设备的 IP 地址。 self.server_socket = None#初始化服务器套接字变量。 self.client_connections = [] # 用于存储所有客户端连接 # Multithreading control self.server_running = True # 程序启动即作为服务端运行 self.lock = threading.Lock() # 线程锁 # 创建接收文件的文件夹 self.received_files_folder = "received_files" if not os.path.exists(self.received_files_folder): os.makedirs(self.received_files_folder) # 新增昵称相关 self.nickname = "User" self.create_nickname_widget() # GUI initialization self.create_widgets() # 绑定回车键 self.msg_entry.bind("<Return>", lambda event: self.send_message()) # 启动服务端监听 self.start_server() # 配置消息颜色标签 self.history_text.tag_configure('send', foreground='black') self.history_text.tag_configure('receive', foreground='blue') # 关闭窗口时销毁资源 self.root.protocol("WM_DELETE_WINDOW", self.on_close) def create_nickname_widget(self): nickname_frame = ttk.LabelFrame(self.root, text="Nickname") nickname_frame.grid(row=0, column=0, padx=10, pady=5, sticky="ew") ttk.Label(nickname_frame, text="Nickname:", font=self.system_font).grid(row=0, column=0, sticky="w", padx=5) self.nickname_entry = ttk.Entry(nickname_frame, width=20) self.nickname_entry.insert(0, self.nickname) self.nickname_entry.grid(row=0, column=1, padx=5) self.change_nickname_btn = ttk.Button( nickname_frame, text="Change Nickname", command=self.change_nickname ) self.change_nickname_btn.grid(row=0, column=2, padx=5) def change_nickname(self): new_nickname = self.nickname_entry.get() if new_nickname: self.nickname = new_nickname def create_widgets(self): # IP address area ip_frame = ttk.LabelFrame(self.root, text="Network Configuration") ip_frame.grid(row=1, column=0, padx=10, pady=5, sticky="ew") ttk.Label(ip_frame, text="Local IP:", font=self.system_font).grid(row=0, column=0, sticky="w", padx=5) self.local_ip_label = ttk.Label(ip_frame, text=self.local_ip, width=20) self.local_ip_label.grid(row=0, column=1, padx=5) ttk.Label(ip_frame, text="Target IP:").grid(row=1, column=0, sticky="w", padx=5) self.target_ip_entry = ttk.Entry(ip_frame, width=20) self.target_ip_entry.insert(0, "172.16.118.0") # 设置目标 IP 的初始默认值 self.target_ip_entry.grid(row=1, column=1, padx=5) ttk.Label(ip_frame, text="Target Port:").grid(row=1, column=2, sticky="w", padx=5) self.target_port_entry = ttk.Entry(ip_frame, width=8) self.target_port_entry.insert(0, "12346") # 默认目标端口号 self.target_port_entry.grid(row=1, column=3, padx=5) # 去掉 Connect Client 按钮,换成测试按钮 btn_frame = ttk.Frame(ip_frame) btn_frame.grid(row=0, column=4, rowspan=2, padx=10, sticky="ns") self.test_btn = ttk.Button( btn_frame, text="Test Connection", command=self.test_connection, width=12 ) self.test_btn.grid(row=0, column=0, pady=2) # Message history area history_frame = ttk.LabelFrame(self.root, text="Message History") history_frame.grid(row=2, column=0, padx=10, pady=5, sticky="nsew") self.history_text = tk.Text( history_frame, height=15, state='disabled', wrap=tk.WORD ) scrollbar = ttk.Scrollbar(history_frame, command=self.history_text.yview) self.history_text.configure(yscrollcommand=scrollbar.set) self.history_text.grid(row=0, column=0, sticky="nsew") scrollbar.grid(row=0, column=1, sticky="ns") # Input area input_frame = ttk.LabelFrame(self.root, text="Message Input") input_frame.grid(row=3, column=0, padx=10, pady=5, sticky="ew") self.msg_entry = ttk.Entry(input_frame, width=40) self.msg_entry.grid(row=0, column=0, padx=5) self.send_btn = ttk.Button( input_frame, text="Send Message", command=self.send_message ) self.send_btn.grid(row=0, column=1, padx=2) self.file_btn = ttk.Button( input_frame, text="Send File", command=self.send_file ) self.file_btn.grid(row=0, column=2, padx=2) # Layout configuration self.root.columnconfigure(0, weight=1) self.root.rowconfigure(2, weight=1) def show_connection_status(self): # Example message pop-up window messagebox.showinfo("Connection Status", "Connection established successfully!") def get_local_ip(self): """获取本地设备的 IP 地址""" try: s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect(("8.8.8.8", 80)) # Connect to a public DNS to get the IP ip = s.getsockname()[0] s.close() return ip except Exception as e: messagebox.showerror("Error", f"Failed to get local IP: {str(e)}") return "127.0.0.1" def start_server(self): """启动服务端监听""" max_retries = 10 # 最大重试次数 retry_count = 0 while retry_count < max_retries: try: # 使用默认服务端端口号 local_server_port = 12346 + retry_count self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 设置 SO_REUSEADDR 选项 self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.server_socket.bind((self.local_ip, local_server_port)) self.server_socket.listen(5) server_thread = threading.Thread(target=self.server_listener, daemon=True) server_thread.start() self.update_history(f"Server started on port {local_server_port}", is_send=False) return except OSError as e: if e.errno == 98: # Address already in use retry_count += 1 next_port = 12346 + retry_count self.update_history(f"Port {local_server_port} is already in use. Retrying with port {local_server_port + 1}...") else: messagebox.showerror("Error", f"Failed to start the server: {str(e)}") return messagebox.showerror("Error", "Failed to start the server after multiple retries.") def server_listener(self): """服务器监听循环,持续接受客户端连接""" while self.server_running: try: conn, addr = self.server_socket.accept() # self.update_history(f"Connection from {addr}", is_send=False) self.client_connections.append(conn) # 添加新连接到列表 client_thread = threading.Thread( target=self.handle_connection, args=(conn,), daemon=True ) client_thread.start() except OSError: break # Exception when closing normally def handle_connection(self, conn): """Handle client connections""" with conn: while True: try: data = conn.recv(BUFFER_SIZE) if not data: break self.process_received_data(data, conn.getpeername()) except ConnectionResetError: break except Exception as e: self.update_history(f"Error receiving data: {str(e)}", is_send=False) break # 连接关闭时从列表中移除 if conn in self.client_connections: self.client_connections.remove(conn) def test_connection(self): """测试与目标 IP 地址和端口的连接""" target_ip = self.target_ip_entry.get() try: target_port = int(self.target_port_entry.get()) except ValueError: messagebox.showerror("Error", "Please enter a valid target port number.") return if not target_ip: messagebox.showwarning("Warning", "Please enter the target IP address.") return try: test_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) test_socket.settimeout(2) test_socket.connect((target_ip, target_port)) test_socket.close() messagebox.showinfo("Test result", "The connection is successful!") except Exception as e: messagebox.showerror("Test result", f"The connection fails: {str(e)}") def send_message(self): """Send a text message""" message = self.msg_entry.get() if not message: return target_ip = self.target_ip_entry.get() try: target_port = int(self.target_port_entry.get()) except ValueError: messagebox.showerror("Error", "Please enter a valid target port number.") return if not target_ip: messagebox.showwarning("Warning", "Please enter the target IP address.") return try: # Construct the protocol header header = f"MSG{datetime.now().strftime('%H:%M:%S')}".ljust(12) full_msg = header.encode() + f"{self.nickname}: {message}".encode('utf-8') # 创建新的连接 client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client_socket.connect((target_ip, target_port)) client_socket.sendall(full_msg) client_socket.close() self.update_history(f"{self.nickname}: {message}") self.msg_entry.delete(0, tk.END) # 广播消息给所有连接的客户端,排除自身 with self.lock: connections_to_remove = [] for conn in self.client_connections: try: # 检查是否为自身连接 if conn.getpeername() != (target_ip, target_port): conn.sendall(full_msg) except OSError as e: if e.errno == 32: # Broken pipe connections_to_remove.append(conn) self.update_history(f"Connection to client broken: {conn.getpeername()}", is_send=False) else: self.update_history(f"Error sending message to client: {str(e)}", is_send=False) # 移除断开的连接 for conn in connections_to_remove: if conn in self.client_connections: self.client_connections.remove(conn) except Exception as e: messagebox.showerror("Error", f"Failed to send the message: {str(e)}") def send_file(self): """Send a file""" file_path = filedialog.askopenfilename() if not file_path: return if os.path.isdir(file_path): messagebox.showerror("Error", "Sending folders is not supported.") return target_ip = self.target_ip_entry.get() try: target_port = int(self.target_port_entry.get()) except ValueError: messagebox.showerror("Error", "Please enter a valid target port number.") return if not target_ip: messagebox.showwarning("Warning", "Please enter the target IP address.") return try: filename = os.path.basename(file_path) filesize = os.path.getsize(file_path) # Construct the file header header = f"FILE:{filename}:{filesize}".ljust(12).encode() # 创建新的连接 client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client_socket.connect((target_ip, target_port)) client_socket.send(header) with open(file_path, 'rb') as f: while chunk := f.read(BUFFER_SIZE): client_socket.send(chunk) client_socket.close() self.update_history(f"File sent: {filename}") # 广播文件给所有连接的客户端,排除自身 with self.lock: connections_to_remove = [] for conn in self.client_connections: try: # 检查是否为自身连接 if conn.getpeername() != (target_ip, target_port): conn.send(header) f.seek(0) while chunk := f.read(BUFFER_SIZE): conn.send(chunk) except OSError as e: if e.errno == 32: # Broken pipe connections_to_remove.append(conn) self.update_history(f"Connection to client broken: {conn.getpeername()}", is_send=False) else: self.update_history(f"Error sending file to client: {str(e)}", is_send=False) # 移除断开的连接 for conn in connections_to_remove: if conn in self.client_connections: self.client_connections.remove(conn) except Exception as e: messagebox.showerror("Error", f"Failed to send the file: {str(e)}") def process_received_data(self, data, address): """Process the received data (general method)""" try: # Parse the protocol header header = data[:12].decode().strip() # Assume the header length is 12 bytes content = data[12:] if header.startswith("FILE"): parts = header.split(':') # File transfer protocol if len(parts) == 3: _, filename, filesize = header.split(':') self.save_file(content, filename, int(filesize), address) self.update_history(f"Received file: {filename} from {address}", is_send=False) else: self.update_history(f"Header format error: {header}", is_send=False) else: # Ordinary message message = content.decode('utf-8') self.update_history(f"{message}", is_send=False) except Exception as e: self.update_history(f"Data parsing error: {str(e)}", is_send=False) def save_file(self, data, filename, filesize, address): """Save the received file""" save_path = os.path.join(self.received_files_folder, filename) try: with open(save_path, 'wb') as f: f.write(data) remaining = filesize - len(data) while remaining > 0: data = self.client_socket.recv(BUFFER_SIZE) f.write(data) remaining -= len(data) self.update_history(f"File {filename} from {address} saved successfully.", is_send=False) except Exception as e: self.update_history(f"Error saving file {filename} from {address}: {str(e)}", is_send=False) def update_history(self, content, is_send=True): """Update the message history (thread-safe)""" def _update(): self.history_text.configure(state='normal') timestamp = datetime.now().strftime("[%H:%M:%S] ") tag = 'send' if is_send else 'receive' self.history_text.insert('end', timestamp + content + '\n', tag) self.history_text.configure(state='disabled') self.history_text.see(tk.END) # Update the interface through the main thread self.root.after(0, _update) def on_close(self): """关闭窗口时销毁资源""" self.server_running = False if self.server_socket: try: self.server_socket.close() except OSError: pass for conn in self.client_connections: try: conn.close() except OSError: pass self.root.destroy() def run(self): """Run the main program""" self.root.mainloop() if __name__ == "__main__": app = P2PApp() app.run() 修改代码:目前的代码不能传输照片等文件。修改代码使其能够传输文件除了文件夹。并将接收到的文件保存。在对话框只显示文件名。
05-13
我现在的chat_server.py 内容是这样的# chat_server.py import os import json import threading from datetime import datetime from flask import Flask, request, jsonify, render_template import subprocess app = Flask(__name__, template_folder="templates") # 全局变量存储对话历史(线程安全) conversation_lock = threading.Lock() conversation_history = {} def get_session_history(session_id): """获取或创建会话历史""" with conversation_lock: if session_id not in conversation_history: conversation_history[session_id] = [] return conversation_history[session_id] def build_prompt(history, new_message): """构建包含历史对话的完整提示""" # 拼接历史对话(最多保留5轮对话) context = "" for entry in history[-5:]: context += f"用户: {entry['user']}\n助手: {entry['assistant']}\n" # 添加新消息 context += f"用户: {new_message}\n助手:" return context @app.route("/") def index(): return render_template("index.html") @app.route("/new_session", methods=["POST"]) def new_session(): """创建新会话端点""" session_id = f"session_{datetime.now().timestamp()}" get_session_history(session_id) # 初始化历史记录 return jsonify({"session_id": session_id}) @app.route("/chat", methods=["POST"]) def chat(): """处理聊天请求""" # 获取请求数据 user_input = request.json.get("message") session_id = request.json.get("session_id", "default") # 获取会话历史 history = get_session_history(session_id) # 构建包含上下文的提示 full_prompt = build_prompt(history, user_input) # 调用模型推理 model_path = os.path.join("models", "DeepSeek-R1-Distill-Qwen-7B-Q4_K_M.gguf") process = subprocess.Popen( ["main.exe", "-m", model_path, "-p", full_prompt, "-n", "256"], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, text=True, encoding='utf-8' ) output, _ = process.communicate() model_response = output.strip() # 更新对话历史 history.append({ "user": user_input, "assistant": model_response, "timestamp": datetime.now().isoformat() }) return jsonify({ "response": model_response, "session_id": session_id }) if __name__ == "__main__": app.run(host="127.0.0.1", port=5000) 怎么添加你的流式响应支持(逐字显示效果),或者你根据我现在的chat_server.py内容融合你的内容 在不影响原来的功能的情况下重新写一份chat_server.py
最新发布
07-19
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值