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

184

我有一个非常简单的HTTP服务器的Shell脚本:

#!/bin/sh

echo "Serving at http://localhost:3000"
python -m SimpleHTTPServer 3000
我想知道如何在这个服务器上启用或添加类似于Access-Control-Allow-Origin: *CORS标头
我想知道如何在这个服务器上启用或添加类似于 Access-Control-Allow-Origin: * 的CORS标头。

3
我喜欢这个简单服务器,使用它的重点可能就是为了提供服务,因为你无法使用本地文件,却需要进行配置。 - Andrew
6个回答

275

不幸的是,简单的HTTP服务器真的很简单,它不允许任何自定义,特别是它发送的标头。不过你可以使用SimpleHTTPRequestHandler的大部分内容创建一个简单的HTTP服务器,并添加所需的标头。

为此,只需创建一个文件simple-cors-http-server.py(或其他名称),根据你所使用的Python版本,在其中加入以下代码之一。

然后你就可以运行python simple-cors-http-server.py 来启动修改后的服务器,它将为每个响应设置CORS标头。

使用顶部的shebang,使文件可执行并将其放入PATH中,你也可以使用simple-cors-http-server.py来运行它。

Python 3解决方案

Python 3使用SimpleHTTPRequestHandlerHTTPServer来运行服务器,它们都来自于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.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)

6
服务器回复 501 Unsupported method ('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
3
SimpleHTTPRequestHandler不支持OPTIONS HTTP方法。如果您想要支持它,可以添加代码(请参阅Python手册中有关HTTP服务器的内容);或者您可以直接避免尝试以那种方式访问服务器。 - poke
2
这看起来很不错,但它还能正常工作吗?我刚试了一下,我的Chrome在控制台中一直报错。 - Rho Phi
5
你可能遇到了预检请求,需要正确实现OPTIONS方法。对于普通请求,只发送Access-Control-Allow-Origin头部的解决方案仍然有效。 - poke
1
@Friedrich--СлаваУкраїні 原始的 test(https://github.com/python/cpython/blob/v3.11.2/Lib/http/server.py#L1246)设置了实际的服务器和命令行处理。当您直接运行 http.server 模块时,它是默认的入口点。我在这里只是重用了这个确切的功能,以避免自己编写实现。 - poke
显示剩余11条评论

170

尝试使用像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


编辑于2022年:我现在最喜欢的解决方案是serve,Next.js内部使用。

只需运行npx serve --cors


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

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

  • localtunnel:与ngrok几乎相同

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


24
我是一个简单的人。我看到需要在一台只安装了Python的机器上安装npm的解决方案,我会反对它。 - Parthian Shot
15
@ParthianShot: 你可能需要学会使用最适合工作的最佳工具。 - Dan Dascalescu
6
我知道如何使用最适合工作的工具。这就是为什么我从未在生产机器上安装过npm,也不打算这样做。当我想要解决像HTTP服务器上的CORS标头这样的简单问题时,我特别不会每次都安装新的语言或包管理器。但无论如何... OP 熟悉 Python,并要求提供 Python 解决方案。因此,根据定义,“合适的工具”就是 Python。 - Parthian Shot
10
添加额外的语言和框架会带来技术债务和增加环境的攻击面。"在任何编程语言中都可能发生致命错误",但是JS比大多数其他语言更容易出现这种情况。每种语言都有陷阱;使用的语言越少,就越不可能有一些不熟悉某种语言的开发人员犯下在另一种语言中不会犯的错误。 - Parthian Shot
11
这就像每次你需要家务帮助时收养一个孩子一样,这会在未来制造更多问题而不是解决问题。 - Parthian Shot
显示剩余6条评论

8
我遇到了同样的问题,并找到了这个解决方案:

我遇到了同样的问题,并找到了这个解决方案:

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方法。


4
尝试这个:https://github.com/zk4/livehttp,支持CORS。
python3 -m pip install livehttp

前往您的文件夹,然后运行livehttp。就这么简单。

http://localhost:5000


2

您需要提供自己的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服务器中启用它。因此,在一些研究之后,我添加了(enable 'CrossOrigin',origins => '*'),但并不奇怪它没有起作用。如果您可以指向任何包含访问控制功能的Python简单http服务器shell脚本,那将不胜感激。 - MChan
在一个次要的注意事项上,我并不是真的想偷懒,但仅仅为了添加这个功能到simpleHTTP服务器而开始学习Python在这一点上似乎不太合理,所以我希望它可以很容易地被添加,或者希望我能找到一种替代/现成的Python脚本来完成这项工作,以便我可以继续我的开发工作。 - MChan
3
SimpleHTTPServer没有支持访问控制的选项。你需要编写自己的代码,或者切换到另一个支持访问控制的Web服务器。可以考虑使用http://www.lighttpd.net/。 - user590028
1
对于采用这种方法的任何人,如果您希望支持“非简单”的CORS请求(需要“preflight”权限的请求),您需要实现一个do_OPTIONS方法,该方法返回一个204响应和以下标头:'Access -Control-Allow-Origin','Access-Control-Allow-Methods'和'Access-Control-Allow-Headers'。 - Roger Heathcote
1
正如@RogerHeathcote所指出的那样,do_OPTIONS方法可以工作,但要小心,因为只要缺少允许的标头就可能会使您的请求被放弃...就像当您发出部分请求并且不允许范围标头时一样(我花了一段时间才找到这一点)。self.send_header("Access-Control-Allow-Headers", "range, accept, accept-encoding, authorization, content-type, dnt, origin, user-agent, x-csrftoken, x-requested-with") - pawel lukaszewicz

1

我的工作代码:

self.send_response(200)
        self.send_header( "Access-Control-Allow-Origin", "*")
        self.end_headers()
        self.wfile.write( bytes(json.dumps( answ ), 'utf-8'))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接