HTTP Methods, Status Codes and Payloads

本篇文章基于 REST api 介绍HTTP请求方法、HTTP响应码和API数据载荷, 是之前介绍 REST 那篇文章的延伸 HTTP Status Codes 1xx group: Signals that an operation is in progress 2xx group: Signals that a request was successfully processed 3xx group: Signals that a resource has been moved to a new location 4xx group: Signals that someting was wrong with the request 5xx group: Signals that there was an error while processing the request 在之前文章中, 定义的 HTTP status code 如下: POST /orders: 201 (Created) - 资源成功创建 GET /orders: 200 (OK) - 请求成功处理 GET /orders/{order_id}: 200 (OK) - 请求成功处理 PUT /orders/{order_id}: 200 (OK) - 资源成功更新 DELETE /orders/{order_id}: 204 (No Content) - 请求被成功处理, 但是没有响应内容, 对比其他方法, DELETE 请求不需要 payload 来删除资源 POST /orders/{order_id}/chanel: 200 (OK) - 取消成功, 由于并不创建任何资源, 故返回200 POST /orders/{orders\id}/pay: 200 (OK) - 支付成功, 同样由于未创建资源, 返回200 上面全是成功的响应, 下面介绍错误响应 ...

August 20, 2025 · 3 min · 575 words · Starslayerx

Redis String

介绍Redis中的字符串键 字符串 字符串建是 Redis 最基本的键值对类型, 这种类型的键值对会在数据库中把单独的一个值关联起来, 被关联的键和值可以为文本, 也可以是图片, 视屏, 音频等二进制数据. SET: 为字符串键设置值 O(1) SET key value ```Redis SET number "10086" > OK SET book "Redis in action" > OK ``` 对于已经存在的 key, 再次赋值会覆盖原值, 若不想覆盖后面添加参数 NX, 相反, 默认 XX 允许覆盖 ```Redis SET key "10086" NX > (nil) SET key "10086" XX > OK ``` GET: 获取字符串键的值 O(1) GET key ```Redis GET number > "10086" ``` 对于不存在的值, 返回空 ```Redis GET key_new > (nil) ``` GETSET: 获取旧值并更新值 O(1) ...

August 19, 2025 · 5 min · 974 words · Starslayerx

IEEE-754 Introduce

IEEE 754 标准数值类型及分类 整数 Integer 整数是没有小数部分的值, 在计算机内通常有两种表示方式: 有符号整数: 可以表示正数和负数, 最常用的是二补码表示. 例如 8 位二进制的范围为[-2^7, 2^7-1] 无符号整数: 仅表示非负数, 8 位二进制的范围为 [0, 2^8-1] 其中补码(Two’s Complement)用于表示负数 正数补码与原码相同 负数的补码 = 该数绝对值的二进制取反 + 1 通过补码, 可以使得加减运算统一, 溢出检测更加简单 浮点数 Floating-point 浮点数用于表示带小数的实数, 尤其适合科学计算和近似表示很大或很小的数值. IEEE 754 定义了浮点数的标准格式, 类似科学计数法: value = (-1)^(sign) x mantissa x 2^(exponent) 浮点数由三部分组成: 符号位 sign: 0/1代表正负 阶码 exponent: 通常使用偏移表示法 尾数 fraction/mantissa: 小数部分 常见浮点数类型: 单精度 float32: 1 位符号 + 8 位阶码 + 23 位尾数 双精度 float64: 1 位符号 + 11 位阶码 + 52 位尾数 浮点数的分类 Categories 以 64 精度为例 ...

August 18, 2025 · 2 min · 363 words · Starslayerx

Designing and Building REST APIs

这篇文章延续之前微服务的内容, 将介绍关于 REST API 的以下几个方面: REST API 的设计原则 Richardson maturity model (RMM) 如何帮助理解 REST 的优势和设计原则 REST API 中资源(resource)和端点(endpoints)设计的概念 表达性状态转移 representational state transfer (REST) 描述了一种通过网络进行通信的应用程序架构风格. 最初, REST 的概念包含了一组用于设计分布式、可扩展 Web 应用的约束条件. 随着时间推移, 出现了更为细致的协议和规范, 为 REST API 的设计提供了明确的指导方针. 如今, REST 已经成为构建 Web API 的最流行选择. 下面将继续在 CoffeeMesh 项目上, 设计相关订单 API. What is REST? REST 由 Roy Fielding 在他的博士论文 “Architectural Styles and the Design of Network-based Software Atchitecture” (PhD diss. University of California,Irvine,2000,p. 109) 中创造. ...

August 17, 2025 · 5 min · 878 words · Starslayerx

Intorduce UUID

