使用OpenSSL BIO发起请求时出现400 Bad Request错误求助
结合你描述的情况——网站HTTP会重定向到HTTPS、需要访问带www前缀域名下的PHP脚本,400错误通常和请求构造不规范或者SSL连接后的请求处理有关,给你几个具体的排查和解决方向:
1. 直接使用HTTPS目标URL,跳过重定向
你的网站会把HTTP请求重定向到HTTPS,那不如直接连接HTTPS的443端口,请求https://www.yourdomain.com/your-target-script.php,避免处理重定向的额外步骤,也减少出错概率。
2. 确保HTTP请求头完全合规
400错误最常见的原因就是请求格式不对,尤其是缺少Host请求头(虚拟主机环境下,服务器完全依赖这个头识别站点)。发送的HTTP请求必须符合标准格式,比如GET请求要写成这样:
const char* http_request = "GET /your-target-script.php HTTP/1.1\r\n" "Host: www.yourdomain.com\r\n" // 这个头必须有! "Connection: close\r\n" // 告诉服务器请求结束后关闭连接 "\r\n"; // 两个换行表示请求头结束
注意每一行末尾是\r\n,最后必须有两个连续的换行(\r\n\r\n),服务器才会认为请求发送完成。
3. 检查OpenSSL连接流程是否正确
确保你的SSL初始化和握手步骤没有问题,关键步骤包括:
- 初始化OpenSSL库:调用
SSL_library_init()、OpenSSL_add_all_algorithms()、SSL_load_error_strings() - 创建TLS客户端上下文:用
SSL_CTX_new(TLS_client_method())(不要用旧的SSLv23_client_method(),优先用TLS 1.2+) - 连接到服务器的443端口(HTTPS默认端口)
- 完成SSL握手:调用
SSL_connect(ssl),检查返回值是否大于0(表示握手成功)
4. 对比浏览器请求头,补充必要字段
有些服务器会校验User-Agent等头字段,你可以打开浏览器开发者工具(F12),在Network面板里找到访问该PHP脚本的请求,复制它的请求头,在你的代码里补充进去,比如加上:
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36\r\n
5. 查看服务器日志定位具体错误
如果能访问目标网站的服务器日志(比如Apache的error.log或者Nginx的access.log),里面会记录400错误的详细原因,比如“Invalid Host header”“Bad request line”,这能帮你快速定位问题所在。
简单示例代码片段
这里给你一个构造请求并发送的简化示例(假设已经完成SSL连接,ssl是有效的SSL*对象):
// 构造符合标准的HTTP GET请求 const char* request = "GET /your-script.php HTTP/1.1\r\n" "Host: www.yourdomain.com\r\n" "User-Agent: OpenSSL-Client/1.0\r\n" "Connection: close\r\n\r\n"; // 发送请求 int write_len = SSL_write(ssl, request, strlen(request)); if (write_len <= 0) { // 处理发送错误 fprintf(stderr, "SSL write failed: %d\n", SSL_get_error(ssl, write_len)); return -1; } // 读取响应 char buffer[4096]; int read_len; while ((read_len = SSL_read(ssl, buffer, sizeof(buffer)-1)) > 0) { buffer[read_len] = '\0'; printf("Response content:\n%s", buffer); } // 清理资源 SSL_shutdown(ssl); SSL_free(ssl); SSL_CTX_free(ctx);
如果按照上面的步骤调整后还是有问题,可以把你代码中SSL连接和请求构造的部分贴出来,这样能更精准地帮你排查。
内容的提问来源于stack exchange,提问作者user6821023

