在简单的HTTP服务器上启用访问控制


121

对于非常简单的HTTP服务器,我具有以下shell脚本:

#!/bin/sh

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

我想知道我怎么可以启用或添加CORS标题喜欢Access-Control-Allow-Origin: *到这台服务器?

Answers:


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使用SimpleHTTPRequestHandlerHTTPServerhttp.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.SimpleHTTPRequestHandlerBaseHTTPServer模块来运行服务器。

#!/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:无法打开文件'simple-cors-http-server.py':[错误2]没有此类文件或目录注销....有什么想法吗?
MChan 2014年

4
@poke服务器以501不支持的方法(“ OPTIONS”)进行响应。我正在使用Python 2.7.6运行OS X 10.10.1。有什么建议? 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不支持OPTIONS HTTP方法。您可以根据需要添加它(阅读有关HTTP服务器的Python手册);否则您将无法尝试访问服务器。

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,也可以尝试 caddycertbot


您可能会发现有用的一些相关工具

  • ngrok:运行时ngrok http 3000,它将创建一个https://$random.ngrok.com允许任何人访问您的http://localhost:3000服务器的URL 。它可以向世界展示您计算机本地运行的内容(包括本地后端/ API)

  • localtunnel:与ngrok几乎相同

  • 现在:运行时now,它将在线上传您的静态资产并将其部署到https://$random.now.sh。除非您另有决定,否则它们将永远保持在线状态。由于差异,部署速度很快(第一个部署除外)。现在适用于生产前端/ SPA代码部署。它还可以部署Docker和NodeJS应用程序。它不是真正的免费,但他们有免费计划。


4
我是一个简单的人。我看到一个解决方案,要求将其安装npm在仅具有已知功能的计算机上python,我对此表示反对。
Parthian Shot '18

6
@ParthianShot:您可能想学习使用最好的工具来完成工作。
Dan Dascalescu

2
@ParthianShot许多开发人员已经安装了node / npm。问题标题具有足够的通用性,可以吸引大量显然不关心python或SimpleHTTPServer的用户,这一点得到了投票的证实。这并不是因为它对所有人都没有帮助。有充分的理由不同时喜欢Node和Python。像leftpad /糟糕的发布/坏的git使用之类的事情似乎与我完全无关。
Sebastien Lorber '18

5
添加其他语言和框架会招致技术负担,增加环境的攻击面。“在任何编程语言中都可能发生致命错误”,是的,但是JS比大多数其他语言都更容易做到这一点。每种语言都有陷阱;使用的语言越少,一些不熟悉其中一种语言的开发人员犯错误的可能性就越小,而这不是另一种语言的错误。
Parthian Shot

2
这就像您每次需要在房子周围寻求帮助时都收养孩子一样;它带来的问题多于解决方案。
Parthian Shot '18

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()实例(如果选择支持HEAD操作,则需要提供do_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知识,我只是将上面提到的shell脚本用作Emberjs应用程序的简单http服务器。仅当遇到访问控制问题时,我才研究发现需要在此简单的http服务器中启用它。因此,在进行了一些研究之后,我添加了(启用“ CrossOrigin”,origins =>'*';),但并不奇怪,它没有起作用。如果可以的话,请指向任何包含访问控制功能的Python简单的HTTP服务器Shell脚本,我们将不胜感激
MChan 2014年

略微说一下,我并不是真的想在这里偷懒,但是开始学习python只是为了将此功能添加到simpleHTTP服务器在这一点上听起来不合逻辑,所以我希望添加起来很容易,或者希望我能找到一个可以完成这项工作的替代/现成的Python脚本,这样我就可以继续进行我的开发工作
MChan

3
SimpleHTTPServer没有支持访问控制的选项。您需要滚动自己的代码-或切换到另一个支持访问控制的Web服务器。想想lighttpd.net
2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.