2011-11-10 41 views
7

Một ngữ cảnh nhỏ:
Tôi cần chạy tập lệnh PHP trong trình duyệt, nhưng tôi không muốn gặp phải sự cố khi cài đặt máy chủ và chịu phí trên máy chủ trên máy tính của mình và tất cả những thứ đi kèm với nó, bao gồm tường lửa, blah blah blah.Tiêu đề() hoạt động như thế nào?

Vì vậy, thay vào đó tôi đã viết máy chủ của riêng mình. Đó là một kịch bản PHP đơn giản mà lắng nghe các kết nối trên cổng 80 của LAN IP của tôi, sau đó tôi chỉ cần tải IP đó trong trình duyệt của tôi và nó hoạt động. Nó nhận được yêu cầu HTTP và bắt đầu một kịch bản PHP thứ hai bằng cách sử dụng exec - điều này là để tôi có thể thực hiện các thay đổi cho nó một cách dễ dàng mà không phải khởi động lại kịch bản máy chủ. Tập lệnh PHP thứ hai này phân tích cú pháp yêu cầu và cuối cùng là include s tập lệnh thực sự được gọi. Nó nhận được kết quả từ đó và gửi phản hồi trở lại trình duyệt với các tiêu đề thích hợp (mà tôi có thể thay đổi).

Vâng, đó là một mớ hỗn độn, nhưng nó hoạt động. Nó làm những gì tôi cần nó để làm.

Bây giờ cho câu hỏi:
Tôi không thể sử dụng header(). Nó dường như không có bất kỳ ảnh hưởng nào đến những gì được gửi trở lại trình duyệt thông qua kết nối socket. Thay vào đó, tôi đã thực hiện chức năng setheader() và lưu trữ các tiêu đề trong một mảng để được thêm vào phần trả lời.

Tôi muốn biết cách chức năng header() thực sự hoạt động bên trong, để tôi có thể sử dụng chức năng đó thay vì chức năng "bị tấn công" của tôi.

+1

[Từ hướng dẫn:] (http://docs.php.net/manual/en/function.header.php) * Headers sẽ chỉ có thể truy cập và xuất ra khi một SAPI hỗ trợ chúng đang được sử dụng. * – Gordon

+0

Bạn có thể vui lòng in phản hồi mẫu được gửi bởi kịch bản máy chủ của bạn tới trình duyệt sẽ bao gồm tiêu đề và nội dung không? –

Trả lời

2

Chức năng header() hoàn toàn bị bỏ qua bởi SAPI của CLI. Nó có tác dụng trên các SAPI của Apache và CGI.

Nói một cách đơn giản, SAPI của CLI không thực hiện bất kỳ logic nào trong các hàm sapi_*_header_*. Mỗi dụ, đối với CLI SAPI, trong php_cli.c:

static int sapi_cli_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) /* {{{ */ 
{ 
    /* We do nothing here, this function is needed to prevent that the fallback 
    * header handling is called. */ 
    return SAPI_HEADER_SENT_SUCCESSFULLY; 
} 
/* }}} */ 

Tất cả những chức năng cơ bản trở NULL, 0 hoặc một tin nhắn thành công giả mạo.

Đối với SAPI CGI, trong cgi_main.c:

static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) 
{ 
    char buf[SAPI_CGI_MAX_HEADER_LENGTH]; 
    sapi_header_struct *h; 
    zend_llist_position pos; 
    zend_bool ignore_status = 0; 
    int response_status = SG(sapi_headers).http_response_code; 

    // Lots of other code... 
} 

Bạn có thể dễ dàng thực hiện công việc này bằng cách sử dụng php-cgi nhị phân và một số thao tác mảng:

server.php

$script_to_run = 'script.php'; 
exec('php-cgi '.escapeshellarg($script_to_run), $output); 
$separator = array_search("", $output); 

$headers = array_slice($output, 0, $separator); 
$body = implode("\r\n", array_slice($output, $separator+1)); 