UUID(Universally Unique Identifier, 通用唯一标识符) 是一种标准化的128位标识符, 用于在分布式系统中生成几乎不会重复的唯一 ID. 最早于 IETF 制定为 RFC 4122 标准, 保证在不同机器、不同时间生成的 ID 也能保持全局唯一. UUID 通常以16进制表示, 采用5段结构, 用连字符 - 分隔, 例如: 550e8400-e29b-41d4-a716-446655440000 有如下特点: 全局唯一 无中心依赖 不可预测 跨平台通用 UUID 有以下不同版本: 版本 生成 特点 v1 基于时间戳 + MAC 地址 按时间排序,含生成设备信息 v3 基于命名空间的 MD5 哈希 输入相同则输出相同(MD5 已不再安全) v4 基于操作系统的随机数生成 完全随机, 最常用 v5 基于命名空间的 SHA-1 哈希 与 v3 类似, 但使用 SHA-1 v6~v8 现代版本(草案) 提高排序性能和隐私保护 其中, 对于需要时间有序的使用 v1, 大多数通用场景使用 v4 UUID 的应用场景 数据库主键(分布式环境避免冲突) 会话标识(Session ID、Token) 文件命名(防止重名) 分布式系统节点 ID 追踪请求链路(Trace ID) 示例代码 ...

August 16, 2025 · 1 min · 138 words · Starslayerx

Microservice with FastAPI

What are microservices ? 什么是微服务? 微服务可以有多种不同的定义方式, 具体取决于希望强调微服务架构的哪个方面, 不同作者会给出略有不同但相关的定义 Sam Newman, 微服务领域最有影响力的作者之一, 给出了一个极简的定义: “Microservices are small, autonomous services that work together.” 这个定义强调了这样一个事实: 微服务是彼此独立运行的应用程序, 但它们可以协作完成任务. 该定义还强调微服务是 “small (小的)”, 这里的 small 并不是指微服务代码量的大小, 而是指微服务具有狭窄且定义清晰的职责范围, 符合单一职责原则(Single Responsibility Principle) —— 即“只做一件事,并把它做好”. James Lewis 和 Martin Fowler 撰写的一篇开创性文章提供了一个更详细的定义, 他们将微服务定义为一种架构风格(architectural style) “an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API” ...

August 15, 2025 · 6 min · 1167 words · Starslayerx

Python Generics

本篇文件介绍 Python 中的 泛型(Generics) Intro 在没有泛型的情况下, 会遇上以下几个问题: 难以表达意图 假设你编写了一个函数, 它接受一个列表, 并返回列表中的第一个元素. 在不使用类型提示的情况下, 这个函数可以处理任何类型的列表, 但我们无法在函数签名中表达"返回的元素的类型与列表中的元素类型相同"这个意图 def get_first_element(items): return items[0] 丧失类型信息 如果使用类型提示, 可能会像下面这样写, 但这样会丢失类型信息. list[Any] 表示可以接收任何类型的列表, 但 -> Any 意味着不知道返回的元素类型是什么, 这使得 mypy 等静态类型检测工具无法追踪类型, 降低了代码的可读性和安全性 from typing import Any def get_first_element(items: list[Any]) -> Any: return items[0] # 调用时, 类型检查工具无法得知 first_str 的类型 first_str = get_first_element(["hello", "world"]) 代码重复 如果为每种可能的类型都编写一个单独的函数, 则会导致代码重复 def get_first_int(items: list[int]) -> int: return items[0] def get_first_str(items: list[str]) -> str: return items[0] 通过引入 类型变量 (TypeVar) 来解决问题, 类型变量就像一个占位符, 代表在未来某时刻会被具体指定的类型 from typing import TypeVar T = TypeVar("T") def get_first_element(items: list[T]) -> T: return items[0] # 现在, 类型检查工具可以正确推断出类型 first_str: str = get_first_element(["hello", "world"]) first_int: int = get_first_element([1, 2, 3]) T = TypeVar('T') 定义了一个名为 T 的类型变量, 这里 T 只是一个约定俗成的名字, 也可以使用其他字母 items: list[T] 表示 items 是一个列表, 其内部元素类型是 T -> T: 返回类型也是 T 当使用 ["hello", "world"] 调用函数时, 静态类型检查器会推断出 T 是 str, 返回类型为 str 当使用 [1, 2, 3] 调用函数时, T 被推断为 int 注意: 这个函数假设列表非空, 如果传入空列表会抛出 IndexError ...

August 14, 2025 · 3 min · 553 words · Starslayerx

Python Strings

