2012-09-19 46 views
39

Tôi đang sử dụng SimpleHTTPServer để kiểm tra một số trang web mà tôi đang làm việc. Nó hoạt động tốt, tuy nhiên tôi cần phải thực hiện một số yêu cầu miền chéo. Điều đó yêu cầu đặt tiêu đề Access-Control-Allow-Origin với tên miền mà trang được phép truy cập.Tôi có thể đặt tiêu đề bằng SimpleHTTPServer của python không?

Có cách nào dễ dàng để đặt tiêu đề bằng SimpleHTTPServer và phân phối nội dung gốc không? Tiêu đề sẽ giống nhau trên mỗi yêu cầu.

Trả lời

42

Đây là một chút của một hack vì nó thay đổi end_headers() hành vi, nhưng tôi nghĩ rằng nó tốt hơn một chút vì sao chép và dán toàn bộ SimpleHTTPServer.py tập tin.

Cách tiếp cận của tôi ghi đè end_headers() trong một phân lớp và trong đó gọi send_my_headers() theo sau bằng cách gọi số siêu lớp là end_headers().

Nó không phải 1 - 2 dòng, dù dưới 20; chủ yếu là boilerplate.

#!/usr/bin/env python 
import SimpleHTTPServer 

class MyHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): 
    def end_headers(self): 
     self.send_my_headers() 

     SimpleHTTPServer.SimpleHTTPRequestHandler.end_headers(self) 

    def send_my_headers(self): 
     self.send_header("Access-Control-Allow-Origin", "*") 


if __name__ == '__main__': 
    SimpleHTTPServer.test(HandlerClass=MyHTTPRequestHandler) 
+0

Cũng đừng quên để gửi các tiêu đề nếu bạn đang xác định lại do_GET: 'def do_GET (tự): self.send_head()' – user474708

+1

Giải pháp này không hoạt động nếu sử dụng mặc định do_GET(). Nó không gọi end_headers. – Koffiman

4
# coding: utf-8 
import SimpleHTTPServer 
import SocketServer 
PORT = 9999 

def do_GET(self): 
    self.send_response(200) 
    self.send_header('Access-Control-Allow-Origin', 'http://example.com')   
    self.end_headers() 

Handler = SimpleHTTPServer.SimpleHTTPRequestHandler 
Handler.do_GET = do_GET 
httpd = SocketServer.TCPServer(("", PORT), Handler) 
httpd.serve_forever() 
+3

Tôi đoán tôi nên rõ ràng hơn ở chỗ tôi vẫn muốn cung cấp nội dung ban đầu, nhưng với tiêu đề bổ sung, không chỉ là tiêu đề một mình. – nynexman4464

9

tôi muốn nói không có cách nào đơn giản để làm việc đó, nơi mà phương tiện đơn giản "chỉ cần thêm 1-2 dòng mà sẽ viết tiêu đề bổ sung và duy trì các chức năng hiện có". Vì vậy, giải pháp tốt nhất là phân lớp lớp SimpleHTTPRequestHandler và triển khai lại chức năng, với việc thêm tiêu đề mới.

Vấn đề đằng sau lý do tại sao không có cách nào đơn giản để làm điều này có thể được quan sát bằng cách nhìn vào việc thực hiện của lớp SimpleHTTPRequestHandler trong thư viện Python: http://hg.python.org/cpython/file/19c74cadea95/Lib/http/server.py#l654

Thông báo các send_head() phương pháp, đặc biệt là các dòng ở phần cuối của phương thức gửi tiêu đề phản hồi. Chú ý việc gọi phương thức end_headers(). Phương pháp này viết tiêu đề cho đầu ra, cùng với một dòng trống báo hiệu kết thúc của tất cả các tiêu đề và bắt đầu của phần thân phản hồi: http://docs.python.org/py3k/library/http.server.html#http.server.BaseHTTPRequestHandler.end_headers

