在反向代理(traefik)后面使用phyton的http.server时获取“ 404”

时间:2019-08-14 08:56:13

标签: python docker traefik

当前,我正在尝试设置一个简单的Web服务。为此,我使用了phyton3 http.server类。整个过程都在Docker容器中运行(称为simple_webservice;暴露端口8010)。

运行没有traefik的容器时,我可以通过调用http://localhost:8010来访问网站。

我用于实现网络服务器的代码可以在here中找到:

import http.server
import socketserver

PORT = 8010
Handler = http.server.SimpleHTTPRequestHandler

with socketserver.TCPServer(("", PORT), Handler) as httpd:
    print("serving at port", PORT)
    httpd.serve_forever()

泊坞窗文件也很简单(代理用于通过apt-get下载):

FROM ubuntu:latest

ENV http_proxy 'http://proxy:port'
ENV https_proxy 'http://proxy:port'
ENV no_proxy 'company.net'

RUN apt-get update &&   apt-get install -y \
                        build-essential \
                        python3 
RUN mkdir /www
COPY ext/ /www
ADD ./entrypoint.sh /entrypoint.sh
ADD server.py /www/server.py
RUN chmod +x /entrypoint.sh

ENTRYPOINT [ "./entrypoint.sh"]

这是我的docker-compose.yml文件,用于将我的容器与traefik反向代理一起使用:

version: '3'

services:
  simple_webservice:
    build: .
    image: "simple_webservice"
    expose:
      - 8010
    networks:
      - internal_network
      - default
    labels:
      - traefik.passHostHeader=true
      - traefik.docker.network=internal_network
      - traefik.enable=true
      - traefik.backend=simple_webservice
      - traefik.frontend.rule=PathPrefix:/webservice
      - traefik.port=8010

networks:
  internal_network:
    external: true

现在,通过调用http://localhost/webservice访问相同的Web服务时,它总是返回:
错误响应
错误代码:404
消息:找不到文件。
错误代码说明:HTTPStatus.NOT_FOUND-没有与给定URI匹配的内容

所以我认为我的服务仍然可以访问并且traefik正常运行,但是我的网络服务器无法处理路径前缀 / webservice ? 我该如何解决?


编辑: 通过发布解决方法来回答。

2 个答案:

答案 0 :(得分:0)

如果/webservice仅在前端公开,则可以使用the stripprefix middleware in Traefik删除它。请注意,这可能会中断绝对中断,并且会导致应用程序中的某些相对重定向和链接(即/foo将不再指向您的前端服务的端点)。

# Strip prefix /foobar and /fiibar
labels:
- "traefik.http.middlewares.test-stripprefix.stripprefix.prefixes=/foobar, /fiibar"

您可以根据需要使用X-Forwarded-Prefix标头为这些路径添加前缀。

  

可以查询X-Forwarded-Prefix标头来动态构建此类URL。

但是,我的建议是通常将您的WSGI应用程序(通常在Python中最终使用)安装在多个端点中,以便在必要时与其自己的URL建立适当的关系。这样,大多数事情都可以同时使用前缀和不使用前缀(直接访问时)。如何执行将取决于所使用的框架。

答案 1 :(得分:0)

解决方法

我找到了解决此问题的方法。但是,这不是一般的解决方案。 (正如我的Dockerfile所说,我在 / www / 中进行操作。)

背景

(重新)加载网页时,将调用do_GET()方法,该方法将调用send_head()

现在,send_head()中有一个可变路径;使用traefik时,变量path(在第66行分配) path = self.translate_path(self.path) 在我的情况下存储 / www / webservice ,这不是有效路径(仅 / www / 是有效的。)

(不良)解决方案

所以,我的解决方法是通过简单地添加以下行来删除 / www /...之后的内容 path = path.replace('/webservice', '')。现在,我的路径再次有效。

请注意,这只是一种解决方法。我猜有一种更可行的方法,无需更改SimpleHTTPServer.py源文件,但我还没有找到一种方法。 send_head(self)方法如下所示:

def send_head(self):
  path = self.translate_path(self.path)
  path = path.replace('/webservice', '')
  f = None
  if os.path.isdir(path):
    parts = urllib.parse.urlsplit(self.path)
    [...]

我也希望能为我的问题提供一个更通用的解决方案。