เปิดใช้งานการควบคุมการเข้าถึงบนเซิร์ฟเวอร์ HTTP แบบง่าย


122

ฉันมีเชลล์สคริปต์ต่อไปนี้สำหรับเซิร์ฟเวอร์ HTTP ที่เรียบง่ายมาก:

#!/bin/sh

echo "Serving at http://localhost:3000"
python -m SimpleHTTPServer 3000

ฉันสงสัยว่าฉันจะเปิดหรือเพิ่มส่วนหัว CORSเช่นAccess-Control-Allow-Origin: *เซิร์ฟเวอร์นี้ได้อย่างไร?

คำตอบ:


197

น่าเสียดายที่เซิร์ฟเวอร์ HTTP ธรรมดานั้นเรียบง่ายมากจนไม่อนุญาตให้มีการปรับแต่งใด ๆ โดยเฉพาะอย่างยิ่งไม่ใช่สำหรับส่วนหัวที่ส่ง อย่างไรก็ตามคุณสามารถสร้างเซิร์ฟเวอร์ HTTP แบบธรรมดาได้ด้วยตัวเองโดยใช้ส่วนใหญ่SimpleHTTPRequestHandlerและเพิ่มส่วนหัวที่ต้องการ

เพียงแค่สร้างไฟล์simple-cors-http-server.py(หรืออะไรก็ได้) และขึ้นอยู่กับเวอร์ชัน Python ที่คุณใช้ให้ใส่หนึ่งในโค้ดต่อไปนี้

จากนั้นคุณสามารถทำได้python simple-cors-http-server.pyและจะเปิดเซิร์ฟเวอร์ที่แก้ไขของคุณซึ่งจะตั้งค่าส่วนหัว CORS สำหรับทุกการตอบสนอง

ด้วยshebangที่ด้านบนทำให้ไฟล์สามารถเรียกใช้งานได้และใส่ลงใน PATH ของคุณและคุณสามารถเรียกใช้โดยใช้simple-cors-http-server.pyเช่นกัน

โซลูชัน Python 3

Python 3 ใช้SimpleHTTPRequestHandlerและHTTPServerจากhttp.serverโมดูลเพื่อรันเซิร์ฟเวอร์:

#!/usr/bin/env python3
from http.server import HTTPServer, SimpleHTTPRequestHandler, test
import sys

class CORSRequestHandler (SimpleHTTPRequestHandler):
    def end_headers (self):
        self.send_header('Access-Control-Allow-Origin', '*')
        SimpleHTTPRequestHandler.end_headers(self)

if __name__ == '__main__':
    test(CORSRequestHandler, HTTPServer, port=int(sys.argv[1]) if len(sys.argv) > 1 else 8000)

โซลูชัน Python 2

Python 2 ใช้SimpleHTTPServer.SimpleHTTPRequestHandlerและBaseHTTPServerโมดูลเพื่อเรียกใช้เซิร์ฟเวอร์

#!/usr/bin/env python2
from SimpleHTTPServer import SimpleHTTPRequestHandler
import BaseHTTPServer

class CORSRequestHandler (SimpleHTTPRequestHandler):
    def end_headers (self):
        self.send_header('Access-Control-Allow-Origin', '*')
        SimpleHTTPRequestHandler.end_headers(self)

if __name__ == '__main__':
    BaseHTTPServer.test(CORSRequestHandler, BaseHTTPServer.HTTPServer)

โซลูชัน Python 2 & 3

หากคุณต้องการความเข้ากันได้สำหรับทั้ง Python 3 และ Python 2 คุณสามารถใช้สคริปต์หลายภาษานี้ซึ่งใช้ได้กับทั้งสองเวอร์ชัน ก่อนอื่นจะพยายามนำเข้าจากตำแหน่ง Python 3 และกลับไปที่ Python 2:

#!/usr/bin/env python
try:
    # Python 3
    from http.server import HTTPServer, SimpleHTTPRequestHandler, test as test_orig
    import sys
    def test (*args):
        test_orig(*args, port=int(sys.argv[1]) if len(sys.argv) > 1 else 8000)
except ImportError: # Python 2
    from BaseHTTPServer import HTTPServer, test
    from SimpleHTTPServer import SimpleHTTPRequestHandler

class CORSRequestHandler (SimpleHTTPRequestHandler):
    def end_headers (self):
        self.send_header('Access-Control-Allow-Origin', '*')
        SimpleHTTPRequestHandler.end_headers(self)

if __name__ == '__main__':
    test(CORSRequestHandler, HTTPServer)

ฉันทำตามคำแนะนำ แต่ด้วยการเรียกใช้ python simple-cors-http-server.py ฉันพบข้อผิดพลาด: python: can't open file 'simple-cors-http-server.py': [Errno 2] ไม่มีไฟล์หรือไดเร็กทอรีดังกล่าวออกจากระบบ .... คิดบ้างไหม
MChan

