Сделать браузер отправить дополнительный HTTP-заголовок, если нажать на гиперссылку

есть ли способ заставить webbrowser отправить дополнительный HTTP-заголовок, если пользователь нажимает на ссылку?

фон: в нашей среде каждый HTTP-запрос имеет уникальный ID на стороне сервера. См.https://serverfault.com/questions/797609/apache-x-request-id-like-in-heroku

Если ваше веб-приложение получает HTTP-запрос, я хотел бы знать, какая страница была страницей раньше. Http-реферера недостаточно, так как пользователь может использовать несколько вкладок в браузере.

Я хотел бы избежать, чтобы поместить уродливый запрос-id в каждый запрос GET, который отправляется из браузера на сервер. До сих пор наши URL-адреса хороши.

моим предпочтительным решением будет магия JavaScript, которая добавляет идентификатор запроса текущей страницы в следующий http-запрос.

шаги подробно:

  1. URL доступа к браузеру http://example.com/search
  2. web сервер получает http-запрос с идентификатором запроса 123
  3. веб-сервер отправляет содержимое URL-адреса в браузер (страница поиска). Страница содержит запрос ID 123 somewhere
  4. пользователь ищет "foobar".
  5. веб-браузер отправляет http-запрос на сервер и каким-то образом включает предыдущий идентификатор запроса.
  6. веб-сервер получает второй http-запрос (ID 456) и может получить доступ к значению первого запроса (ID 123) как-то.
  7. веб-сервер может хранить отношение "123 -- > 456" в базе данных для последующего анализа.

моя цель-отслеживать отношения "123 -- > 456". Выше решение - это просто стратегия, чтобы добраться до цели. Приветствуются и другие стратегии.

мы используем веб-фреймворк django. Но AFAIK это имеет значение в этом контексте.

пользователь может использовать несколько вкладок в своем браузере

я уточняю, что это означает для соответствующее решение. Последовательность запросов, поступающих от одного пользователя, не решает проблему.

использовать с несколькими вкладками:

  1. пользователь смотрит на страницу A в tab1
  2. пользователь смотрит на страницу B в tab2
  3. пользователь следует по ссылке на странице A на страницу c
  4. пользователь следует по ссылке на странице C на страницу D
  5. пользователь следует по ссылке на странице B (таб2) на страницу E.

Я хочу знать, видеть двух последовательности:

A -> C -> D

и

B -> E

4 ответов


единственный современный "нормальный" вариант здесь-использовать ServiceWorker.

ServiceWorker может перехватывать HTTP-запросы для домена, которым вы управляете, и украшать его дополнительными заголовками.

ServiceWorker работает " вне " вкладки браузера, и если несколько вкладок открыты с одним и тем же веб-сайтом, один и тот же serviceworker будет использоваться для всех из них.

полный учебник о том, как это сделать, безусловно, слишком много для этого окна ответов, но перехват и выполнение материал с HTTP-запросами является большим прецедентом, поэтому источники за пределами сайта обычно будут иметь это в качестве примера.

Я бы сказал, что это плохая идея. Если вы думаете, что вам это нужно, возможно, вы можете справиться с этим по-другому. Распространенным способом сделать это может быть использование cookies.


мы можем изменить заголовки запросов, используя:

  • .setRequestHeader () метод объекта XMLHttpRequest () (в том же или разрешенные источники).
  • редактирование заголовков в консоли браузера или использование некоторого дополнения (это не практично).
  • выполнение запроса со стороны сервера e.g используя CURL, wget или некоторую библиотеку (клиент->serverProxy->url с пользовательскими заголовками ).

это не возможно (с помощью javascript) изменить заголовки, отправленные браузером в запросе типа <a href=""></a> потому что, по крайней мере, теперь согласование содержимого http является внутренней возможностью браузера (за исключением части использования XMLHttpRequest в same или разрешенные источники).

