Implementation examples in django

I think our tdm proposal is already at a good point so it is time to start fiddling with real code. I would like to share these comments to see if I've understood the proposal correctly. In case you want to see the files without reading the django tutorial, let me know and I will upload them to github.

proposal-http-headers

I start from the django tutorial to discuss a few examples of tdm implementation. I've prepared a small server with the files described in that tutorial (https://docs.djangoproject.com/en/3.2/intro/tutorial01/), that you can reach at http://207.154.202.197/polls/.
This comment is something that you add to at the end of tutorial 3, https://docs.djangoproject.com/en/3.2/intro/tutorial03/, or better at the section devoted to changing/adding headers to response https://docs.djangoproject.com/en/3.2/ref/request-response/#setting-header-fields.

This is a simple view function (in the file views.py inside the app "polls" developed in the tutorial)

def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    context = {
        'latest_question_list': latest_question_list,
    }
    resp = render(request, 'polls/index.html', context)
    # TDM headers
    resp['tdm-reservation'] = 2
    resp['tdm-policy'] = 'http://example.com/license'
    return resp

Using "web developer tools" in your browser, you can check the response headers.
If you want to add the same header all at once in all pages, in a file inside the app (e.g. middleware.py) define a class like this:

class MyMiddleware:

    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)
        response['tdm-reservation'] = 2 # or 1
        response['tdm-policy'] = "'
http://127.0.0.1:8000/polls/license
'" # or leave it empty or delete the line
        return response

and register the class in settings.py in the section MIDDLEWARE :

MIDDLEWARE = [
    ...
    'polls.middleware.MyMiddleware',
]

As what regards images, likely the best solution is using FileResponse (but I've not checked if you can simply use HttpResponse)

from django.http import FileResponse

def send_file(response):
    img = open('media/hello.jpg', 'rb')
    response = FileResponse(img)
    response['tdm-reservation'] = 2
    response['tdm-policy'] = "'http://127.0.0.1:8000/polls/license'"
    return response

or, if you like and are in the mood, you can check X-sendfile directly in the web server:

https://pythonhosted.org/xsendfile/howto.html#integration-in-your-application

There is a little drawback. If you go to http://207.154.202.197/polls and APPEND_SLASH = False in settings.py, you will receive a status code 301 and you'll loose all custom headers. There is a way to get both 200 and 301 status code with this nginx setup:

location / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn.sock;
        proxy_pass_request_headers on;
    }

Remember that you'll receive the custom headers only when the status code is 200, so you should check the 200 response, leaving apart 301.

proposal-file-at-origin

Producing a json file is sort of easy job. Add this function, always in views.py inside polls app:

def tdm(request):
    data = {
    1: {
          "location": "/directory-a",
          "tdm-reservation": 1
          },
    2: {
          "location": "/directory-b/html",
          "tdm-reservation": 2,
          "tdm-policy":"https://example.com/tdm-licenses/license-a"
          },
    3: {
          "location": "/directory-b/images/*.jpg",
          "tdm-reservation": 0
          }
    }
    return JsonResponse(data)

then add to urls.py the route to the file

from django.urls import path, include
from polls.views import tdm

urlpatterns = [
    ...

    path('.well-known/tdmrep.json', tdm, name="tdm"),
]

In this way all web resources are manually managed, I mean it is possible to build an app to manage them all: adding url, changing tdm when necessary, etc.

Conclusions

Using django, one of the two major characters in this play - the other being wordpress, both solutions (headers and a single file in a known position) are technically viable, with a slightly preeminence of that based on a file. I think using headers is not so robust as it appears but this consideration requires a bit more experience than mine on this subject matter.

=======================
Claudio Tubertini
Almalibri.it
mob +39 327 1503898

Received on Thursday, 24 June 2021 08:18:42 UTC