这篇文章总结一下 Python 中字符串的类型 Unicode String 字符串 u 在 Python3 中是多余的, 因为所有的普通字符串默认都是 Unicode, 但在 Python2 中, u 用来显示的表示 Unicode 字符串, 现在保留这个是为了向后兼容 Fromatted String 格式化字符串 f 前缀用于创建格式化字符串, 这是最常见的字符串格式方法, 运行在字符串中嵌入表达式, 在求值时转换为普通的 str name = "World" greeting = f"Hello, {name}!" # 结果: "Hello, World!" Raw String 原始字符串 r 前缀用于创建原始字符串, 会忽略反斜杠 \ 的转义功能, 在编写文件路径或正则表达式的时候非常有用, 可以避免大量的反斜杠转义 path = r"C:\Users\Documents" # 单个反斜杠 ' regex = r"\bword\b" # \b 不会被转义 Bytes String 字节串 b 前缀用于创建字节串字面量, 表示一个不可变的字节序列, 而不是 Unicode 文本, 字节串主要用于二进制数据, 例如图像文件、网络数据或压缩文件等 binary_data = b"Hello" # 存储的是 ASCII 编码的字节 Template String 模板字符串 t 前缀用于创建模板字符串, 这是 Python 3.14 引入的新功能, 由 PEP 750 通过. ...

August 13, 2025 · 1 min · 151 words · Starslayerx

FastAPI Response Model

本篇文章介绍 FastAPI 的返回类型 response model 可以在返回函数的类型注解中声明该接口的响应数据类型 类型注解的用法和输入数据参数一样, 可以使用: Pydantic 模型 list 列表 dict 字典 scalar 标量值 (int, bool …) @app.post("/items/") async def create_item(item: Item) -> Item: ... @app.get("/items/") async def read_items() -> list[Item]: ... FastAPI 会使用返回类型完成一下事情: 验证返回类型 如果返回的数据无效, 说明业务代码有问题, FastAPI 会返回服务器错误, 而不是把数据发给客户端 在 OpenAPI 中为响应添加 JSON Schema 用于自动生成接口文档, 自动生成客户端代码 最重要的是 它会限制并过滤出数据, 只保留返回类型中定义的字段 response_model Parameter 有时候可能需要返回的数据和类型注解不完全一致, 例如: 可能想返回字典或数据库对象, 但声明的响应类型为 Pydantic 模型 这样 Pydantic 会做数据文档、验证等工作, 即使返回的是字典或 ORM 对象 如果直接用返回类型注解, 编辑器会提示类型不匹配的错误 这种情况下, 可以用路径装饰器的 response_model 参数来声明响应类型, 而不是用返回类型注解 class Item(BaseModel): name: str description: str | None = None price: float tax: float | None = None tags: list[str] = [] @app.post("/items/", response_model=Item) async def create_item(item: Item) -> Any: return item @app.get("/items/", response_model=list[Item]) async def read_items() -> Any: return [ {"name": "Portal Gun", "price": 42.0}, {"name": "Plumbus", "price": 32.0}, ] 注意: ...

August 12, 2025 · 5 min · 918 words · Starslayerx

Fastapi Cookie and Header Parameters

这篇文章介绍 Fastapi 的 Cookie 和 Header 参数 Cookie Parameters 通过定义 Query 和 Path 参数一样定义 Cookie 参数 from typing Annotated from fastapi import Cookie, FastAPI app = FastAPI() @app.get("/items/") async def read_items(ads_id: Annotated[str | None, Cookie()] = None): return {"ads_id": ads_id} Cookie Parameters Models 如果有一组相关的 cookies, 可以使用 Pydantic model 来声明. 这样可以在多个部分复用这个模型, 同时还能一次性为所有参数声明验证规则和元数据. 下面使用 Pydantic 模型定义 Cookies, 然后将参数声明为 Cookie from typing import Annotated from fastapi import FastAPI, Cookie from pydantic import BaseModel app = FastAPI() class Cookie(BaseModel): session_id: str fatebook_tracker: str | None = None googall_tracker: str | None = None @app.get("/items/") async def read_items(cookies: Annotated[Cookies, Cookie()]): return cookies Forbid Extra Cookies 禁止额外的Cookie 在某些场景下(虽然并不常见), 可能希望限制 API 只能接收特定的 Cookie. 这样, API 就可以"自己"管理 Cookie 同意策略了. from typing import Annotated from fastapi import FastAPI, Cookie from pydantic import BaseModel app = FastAPI() class Cookies(BaseModel): model_config = {"extra": "forbid"} # forbid extra cookies session_id: str fatebook_tracker: str | None = None googall_tracker: str | None = None @app.get("/items/") async def read_items(cookies: Annotated[Cookies, Cookie()]): return cookies 这样, 如果客户端发送额外的 cookies, 则会收到一个错误响应. 例如, 客户端发送了 santa_tracker 这个额外 Cookie ...

August 11, 2025 · 3 min · 499 words · Starslayerx