【问题标题】:How to encode python variables into URL and web-server response?如何将 python 变量编码为 URL 和 Web 服务器响应?
【发布时间】:2014-12-05 19:34:31
【问题描述】:

假设我有一个 Python 函数,它接受多个参数作为输入并返回一个输出。

现在我想要一个基于此功能的“网络服务”(API)。这意味着应该有一个可以使用一些参数调用的 URL,这些参数应该传递给函数,函数获取它们并计算相应的结果(输出)并将其传递回 Web 服务器,在它的反过来,将结果显示给用户(可能是另一个程序)。

如果一个简单的函数接受两个实值参数(例如xy)并返回一个实值结果,函数的调用可以通过 throw get 参数来组织。例如:

www.my_web_site.org/my_func_name?x=1.234&y=3.456

因此,我希望网页只包含一个实数。

但是,对于更复杂的输入,我应该怎么做并不是很明显。假设作为某些参数的值,我们可以有列表和字典。我应该如何在 URL 中对它们进行编码。我可以想象这样的事情:

www.my_web_site.org/my_func_name?x=[1,2,3,4]&y={1:'a',2:'b'}

但是,我不确定这是一个优雅的解决方案。有什么标准怎么做吗?也许我应该使用 XML 或 JSON 对输入进行编码。

同样的问题也适用于输出。假设我们可以有字典或列表甚至一个集合作为输出。我该如何表示。我应该只使用str(output) 还是有其他“标准”解决方案?

【问题讨论】:

    标签: python xml json api url


    【解决方案1】:

    我应该只使用str(output)吗?

    不!首先,您需要repr(),因为它为许多内置 Python 类型返回有效的 Python 代码。但是,要解析它的输出,您需要以某种方式执行它。虽然 Python 有 ast.literal_eval() 可以安全地在不受信任的输入上运行(它只处理字符串、数字、元组、列表、字典、布尔值和 None),但它仍然不是很便携,而且传递 Python 代码有点难看用于数据。


    最好的解决方案是使用JSON 对其进行编码。您可以使用json.dumps 进行序列化,使用json.loads 进行反序列化。

    • 几乎可以用每种语言解析它,因此即使您想从其他工具发送请求,也可以轻松创建参数
    • 它是一种标准化格式,也易于人类阅读。
    • 反序列化不受信任的数据是安全的(您不能编写在反序列化时会占用大量内存的 JSON,也不能像使用 pickle 那样执行任意代码)
    • 它不会像 XML 那样增加大量的膨胀/偷听。

    但是,在发送 JSON 有效负载时,我会使用 POST 而不是 GET(即使对 JSON 数据进行 url 编码是安全的 - 但在 URL 中包含一长串 JSON 并不那么漂亮)。这样,您可以简单地将整个 JSON 结构转储到请求正文中,使用 application/json Content-type 并且在您的后端您甚至可以轻松访问它,例如request.get_json() 如果您使用的是 Flask。

    如果您需要在 JSON 中支持不是 natively supported 的变量类型,您可以简单地将 JSON 编码器/解码器子类化并将这些类型转换为您喜欢的任何符号,例如日期时间对象的 ISO 日期字符串。

    【讨论】:

      【解决方案2】:

      RESTful 风格

      GET /rectangle/1.34553/7.3439
      GET /rectangle?x=1.5478;y=7.4535
      

      黑客

      GET /rectangle?args=%5B1.5467%2C+7.543%5D  # urlencoded json
      GET /rectangle?_=WzEuNTY3NCwgNy4zNTQ2Mjdd  # url-safe base64 encoded json
      GET /rectangle?_=eJzTyCkw4PI05EocxYMH6wEAXqha4Q  # left as exercise for the reader
      

      【讨论】:

        【解决方案3】:

        我们有一个类似的场景(数据库中介)。我们从 GET 开始,但后来切换到 POST 来提供输入,因为不同浏览器中的 URL 长度有不同的限制。参数的 urlencoding 也很昂贵且难以观察。

        我们首选的发送输入方式是 JSON,但有一些约定。与 XML 相比,JSON 易于阅读,并且可以通过 **kwargs 方法轻松地为 Python 函数提供参数。但是依赖于调用者知道参数的名称。这比您想象的要难,因为它使名称的任何更改(例如,参数名称中的拼写错误)都难以修复并引入了一定程度的脆弱性。 (对此我没有想到明显的解决方案!)一个单独的列表提供了参数的位置顺序。这对我们来说很重要,因为 Web 服务的另一端是一个 DB PROC,而 SQL 仍然停留在最近一千年的严格位置参数中。使用纯 Python 服务器端,这对您来说可能不是问题,但也可以考虑 C++ 等。

        在输出端,我们交替使用纯 JSON 和 CSV 的变体,因为我们不想承担将大量行作为 JSON 哈希对象处理的成本。所以我们也使用 CSV 字符串数组(1 行=1 字符串)对行进行编码,有一个标题行对象,并在接收端将其解析回一个行对象数组。

        HTH。我怀疑是否有一个“正确”的答案。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2023-04-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-08-10
          • 1970-01-01
          • 2023-02-14
          相关资源
          最近更新 更多