我想请您帮助解决我在Rust中使用FastCGI协议时遇到的一个问题。
这是我的代码(我有这个代码感谢我过去的问题的答案相关的主题,这是this和这个):
# ![allow(non_snake_case)]
# ![allow(unused_must_use)]
use std::os::unix::net::{UnixStream};
use std::io::{Read, Write};
fn main() {
const FCGI_VERSION_1: u8 = 1;
const FCGI_BEGIN_REQUEST:u8 = 1;
const FCGI_END_REQUEST: u8 = 3;
const FCGI_RESPONDER: u16 = 1;
const FCGI_PARAMS: u8 = 4;
const FCGI_GET_VALUES: u8 = 9;
let socket_path = "/run/php-fpm/php-fpm.sock";
let mut socket = match UnixStream::connect(socket_path) {
Ok(sock) => sock,
Err(e) => {
println!("Couldn't connect: {e:?}");
return
}
};
let requestId: u16 = 1;
let role: u16 = FCGI_RESPONDER;
let beginRequest = vec![
// FCGI_Header
FCGI_VERSION_1, FCGI_BEGIN_REQUEST,
(requestId >> 8) as u8, (requestId & 0xFF) as u8,
0x00, 0x08, // This is the size of `FCGI_BeginRequestBody`
0, 0,
// FCGI_BeginRequestBody
(role >> 8) as u8, (role & 0xFF) as u8,
0, // Flags
0, 0, 0, 0, 0, // Reserved
];
socket.write_all(&beginRequest).unwrap();
let data = vec![
(100) as u8,
];
let contentLength = data.len();
assert!(contentLength <= usize::MAX);
let requestHeader = vec![
FCGI_VERSION_1, FCGI_BEGIN_REQUEST,
(requestId >> 8) as u8, (requestId & 0xFF) as u8,
(contentLength >> 8) as u8, (contentLength & 0xFF) as u8,
0, 0,
];
socket.write_all(&requestHeader).unwrap();
let param_name = "SCRIPT_FILENAME".as_bytes();
let param_value = "index.php".as_bytes();
let lengths = [ param_name.len() as u8, param_value.len() as u8 ];
socket.write_all (&lengths).unwrap();
socket.write_all (param_name).unwrap();
socket.write_all (param_value).unwrap();
let mut response = String::new();
socket.read_to_string(&mut response);
print!("response: {}", response);
}
这段代码启动了一个请求,并在套接字中写入参数SCRIPT_FILENAME
。我认为这段代码工作正常,在执行程序时,控制台显示如下:
response: DX-Powered-By: PHP/8.1.11
Content-type: text/html; charset=UTF-8
因此,我假设FastCGI没有执行我传递给它的PHP文件,所以我所做的是尝试找到如何执行这些文件,或者执行FastCGI规范索引中的请求。
但是我不知道怎么做。那么我怎么才能得到我传递给它的php文件的输出呢?我遗漏了什么呢?我想澄清一下,我对FastCGI是一个新手,我对二进制协议没有任何经验,所以我真的很抱歉,如果我遗漏了一些看起来很明显的东西。
1条答案
按热度按时间mspsb9vt1#
您应该删除第二条
FCGI_BEGIN_REQUEST
消息,并在FCGI_PARAMS
消息 * 之后 * 添加一条FCGI_STDIN
消息(如果没有要发送的POST
数据,请使用contentLength=0
),然后使用read_exact
读取响应的报头,提取其内容长度,并再次使用read_exact
获取响应的内容:备注:
FCGI_STDOUT
消息,因此您需要一个循环来重新组装它们。FCGI_STDOUT
以外的其他消息类型,因此您需要添加对该消息类型的适当处理,以代替我使用的assert
。