You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS向Node.js(v19.0.1)发送含非ISO-8859-1字符的POST请求报错求助

解决请求头含特殊字符的POST请求失败问题

问题根源

HTTP/1.1 标准规定请求头字段值仅允许包含 ISO-8859-1 字符集内的可打印字符,你遇到的右单引号、表情符号、特殊符号等都属于非ISO-8859-1字符,服务器会直接拒绝这类不符合规范的请求,这也是Postman测试同样失败的原因。

方案1:将数据移至请求体(推荐,后端修改极小)

虽然你担心后端修改,但这个方案的后端改动非常简单,完全不需要复杂的JavaScript知识:

前端修改(Swift/Alamofire)

把原来放在请求头的参数移到请求体中:

import Foundation
import Alamofire

func updateNote(date: String, title: String, note: String, id: String) {
    // 构造请求体参数
    let parameters: [String: Any] = [
        "title": title,
        "date": date,
        "note": note,
        "id": id
    ]
    // 发送请求时传入parameters,Alamofire会自动编码为form-data格式
    AF.request("http://\(networkIP):8081/update", method: .post, parameters: parameters, encoding: URLEncoding.httpBody)
        .resume()
}

后端修改(Node.js)

如果你的后端用Express框架,只需要添加一行解析请求体的代码,再把获取数据的方式从headers改成body即可:

const express = require('express');
const app = express();

// 添加这行代码,用于解析form-data格式的请求体
app.use(express.urlencoded({ extended: true }));

app.post('/update', (req, res) => {
    // 原来的req.headers.title改成req.body.title,其他字段同理
    const title = req.body.title;
    const date = req.body.date;
    const note = req.body.note;
    const id = req.body.id;
    
    // 这里保留你原来的业务逻辑,不需要改动
    // ...
    
    res.send('success');
});

app.listen(8081);

这个方案不仅彻底解决字符问题,还符合HTTP规范,后续不会再出现类似兼容问题。

方案2:对请求头字段值进行RFC 2047编码(需后端配合解码)

如果实在不想调整后端核心逻辑,只能对特殊字符进行编码,让请求头符合ISO-8859-1规范,但后端必须解码才能拿到原始内容:

前端编码实现

在Swift中新增一个RFC 2047编码函数:

import Foundation

// 将字符串转为RFC 2047格式的Base64编码
func encodeHeaderValue(_ value: String) -> String? {
    guard let data = value.data(using: .utf8) else { return nil }
    let base64Str = data.base64EncodedString()
    return "=?UTF-8?B?\(base64Str)?="
}

// 修改请求函数
func updateNote(date: String, title: String, note: String, id: String) {
    let encodedTitle = encodeHeaderValue(title) ?? title
    let encodedNote = encodeHeaderValue(note) ?? note
    
    let headers: HTTPHeaders = [
        "title" : encodedTitle,
        "date" : date,
        "note" : encodedNote,
        "id" : id
    ]
    AF.request("http://\(networkIP):8081/update", method: .post, encoding: URLEncoding.httpBody, headers: headers)
        .resume()
}

后端解码(必须添加,否则无法获取原始内容)

在Node.js中新增解码逻辑:

// 新增解码函数
function decodeRFC2047(str) {
    return str.replace(/=\?UTF-8\?B\?(.*?)\?=/g, (match, base64) => {
        return Buffer.from(base64, 'base64').toString('utf8');
    });
}

// 在接口中使用解码后的字段
app.post('/update', (req, res) => {
    const title = decodeRFC2047(req.headers.title);
    const note = decodeRFC2047(req.headers.note);
    // ...业务逻辑
});

但这个方案不符合HTTP规范,后续仍可能出现其他兼容问题,所以还是优先推荐方案1。

内容的提问来源于stack exchange,提问作者eric_b_231

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 12:31:03