我想做的是解析一个原始的http响应。我从一个PHP
文件中得到http响应,例如我的php文件有以下内容:
<?php
echo "Hello";
header("Location: form.php");
?>
它会返回以下响应:
Status: 302 Found\r\nX-Powered-By: PHP/8.1.11\r\nLocation: form.php\r\nContent-type: text/html; charset=UTF-8\r\n\r\nHello
到目前为止,一切都很好。但是如果文件有错误,比如像这样的语法错误:
<?php
echo "Hello"//;
header("Location: form.php");
?>
我得到这样的回应:
PHP message: PHP Parse error: syntax error, unexpected identifier \"header\", expecting \",\" or \";\" in/var/www/public/index.php on line 5Status: 500 Internal Server Error\r\nX-Powered-By: PHP/8.1.11\r\nContent-type: text/html; charset=UTF-8\r\n\r\n
正如您所看到的,响应明显不同,头的顺序也不同(我想澄清一下,我使用“{:?}"打印了这个,所以一些"
后面的\
实际上不是响应的一部分)。因此,这导致了一些库(如this)返回错误,所以我决定自己解析响应。
那么,我该如何正确地解析响应呢?我该如何处理它呢?我应该使用正则表达式之类的东西吗?提前感谢。
为了澄清,我使用FastCGI协议获得http响应,所以我不能用其他任何方式获得响应。我还想说,我不是在寻找解决我在库中遇到的错误的方法,我只是想知道如何自己解析http响应。
编辑
你们可以看到我是如何得到响应的我会给你们看我的rust代码,是这样的:
use std::os::unix::net::{UnixStream};
use std::io::{Read, Write};
use std::str;
fn main() {
const FCGI_VERSION_1: u8 = 1;
const FCGI_BEGIN_REQUEST:u8 = 1;
const FCGI_END_REQUEST: u8 = 3;
const FCGI_STDIN: u8 = 5;
const FCGI_STDOUT: u8 = 6;
const FCGI_STDERR: u8 = 7;
const FCGI_RESPONDER: u16 = 1;
const FCGI_PARAMS: u8 = 4;
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();
// write the FCGI_PARAMS
let param1_name = "SCRIPT_FILENAME".as_bytes();
let param1_value = "/home/davebook-arch/projects/so/index.php".as_bytes();
let lengths1 = [ param1_name.len() as u8, param1_value.len() as u8 ];
let params1_len: u16 = (param1_name.len() + param1_value.len() + lengths1.len()) as u16;
let param2_name = b"REQUEST_METHOD";
let param2_value = b"GET";
let lengths2 = [ param2_name.len() as u8, param2_value.len() as u8 ];
let params2_len: u16 = (param2_name.len() + param2_value.len() + lengths2.len()) as u16;
let params_len = params1_len + params2_len;
let paramsRequest = vec![
FCGI_VERSION_1, FCGI_PARAMS,
(requestId >> 8) as u8, (requestId & 0xFF) as u8,
(params_len >> 8) as u8, (params_len & 0xFF) as u8,
0, 0,
];
socket.write_all (¶msRequest).unwrap();
socket.write_all (&lengths1).unwrap();
socket.write_all (param1_name).unwrap();
socket.write_all (param1_value).unwrap();
socket.write_all (&lengths2).unwrap();
socket.write_all (param2_name).unwrap();
socket.write_all (param2_value).unwrap();
let mut stdout: String = String::new();
// get the response
let requestHeader = vec![
FCGI_VERSION_1, FCGI_STDOUT,
(requestId >> 8) as u8, (requestId & 0xFF) as u8,
0, 0,
0, 0,
];
socket.write_all(&requestHeader).unwrap();
loop {
// read the response header
let mut responseHeader = [0u8; 8];
socket.read_exact (&mut responseHeader).unwrap();
if responseHeader[1] != FCGI_STDOUT && responseHeader[1] != FCGI_STDERR{
if responseHeader[1] == FCGI_END_REQUEST {
println!("FCGI_END_REQUEST: {:?}", responseHeader);
break;
} else {
println!("NOT FCGI_END_REQUEST: {}", responseHeader[1]);
break;
}
}
// read the body
let responseLength = ((responseHeader[4] as usize) << 8) | (responseHeader[5] as usize);
let mut responseBody = vec![0; responseLength];
socket.read_exact (&mut responseBody).unwrap();
stdout.push_str(&String::from_utf8_lossy(&responseBody));
// read the padding
let mut pad = vec![0; responseHeader[6] as usize];
socket.read_exact (&mut pad).unwrap();
}
println!("Output: {:?}", stdout);
}
完整和详细的上下文在this问题中(在我对那个问题的回答中有更多的细节)。在我看来,最好向你展示这个问题,这样你就可以看到我是如何详细解释那里的一切的。
编辑2
我已经执行了这个问题答案中的代码。它运行得很好,但只是在第一种情况下,在第二种情况下,我该怎么办?我是收集错误数据的那个人吗?或者我该如何解析http响应?
1条答案
按热度按时间ee7vknir1#
我从来没有在Rust做过这个,我做Rust的时间也不长,不要把这个当作权威的回答什么的,但是做
给了我
并将原始数据转换为
给出:
因此您可以使用
检查它是否是“PHP消息”,在本例中,PHP消息是
PHP Parse error: syntax error, unexpected identifier \"header\", expecting \",\" or \";\" in/var/www/public/index.php on line 5