Почему якоря в кодировке URI ('#') вызывают 404 и как с этим бороться в JS?

prettyPhoto использует хэштеги, но если они закодированы (до%23), большинство браузеров выдаст ошибку 404. Это обсуждалось ранее:

Вы получаете ошибку 404, потому что часть #callback не является частью URL. Это закладка, используемая браузером, и она никогда не отправляется в запросе на сервер. Если вы закодируете хеш, он вместо этого станет частью имени файла.

  1. Почему хеш становится частью файла только потому, что он закодирован в URI? Разве это не ошибка?

  2. Я спрашиваю, потому что prettyPhoto использует хэштеги и страдает от той же проблемы. Я думаю, добавив '?' прежде чем хеш - самое элегантное решение, я просто немного растерялся, как это сделать в существующем коде:

    function getHashtag () {
    URL =location.href;
    хэштегом =url.indexOf('# галерея') ==-1) decodeURI(url.substring(url.indexOf('# галерея')+1,url.length!)):? ложно;
    вернуть хэштегом;
    }
    function setHashtag(){
    if(typeof theRel=='undefined')return; location.hash=theRel+'/'+rel_index+'/';
    }
    function clearHashtag(){
    если - location.hash="" (location.href.indexOf ('# галерея') == 1!);
    }
  3. Любые другие предложения? Я попытаюсь настроить свою страницу 404, но это скорее похоже на решение проблемы, чем на ее предотвращение.

Спасибо!

РЕДАКТИРОВАТЬ: Поскольку, очевидно, нет ничего плохого в том, как prettyphoto обрабатывает эти хэши, в итоге я добавил эти правила на свой сервер apache:

RewriteRule ^(.*).shtml(%23|#)$ /$1.shtml [R=301,NE,L]
RewriteRule ^(.*).shtml([^g]+)gallery(.+)$ /$1.shtml#gallery$3 [R=301,NE,L]

Они успешно обрабатывают случаи, когда% 23 вызывает проблемы.

2 ответа

Решение
  1. Почему хеш становится частью файла только потому, что он закодирован в URI? Разве это не ошибка?

Если вы указываете свой браузер на http://example.com/index.html#title, браузер интерпретирует это, чтобы сделать запрос на файл index.html с сервера example.com, Когда запрос завершен, браузер ищет в документе элемент привязки с именем title (т.е. <a name="title">My title</a>).

Если вы вместо этого укажите на http://example.com/index.html%23title, браузер делает запрос на файл index.html%23title от example.com, который, вероятно, не существует на сервере, давая вам 404. Видите разницу?

И это не ошибка. Это часть интернет-стандарта, который последний раз обновлялся в 1998 году. См. RFC 2396. Цитирование:

Символ "#" исключен, поскольку он используется для отделения URI от идентификатора фрагмента в ссылках URI (раздел 4).

Что касается 2 и 3, в вашем примере кода недостаточно контекста, чтобы сказать, что вы пытаетесь сделать. Как вы называете свой код? Что вы пытаетесь сделать с Prettyphoto, который не работает? Вы пытаетесь перенаправить на определенную фотографию или галерею от клика пользователя или другого события javascript? Вы пытаетесь открыть галерею, когда кто-то посещает определенную страницу?

Я проверил связанный вопрос с помощью twitter / oauth, но не вижу, как это связано с предоставленным вами кодом. Я тоже начал ковыряться в prettyphoto, но я не понимаю, как ваш код связан с этим.

Вместо того, чтобы менять страницу 404, может быть, вам нужен обработчик кода или правило перезаписи сервера, которое принимает не найденные запросы с %23 в них и перенаправляет пользователя на декодированный URL. Это может иметь некоторые недостатки, но было бы довольно элегантно, если вы принимаете входящие запросы из других источников, которые вы не можете контролировать. Какова ваша серверная среда? (язык, технология сервера, кто владеет машиной и т. д.)

Я был бы рад обновить мой ответ с решением или обходным путем для вас.

Ответить #1)

Он станет частью URL, потому что это больше не токен, который браузер / сервер / и т.д. знает, как анализировать.

Что я имею в виду, это "?" играет значительную роль в URL-адресах - сервер знает, как отделить то, что раньше, от того, что после. Браузеру не нужно заботиться о том, что является или не является динамическим в URI - все это важно (хотя JavaScript разделяет значения в объекте location).

Браузер не будет отправлять "#......" на сервер, поскольку хэштег имеет специальные коннотации для браузера.

Однако, если вы избежите этого хэша в JavaScript, браузер без колебаний отправит эту экранированную строку на сервер в виде буквального значения.

Почему бы и нет? Если в вашем поисковом запросе на законных основаниях требовался хеш-символ (вы отправляете запрос POST на стену Facebook и отправляете номер телефона), то вас обидят. Или вы выполняете GET-поиск по некоторому номеру на 411.com или чем-то еще, и они на самом деле не продумали свое приложение.

Проблема в том, что сервер не поймет, что экранированное значение должно храниться отдельно от URL, если оно встречается в фактическом пути.

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

Так что если вы ищете:

//mysite.gov.on.ca/path/to/file.extension%23action%3Dfullscreen

воистину, ты непременно должен быть 404.

Я уверен, что есть несколько вещей, которые вы могли бы сделать. Первый будет в Apache, или откуда бы вы ни работали, вы могли бы написать RegEx, который соответствует любому URL-адресу вплоть до первого "%23", предполагая, что нет "?" заранее.

Менее душераздирающие реализации могут потребовать выяснения, есть ли способ избежать "#", которые являются дружественными для плагинов.

Например, Google использует стратегию "hash-bang" ("#!"), В которой он запрашивает, чтобы URL-адреса передавались таким образом, чтобы узнать, следует ли кодировать.

Другие варианты могут быть для проверки "#" символа с помощью url.indexOf("#"); и разделение URL-адреса на хеш, и отправка правильной части.

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

Другие вопросы по тегам