print_r($headers); 
print $body; 

script.php

header('Content-Type: text/plain'); 
echo 'Hello, World!'; 

Output:

Array 
(
    [0] => X-Powered-By: PHP/5.3.8 
    [1] => Content-Type: text/plain 
) 
Hello, World! 
1

Chức năng header() hoạt động chính xác như triển khai của bạn: nó chỉ gửi tiêu đề văn bản thuần túy trong phản hồi, trước nội dung của trang (đó là lý do tại sao nó sẽ ném lỗi nếu nội dung đã được gửi cho khách hàng). Vì vậy, tôi nghĩ bạn đang làm đúng cách. Dù sao, bạn có một số vấn đề trong việc thực hiện của bạn. Tôi nghĩ rằng việc cài đặt một máy chủ Web sẽ dễ dàng hơn rất nhiều.

0

Và bạn có sử dụng đúng cách gọi theo kiểu CGI không? - nếu không, hầu hết các chức năng liên quan đến HTTP sẽ không hoạt động trong PHP - và vẫn CGI không tốt nhất như cuộc gọi thư viện từ Apache hoặc IIS

Tại sao không dùng EasyPHP hoặc một cái gì đó như thế này?

PS Ý của bạn là gì bởi "yêu cầu phân tích cú pháp"?

0

Các tiêu đề gửi thực tế được thực hiện bởi lớp SAPI (API máy chủ) của PHP. Ví dụ SAPIs bao gồm mod_php cho Apache và phiên bản CLI của PHP sẽ được chạy khi bạn gọi exec. Trong trường hợp của SAPI CLI, việc gửi các tiêu đề là một noop vì nó thường không có ý nghĩa để hiển thị các tiêu đề HTTP cho một kịch bản chạy trên dòng lệnh.

Hãy thử sử dụng php-cgi làm nhị phân thay vì PHP. Các SAPI CGI nên xuất các tiêu đề chính xác.

0

Tùy thuộc vào mô-đun SAPI (mã gọi tập lệnh PHP) để quyết định phải làm gì với tiêu đề. Các SAPI CLI, mà bạn có thể sử dụng, chỉ cần bỏ qua bất kỳ tiêu đề được thiết lập bởi kịch bản. SAPI CGI, mà bạn có thể sử dụng với lệnh php-cgi, xuất chúng theo mặc định nhưng hỗ trợ giao diện dòng lệnh để ngăn chặn chúng. Lý tưởng nhất, bạn sẽ chỉ viết mô-đun SAPI của riêng bạn mà giao diện đúng với máy chủ web của bạn.

0

Một HTTP response thông thường trông giống như rằng:

HTTP/1.1 200 OK 
Date: Thu, 10 Nov 2011 15:35:27 GMT 
Server: Apache 
Connection: close 
Transfer-Encoding: chunked 
Content-Type: text/html; charset=None 

<!DOCTYPE html> 
<html> 
.... 

Chức năng PHP header() chăm sóc đặt - tốt, - tiêu đề vào phần đầu của câu trả lời. HTML thực tế bạn có thể xuất bằng cách sử dụng print và các mục tương tự.

Bây giờ, nếu đó là tập lệnh PHP, đang phát Apache, tập lệnh này chịu trách nhiệm đặt dòng tiêu đề của bạn trong phản hồi của nó. header() chỉ hoạt động nếu đầu ra được gửi tới thiết bị xuất chuẩn và không được ghi tùy chỉnh vào ổ cắm sao cho, sau khi tập lệnh PHP-CGI kết thúc, tiêu đề thích hợp có thể được thêm vào đầu ra.

0

Tôi biết tôi sẽ nghe có vẻ ngu ngốc, nhưng tại sao không chỉ cài đặt đèn hoặc đèn? Nó thực sự là "giải nén & chạy & voilà" loại giải pháp, điều đó thực sự sẽ giúp bạn giải quyết vấn đề.

Các vấn đề liên quan