Do đó, sẽ không thể phân lớp trình xử lý SimpleHTTPRequestHandler, gọi siêu -class do_GET() phương pháp, và sau đó chỉ cần thêm một tiêu đề - bởi vì việc gửi các tiêu đề đã hoàn thành khi cuộc gọi đến phương thức trả về siêu đẳng cấp do_GET(). Và nó phải hoạt động như thế này bởi vì phương thức do_GET() phải gửi phần thân (tệp được yêu cầu) và gửi phần thân - nó phải hoàn thành việc gửi các tiêu đề. Vì vậy, một lần nữa, tôi nghĩ rằng bạn đang bị mắc kẹt với sub-classing các lớp SimpleHTTPRequestHandler, thực hiện nó chính xác như mã trong thư viện (chỉ cần sao chép-dán nó?), Và thêm một tiêu đề trước khi cuộc gọi đến end_headers() phương pháp trong send_head():

... 
self.send_header("Last-Modified", self.date_time_string(fs.st_mtime)) 
# this below is the new header 
self.send_header('Access-Control-Allow-Origin', '*') 
self.end_headers() 
return f 
... 
+0

Hmm, vâng, tôi đang tìm giải pháp một hoặc hai dòng. Sao chép phương pháp này là giải pháp tốt nhất tiếp theo mặc dù – nynexman4464

+0

Sau đó, nó không nên cung cấp self.send_header() và self.end_headers() API cho công chúng như tất cả nó làm là để gây nhầm lẫn nhà phát triển tiêu dùng. Các tiêu đề thực sự được thêm vào nội dung phản hồi. – yorkw

0

Trong khi đây là một câu trả lời cũ, kết quả đầu tiên của mình trong google ...

Về cơ bản những gì @ iMon0 suggested..Seems có đúng không? .. Ví dụ về doPOST

def do_POST(self): 
    self.send_response 
    self.send_header('Content-type','application/json') 
    self.send_header('Access-Control-Allow-Origin','*') 
    self.end_headers() 
    sTest = {} 
    sTest['dummyitem'] = "Just an example of JSON" 
    self.wfile.write(json.dumps(sTest)) 

Bằng làm điều này, dòng chảy cảm thấy chính xác ..

1: Bạn nhận được một yêu cầu

2: Bạn áp dụng các tiêu đề và loại phản ứng bạn muốn

3:. Bạn gửi lại dữ liệu bạn muốn, hãy này những gì hoặc làm thế nào bao giờ bạn muốn,

Ví dụ trên là làm việc tốt cho tôi và có thể được mở rộng hơn nữa, nó chỉ là một máy chủ JSON xương trần. Vì vậy, tôi sẽ để lại điều này ở đây trên SOF trong trường hợp ai đó cần nó hoặc bản thân tôi trở lại trong một vài tháng cho nó.

Điều này tạo ra tệp JSON hợp lệ chỉ với đối tượng sTest, Giống như một trang/tệp được tạo bởi PHP.

+1

Tôi đoán câu hỏi ban đầu có thể rõ ràng hơn, nhưng điều tôi muốn là một cách đơn giản để phân phát nội dung từ thư mục cho mục đích dev và thêm tiêu đề để cho phép yêu cầu gốc chéo. Lý tưởng của tôi sẽ giống như 'python -m SimpleHTTPServer --header = Access-Control-Allow-Origin'. Điều đó là không thể, vì vậy bạn phải thực hiện một số mã để làm điều đó. Bạn có thể mở rộng 'SimpleHTTPServer' để thực hiện nhiều việc khác. – nynexman4464

+0

Bạn có thể đăng tiêu đề từ bên trong nội dung được phân phát? Nếu không, bây giờ PHP cung cấp cho nó máy chủ web riêng, do đó bạn không cần phải cài đặt apache. Cho phép bạn kích hoạt nó bằng một thư mục và không có gì khác. Miễn là bạn tìm thấy một giải pháp – Mayhem