тогда, на мой взгляд, как сказал @Evert, у вас есть два практических способа (третий на самом деле) для достижения вашей цели, выполняя прокси-сервер или Используя cookies. Здесь у вас есть очень простой способ, используя на <a> такой:

<a href="https://www.google.com/" ping="trackPing.py">Link to track</a>

ping содержит разделенный пробелом список URL-адресов, к которым, когда этот гиперссылка следовать, запросы столба с телом пинг будет отправлен в браузере (в фоновом режиме). Обычно используется для отслеживания.

Откройте консоль - > сеть, удалите все, запустите фрагмент и нажмите на ссылку, если Ваш браузер поддерживает его, вы увидите, что браузер отправляет запрос POST в trackPing.py (Я думаю, не существует в SO), этот пост пуст, но вы можете отслеживать переменные среды, такие как request.environ['REMOTE_ADDR'] или что-то в этом роде.


прежде всего, извините за мой английский.

Edit:

после прочтения вашего редактирования, я понял, что мой ответ не подходит, из-за вкладок.

невозможно изменить непосредственно способ, которым браузер делает запрос get. Зная это, ваши возможности таковы:

  • используйте GET параметры. Я знаю, ты пытаешься избежать этого.
  • как сказал @Evert, используйте ServiceWorkers. Это самый чистый способ изменить запрос, прежде чем он покинет браузер.
  • последний подход (простой) похож на @Emeeus, но вместо использования localStorage, значения которых разделяются между вкладками,вы должны использовать sessionStorage, значения которого независимы от табуляции. Кроме того, вместо того, чтобы хранить весь маршрут, вы должны хранить только случайный идентификатор. Этот идентификатор будет работать как идентификация цепочки запросов для конкретной вкладки. Затем, как только ваш веб-сервер возвращает each используя <meta name="request_id" content="123" /> вам просто нужно сделать запрос через ajax к определенной конечной точке отслеживания и сохранить:
    • chain_id (хранится в sessionStorage)
    • идентификатор_запроса (хранится в голове > meta)
    • метка (генерируется на веб-сервере)
    • идентификатора session_id (доступно с веб-сервера). Вы можете избежать этого, но это все еще полезно для проверки цели.

запрос на сохранение маршрута выполняется после загрузки страницы, а не до. Этот подход очень похож на то, как работает Analytics.

// generate an unique code and store it in sessionStorage.
if (!sessionStorage.getItem('chain_id')) { 
    sessionStorage.setItem('chain_id', 'a7835e0a-3ee9-e981-...');
}

// Then, if you use JQuery:
$(document).ready(function() {
    $.ajax({
        type: "POST",
        url: 'your/tracking/endpoint/',
        data: {
            'chain_id': sessionStorage.getItem('chain_id'),
            'request_id': document.querySelector("meta[name='request_id']").getAttribute('content'),
        }
    });
});

Примечание: предпочтительно не использовать JQuery для обработки запросов отслеживания и не ждать, пока документ не будет полностью загружен. Это просто пример.

и это все. у вас есть отношение между user-agent, цепочкой, запросом и временная метка запроса, поэтому, если вам нужно знать, какой запрос был сделан до или после данного, вам просто нужно искать в базе данных с помощью Chain-ID и отметка времени в качестве фильтров.

модель django для ваших запросов может быть.

from django.db import models
from django.contrib.sessions.models import Session


class Request(models.Model):
    session = models.ForeignKey(Session)
    chain_id = models.Charfield(max_length=100)
    request_id = models.WhatEverField...
    request_url = models.URLField(max_length=200)
    created = models.DateTimeField(auto_now_add=True)

надеюсь, это поможет.


Я не знаю, поможет ли это, но я думаю, может быть, Ajax сделает, например, установите дополнительный заголовок внутри прослушивателя событий onclick, как для идентификатора запроса, если это не что-то чувствительное, вы можете использовать cookie для контейнера или, возможно, что-то намного лучше ...