fastcgi get 参数

99ANYc3cd6
预计阅读时长 27 分钟
位置: 首页 参数 正文

在 FastCGI 环境中,GET 参数是作为环境变量的一部分传递给你的应用程序的,你不需要像解析 POST 数据那样去读取标准输入,而是直接从环境变量中读取即可。

fastcgi get 参数
(图片来源网络,侵删)

理解 GET 请求的构成

一个典型的 URL 如下:

http://www.example.com/index.php?name=John&age=30&city=New+York

这个 URL 可以分解为:

  • 请求路径: /index.php
  • 查询字符串: ?name=John&age=30&city=New+York

在 FastCGI 协议中:

fastcgi get 参数
(图片来源网络,侵删)
  • 请求路径 通常会设置在 SCRIPT_NAMEPATH_INFO 等环境变量中。
  • 查询字符串 会完整地放在一个名为 QUERY_STRING 的环境变量中。

关键的环境变量

要获取 GET 参数,你主要需要关注以下几个环境变量:

  • QUERY_STRING: 这是最重要的一个,它包含了 URL 中问号 之后的所有内容,未经 URL 解码
    • 对于上面的 URL,QUERY_STRING 的值就是 "name=John&age=30&city=New+York"
  • REQUEST_METHOD: HTTP 请求方法,"GET", "POST",你可以用它来判断请求类型。
  • CONTENT_TYPE (或 HTTP_CONTENT_TYPE): 如果是 POST 请求,这个变量会告诉你请求体的内容类型(如 application/x-www-form-urlencoded)。
  • CONTENT_LENGTH: 如果是 POST 请求,这个变量会告诉你请求体的长度。

如何获取 GET 参数(分语言示例)

获取 GET 参数的通用步骤是:

  1. 从环境变量 QUERY_STRING 中获取原始的查询字符串。
  2. 将查询字符串按照 & 分割成键值对。
  3. 对每个键值对,按照 分割成键和值。
  4. (重要) 对键和值进行 URL 解码,因为 QUERY_STRING 中的空格是 或 %20,特殊字符是 编码的。

1 C/C++ 示例

在 C/C++ 中,你可以使用 getenv() 函数来读取环境变量,解析过程需要手动完成。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
// 一个简单的 URL 解码函数
void url_decode(char *dst, const char *src) {
    char a, b;
    while (*src) {
        if (*src == '%' && ((a = src[1]) && (b = src[2])) && (isxdigit(a) && isxdigit(b))) {
            if (a >= 'a')
                a -= 'a'-'A';
            if (a >= 'A')
                a -= ('A' - 10);
            else
                a -= '0';
            if (b >= 'a')
                b -= 'a'-'A';
            if (b >= 'A')
                b -= ('A' - 10);
            else
                b -= '0';
            *dst++ = 16 * a + b;
            src += 3;
        } else if (*src == '+') {
            *dst++ = ' ';
            src++;
        } else {
            *dst++ = *src++;
        }
    }
    *dst++ = '\0';
}
int main(void) {
    // 1. 从环境变量获取 QUERY_STRING
    char *query_string = getenv("QUERY_STRING");
    if (query_string == NULL) {
        query_string = "";
    }
    printf("Content-Type: text/html\r\n\r\n");
    printf("<html><head><title>FastCGI GET Params</title></head><body>");
    printf("<h1>Received GET Parameters</h1>");
    // 2. 解析查询字符串
    char *key, *value;
    char *param = strtok(query_string, "&");
    while (param != NULL) {
        key = param;
        value = strchr(param, '=');
        if (value != NULL) {
            *value = '\0'; // 分割 key 和 value
            value++;       // value 指向 '=' 后面的第一个字符
        }
        // 3. 对 key 和 value 进行 URL 解码
        char decoded_key[1024];
        char decoded_value[1024];
        url_decode(decoded_key, key);
        if (value) {
            url_decode(decoded_value, value);
        } else {
            decoded_value[0] = '\0';
        }
        printf("<p><b>Key:</b> %s, <b>Value:</b> %s</p>", decoded_key, decoded_value);
        param = strtok(NULL, "&");
    }
    printf("</body></html>");
    return 0;
}

2 PHP 示例

PHP 是最常用于 FastCGI 的语言之一,在 PHP 中,这一切都由 PHP 引擎自动处理,你只需要使用超全局变量 $_GET 即可。