4
@poke เซิร์ฟเวอร์ตอบสนองด้วยวิธี 501 ที่ไม่รองรับ ('OPTIONS') ฉันใช้ OS X 10.10.1 พร้อม Python 2.7.6 ข้อเสนอแนะใด ๆ ? HTTP/1.0 501 Unsupported method ('OPTIONS') Server: SimpleHTTP/0.6 Python/2.7.6 Date: Wed, 21 Jan 2015 23:16:10 GMT Content-Type: text/html Connection: close Access-Control-Allow-Origin: *
HairOfTheDog

1
@HairOfTheDog SimpleHTTPRequestHandler ไม่สนับสนุนวิธี HTTP OPTIONS คุณสามารถเพิ่มได้หากต้องการ (อ่านคู่มือ Python เกี่ยวกับเซิร์ฟเวอร์ HTTP) หรือคุณไม่สามารถพยายามเข้าถึงเซิร์ฟเวอร์เช่นนั้น
โผล่

2
@RobertoFranceschini คุณอาจกำลังพบกับคำขอที่เน้นไว้ล่วงหน้าซึ่งต้องใช้OPTIONSวิธีการอย่างถูกต้อง สำหรับคำขอแบบธรรมดาวิธีแก้ปัญหาในการส่งเฉพาะAccess-Control-Allow-Originส่วนหัวก็ยังคงใช้งานได้ดี
โผล่

1
@ Tyguy7 นั่นอาจเป็นพฤติกรรมทั่วไปกับเซิร์ฟเวอร์ HTTP ธรรมดา ฉันมีผลลัพธ์ที่แตกต่างกันเกี่ยวกับประสิทธิภาพมาก่อน แต่สำหรับการใช้งานเซิร์ฟเวอร์เพียงชั่วครู่ฉันยังถือว่าเป็นวิธีแก้ปัญหาที่เร็วที่สุด
โผล่

108

ลองใช้ทางเลือกอื่นเช่น http-server

เนื่องจาก SimpleHTTPServer ไม่ใช่เซิร์ฟเวอร์ที่คุณปรับใช้กับการใช้งานจริงฉันคิดว่าที่นี่คุณไม่สนใจเครื่องมือที่คุณใช้มากนักตราบใดที่มันทำงานในการเปิดเผยไฟล์ของคุณhttp://localhost:3000ด้วยส่วนหัว CORS ในแบบง่ายๆ บรรทัดคำสั่ง

# install (it requires nodejs/npm)
npm install http-server -g

#run
http-server -p 3000 --cors

ต้องการ HTTPS หรือไม่

หากคุณต้องการ https ในท้องถิ่นคุณสามารถลองใช้แคดดี้หรือใบรับรอง


เครื่องมือที่เกี่ยวข้องบางอย่างที่คุณอาจพบว่ามีประโยชน์

  • ngrok : เมื่อทำงานngrok http 3000จะสร้าง URL https://$random.ngrok.comที่อนุญาตให้ทุกคนเข้าถึงhttp://localhost:3000เซิร์ฟเวอร์ของคุณ มันสามารถแสดงให้โลกเห็นสิ่งที่ทำงานในคอมพิวเตอร์ของคุณ (รวมถึงแบ็กเอนด์ / apis ในเครื่อง)

  • localtunnel : เกือบจะเหมือนกับ ngrok

  • ตอนนี้เมื่อทำงานก็อัปโหลดสินทรัพย์คงที่ของคุณออนไลน์และปรับใช้ให้พวกเขาnow https://$random.now.shพวกเขายังคงออนไลน์ตลอดไปเว้นแต่คุณจะตัดสินใจเป็นอย่างอื่น การทำให้ใช้งานได้รวดเร็ว (ยกเว้นครั้งแรก) ด้วยความแตกต่าง ตอนนี้เหมาะสำหรับการปรับใช้โค้ด frontend / SPA สำหรับการผลิตนอกจากนี้ยังสามารถปรับใช้แอป Docker และ NodeJS มันไม่ฟรีจริง ๆ แต่พวกเขามีแผนฟรี


5
ฉันเป็นคนง่ายๆ ฉันเห็นวิธีแก้ปัญหาที่ต้องติดตั้งnpmบนเครื่องที่รู้ว่ามีเท่านั้นpythonฉันลงคะแนน
Parthian Shot

6
@ParthianShot: คุณอาจต้องการเรียนรู้ที่จะใช้เครื่องมือที่ดีที่สุดสำหรับงานนี้
Dan Dascalescu

