API 端点的 Django 子域配置

kst*_*tis 5 python django subdomain url nginx

我已经建立了一个 Django 项目,它利用django-rest-framework来提供一些 ReST 功能。网站和其他功能都运行良好。

然而有一个小问题:我需要我的 API 端点指向不同的子域

例如,当用户访问网站时,他/她可以根据我的正常导航urls.py

http://example.com/control_panel
Run Code Online (Sandbox Code Playgroud)

到目前为止,一切都很好。然而,当使用 API 时,我想将其更改为更合适的东西。因此,http://example.com/api/tasks我需要将其变为:

http://api.example.com/tasks
Run Code Online (Sandbox Code Playgroud)

我该怎么做呢?

提前致谢。

PS 该网站将在 Gunicorn 上运行,并使用 nginx 作为反向代理。

小智 4

我对基于 Django 的 API 也有类似的问题。我发现编写自定义中间件类并使用它来控制在哪些子域上提供哪些 URL 很有用。

Django 在提供 URL 时并不真正关心子域,因此假设您的 DNS 设置为 api.example.com 指向您的 Django 项目,那么 api.example.com/tasks/ 将调用预期的 API 视图。

问题是 www.example.com/tasks/ 也会调用 API 视图,而 api.example.com 将在浏览器中提供主页。

因此,一些中间件可以检查子域是否与 URL 匹配,并在适当的情况下引发 404 响应:

## settings.py

MIDDLEWARE_CLASSES += (
    'project.middleware.SubdomainMiddleware',
)


## middleware.py

api_urls = ['tasks']  # the URLs you want to serve on your api subdomain

class SubdomainMiddleware:
    def process_request(self, request):
        """
        Checks subdomain against requested URL.

        Raises 404 or returns None
        """
        path = request.get_full_path()  # i.e. /tasks/
        root_url = path.split('/')[1]  # i.e. tasks
        domain_parts = request.get_host().split('.')

        if (len(domain_parts) > 2):
            subdomain = domain_parts[0]
            if (subdomain.lower() == 'www'):
                subdomain = None
            domain = '.'.join(domain_parts[1:])
        else:
            subdomain = None
            domain = request.get_host()

        request.subdomain = subdomain  # i.e. 'api'
        request.domain = domain  # i.e. 'example.com'

        # Loosen restrictions when developing locally or running test suite
        if not request.domain in ['localhost:8000', 'testserver']:
            return  # allow request

        if request.subdomain == "api" and root_url not in api_urls:
            raise Http404()  # API subdomain, don't want to serve regular URLs
        elif not subdomain and root_url in api_urls:
            raise Http404()  # No subdomain or www, don't want to serve API URLs
        else:  
            raise Http404()  # Unexpected subdomain
        return  # allow request  
Run Code Online (Sandbox Code Playgroud)