fastcgi get 参数
(图片来源网络,侵删)
<?php
// PHP 会自动解析 QUERY_STRING 并填充到 $_GET 超全局变量中
// 你不需要手动读取 QUERY_STRING 或进行 URL 解码
header('Content-Type: text/html; charset=utf-8');
echo "<html><head><title>FastCGI GET Params (PHP)</title></head><body>";
echo "<h1>Received GET Parameters</h1>";
// 直接遍历 $_GET 数组
if (!empty($_GET)) {
    foreach ($_GET as $key => $value) {
        // PHP 已经自动对键和值进行了 URL 解码
        echo "<p><b>Key:</b> " . htmlspecialchars($key) . 
             ", <b>Value:</b> " . htmlspecialchars($value) . "</p>";
    }
} else {
    echo "<p>No GET parameters received.</p>";
}
echo "</body></html>";
?>

注意: 使用 htmlspecialchars() 是为了防止 XSS 攻击,这是一个良好的安全实践。

3 Python (Flask) 示例

如果你使用 Python 的 WSGI 框架(如 Flask、Django)来处理 FastCGI,获取参数的方式与普通的 WSGI 应用完全相同。

# app.py
from flask import Flask, request
app = Flask(__name__)
@app.route('/')
def get_params():
    # request.args 是一个 MultiDict 对象,包含了所有 GET 参数
    # 它已经自动处理了 URL 解码
    name = request.args.get('name', 'Guest') # 提供默认值 'Guest'
    age = request.args.get('age', type=int)  # 可以指定类型,自动转换
    response_html = f"""
    <html>
        <head><title>FastCGI GET Params (Python Flask)</title></head>
        <body>
            <h1>Received GET Parameters</h1>
            <p><b>Name:</b> {name}</p>
            <p><b>Age:</b> {age}</p>
        </body>
    </html>
    """
    return response_html
if __name__ == '__main__':
    # 开发时可以直接运行,生产环境需要配合 cgi 或 flup 等库来运行 FastCGI
    #  flup.fcgi.FCGI().run(wsgi_app=app)
    app.run(debug=True)

GET vs. POST 参数

这是一个非常重要的区别,尤其是在处理 FastCGI 时:

特性 GET 参数 POST 参数
数据来源 QUERY_STRING 环境变量 标准输入
数据格式 key1=value1&key2=value2 key1=value1&key2=value2 (通常是 application/x-www-form-urlencoded)
获取方式 直接读取环境变量 需要从 stdin 读取,并根据 CONTENT_LENGTH 读取指定长度的数据
大小限制 通常受 URL 长度限制(约 2048 字符) 理论上只受服务器配置限制
安全性 参数会显示在 URL 和服务器日志中,不适合敏感信息 数据在请求体中,相对更安全

POST 参数获取示例 (C/C++)

// ... (url_decode 函数同上) ...
int main(void) {
    printf("Content-Type: text/html\r\n\r\n");
    printf("<html><body>");
    // 检查是否是 POST 请求
    char *request_method = getenv("REQUEST_METHOD");
    if (request_method && strcmp(request_method, "POST") == 0) {
        // 获取 Content-Length
        char *content_length_str = getenv("CONTENT_LENGTH");
        int content_length = 0;
        if (content_length_str) {
            content_length = atoi(content_length_str);
        }
        if (content_length > 0) {
            // 从标准输入读取 POST 数据
            char *post_data = (char *)malloc(content_length + 1);
            fread(post_data, 1, content_length, stdin);
            post_data[content_length] = '\0';
            printf("<h1>Received POST Data:</h1>");
            printf("<pre>%s</pre>", post_data);
            // 解析 POST 数据的逻辑与 GET 类似
            // ...
            free(post_data);
        }
    } else {
        printf("<p>This script only handles POST requests.</p>");
    }
    printf("</body></html>");
    return 0;
}

  1. GET 参数在 QUERY_STRING: GET 参数不是通过标准输入传递的,而是通过名为 QUERY_STRING 的环境变量。
  2. 自动解析: 像 PHP、Python Flask、Ruby on Rails 等高级语言和框架已经为你封装好了从 QUERY_STRING 读取、解析和 URL 解码的繁琐过程,直接使用 $_GETrequest.args 等即可。
  3. 手动解析: 如果你使用 C/C++ 等底层语言,你需要自己编写代码来读取 QUERY_STRING,按 & 和 分割,并进行 URL 解码。
  4. 区分 GET 和 POST: 一定要通过 REQUEST_METHOD 环境变量来判断请求类型,并分别从 QUERY_STRING (GET) 和 stdin (POST) 获取数据。
-- 展开阅读全文 --
头像
OpenWRT WiFi参数如何优化无线性能?
« 上一篇 昨天
lenovo miix28拆机
下一篇 » 今天

相关文章

取消
微信二维码
支付宝二维码

最近发表

标签列表

目录[+]