2
@ParthianShot นักพัฒนาหลายคนติดตั้ง node / npm ไว้แล้วและชื่อคำถามนั้นกว้างพอที่จะดึงดูดผู้ใช้จำนวนมากที่ไม่สนใจ python หรือ SimpleHTTPServer ซึ่งได้รับการยืนยันจาก upvotes ไม่ใช่เพราะคุณไม่ได้เป็นประโยชน์สำหรับทุกคน มีเหตุผลที่ดีที่จะไม่ชอบทั้ง Node และ Python เช่นกัน สิ่งต่างๆเช่น leftpad / การเผยแพร่ที่ไม่ดี / การใช้งาน git ที่ไม่ดีดูเหมือนจะไม่เกี่ยวข้องกับฉันเลย
Sebastien Lorber

5
การเพิ่มภาษาและกรอบงานเพิ่มเติมก่อให้เกิดหนี้ทางเทคนิคและเพิ่มพื้นผิวการโจมตีของสภาพแวดล้อม "ข้อผิดพลาดร้ายแรงสามารถเกิดขึ้นได้ในภาษาโปรแกรมใดก็ได้" จริง แต่ JS ทำให้วิธีนั้นง่ายกว่าภาษาอื่น ๆ เกือบทั้งหมด และทุกภาษามี gotchas; ยิ่งคุณใช้ภาษาน้อยเท่าไหร่ก็ยิ่งมีโอกาสน้อยที่นักพัฒนาซอฟต์แวร์บางคนที่ไม่คุ้นเคยกับภาษาใดภาษาหนึ่งจะทำผิดซึ่งจะไม่ผิดพลาดในภาษาอื่น
Parthian Shot

2
นี่ก็เหมือนกับการรับเลี้ยงเด็กทุกครั้งที่คุณต้องการความช่วยเหลือในบ้าน มันสร้างปัญหามากกว่าที่จะแก้ตามท้องถนน
Parthian Shot

1

ฉันมีปัญหาเดียวกันและมาที่วิธีแก้ปัญหานี้:

class Handler(SimpleHTTPRequestHandler):
    def send_response(self, *args, **kwargs):
        SimpleHTTPRequestHandler.send_response(self, *args, **kwargs)
        self.send_header('Access-Control-Allow-Origin', '*')

ฉันเพิ่งสร้างคลาสใหม่ที่สืบทอดจาก SimpleHTTPRequestHandler ที่เปลี่ยนsend_responseวิธีการเท่านั้น


0

คุณจะต้องระบุ do_GET () (และ do_HEAD () ของคุณเองหากเลือกที่จะสนับสนุนการทำงานของ HEAD) อะไรทำนองนี้:

class MyHTTPServer(SimpleHTTPServer):

    allowed_hosts = (('127.0.0.1', 80),)

    def do_GET(self):
        if self.client_address not in allowed_hosts:
            self.send_response(401, 'request not allowed')
        else:
            super(MyHTTPServer, self).do_Get()

ขอบคุณสำหรับคำตอบ แต่ฉันไม่มีความรู้เกี่ยวกับ Python เลยฉันแค่ใช้เชลล์สคริปต์ที่กล่าวถึงข้างต้นเป็นเซิร์ฟเวอร์ http ง่ายๆสำหรับแอพ Emberjs ของฉัน เฉพาะเมื่อชนกับปัญหาการควบคุมการเข้าถึงฉันค้นคว้าเพื่อพบว่าฉันจำเป็นต้องเปิดใช้งานในเซิร์ฟเวอร์ http แบบธรรมดานี้ ดังนั้นหลังจากการวิจัยบางอย่างฉันได้เพิ่ม (เปิดใช้งาน 'CrossOrigin', origins => '*';) แต่ไม่น่าแปลกใจที่มันไม่ได้ผล หากคุณสามารถช่วยชี้ฉันไปที่สคริปต์เชลล์ http เซิร์ฟเวอร์ Python แบบง่ายที่มีคุณสมบัติการควบคุมการเข้าถึงที่จะได้รับการชื่นชมอย่างมาก
MChan

ในบันทึกย่อฉันไม่ได้พยายามขี้เกียจที่นี่จริงๆ แต่เริ่มเรียนรู้ python เพียงเพื่อเพิ่มคุณสมบัตินี้ลงในเซิร์ฟเวอร์ simpleHTTP ไม่ได้ฟังดูมีเหตุผลในตอนนี้ดังนั้นฉันหวังว่ามันจะง่ายต่อการเพิ่มหรือหวังว่าฉันจะพบ สคริปต์ Python ทางเลือก / สำเร็จรูปที่สามารถทำงานได้เพื่อให้ฉันทำงานพัฒนาต่อไปได้
MChan

3
SimpleHTTPServer ไม่มีตัวเลือกเพื่อรองรับการควบคุมการเข้าถึง คุณจะต้องม้วนรหัสของคุณเองหรือเปลี่ยนไปใช้เว็บเซิร์ฟเวอร์อื่นที่รองรับการควบคุมการเข้าถึง คิดถึงlighttpd.net
user590028
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.