我想要做的是決議一個原始的 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
正如您所看到的,回應明顯不同,標題的順序也不同(我想澄清一下,我使用“{:?}”列印了這個,所以\后面的一些"并不是回應的一部分)所以,有導致像這樣的一些庫回傳錯誤,所以我決定自己決議回應。
那么如何以正確的方式決議回應呢?知道我可以得到第一個和第二個這樣的結果,我該如何處理?我應該使用正則運算式之類的東西嗎?提前致謝。
澄清一下,我使用 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);
}
完整和詳細的背景關系在這個問題中(在我對該問題的回答中有更多細節)。在我看來,最好向您展示這個問題,以便您可以看到我如何詳細解釋那里的所有內容。
編輯 2
我已經執行了這個問題的答案中的代碼。它作業得很好,但只有在第一種情況下,在第二種情況下,我能做什么?我是不是收集了錯誤的資料?或者我怎樣才能決議那個http回應?
uj5u.com熱心網友回復:
我以前從未在 Rust 中做過這個,而且我做 Rust 的時間也不長,不要將此作為權威答案或任何東西,而是做
fn main(){
let raw="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\r\n\r\nboody contains separator, account for that";
let raw_split = raw.splitn(2, "\r\n\r\n").collect::<Vec<&str>>();
let headers = raw_split[0].split("\r\n").collect::<Vec<&str>>();
let body = raw_split[1];
let mut headers_map = std::collections::HashMap::new();
for header in headers {
let header = header.splitn(2,": ").collect::<Vec<&str>>();
headers_map.insert(header[0], header[1]);
}
println!("{:?}", headers_map);
println!("{}", body);
}
給我
{"X-Powered-By": "PHP/8.1.11", "Status": "302 Found", "Location": "form.php", "Content-type": "text/html; charset=UTF-8"}
Hello
boody contains separator, account for that
并將原始更改為
let raw = "PHP message: PHP Parse error: syntax error, unexpected identifier \"header\", expecting \",\" or \";\" in/var/www/public/index.php on line 5\r\nStatus: 500 Internal Server Error\r\nX-Powered-By: PHP/8.1.11\r\nContent-type: text/html; charset=UTF-8\r\n\r\n";
給出:
{"PHP message": "PHP Parse error: syntax error, unexpected identifier \"header\", expecting \",\" or \";\" in/var/www/public/index.php on line 5", "X-Powered-By": "PHP/8.1.11", "Content-type": "text/html; charset=UTF-8", "Status": "500 Internal Server Error"}
所以你可以使用
if headers_map.contains_key("PHP message"){
what to do if its a PHP message?
}
檢查它是否是“PHP 訊息”,在這種情況下,PHP 訊息是PHP Parse error: syntax error, unexpected identifier \"header\", expecting \",\" or \";\" in/var/www/public/index.php on line 5
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/525837.html
上一篇:尚不可用的資源的HTTP狀態代碼
