简体   繁体   English

历史记录API,刷新和书签

[英]History API, refresh and bookmark

pushState doesn't make a request, it just changes the url and stores a new history entry. pushState不会发出请求,它只是更改URL并存储新的历史记录条目。 Thinking about this concept, it's impossible to refresh or bookmark because the server will always do a request. 考虑到这个概念,由于服务器将始终执行请求,因此无法刷新或添加书签。 A server-side solution is needed. 需要服务器端解决方案。
After several hours searching, I have found a solution, every single call must be redirect to index.php to let PHP handle the request. 经过几个小时的搜索,我找到了一个解决方案,每个调用都必须重定向到index.php以使PHP处理请求。

rewrite ^/(.*)$ /index.php?page=$1 last

I don't know exactly how this file should be to let a website refresh or bookmark a page. 我不确切知道该文件应如何让网站刷新或为页面添加书签。 Can somebody help me ? 有人可以帮我吗? I made an example to help clarify. 我举了一个例子来帮助澄清。


index.html index.html

<!DOCTYPE html>

<html>
    <head>
        <meta charset = "utf-8">

        <title>History API</title>

        <script>
            function ajax (url, callback) {
                var conection = new XMLHttpRequest ();

                conection.open ("GET", url, true);

                conection.setRequestHeader ("X-Requested-With", "XMLHttpRequest");

                conection.send (null);

                conection.onreadystatechange = function () {
                    if (conection.readyState === 4) {
                        if (conection.status === 200) {
                            callback (conection.responseText);
                        }
                        else if (conection.status === 404) {
                            alert ("Page not found !");
                        }
                        else {
                            alert ("Error !");
                        }
                    }
                }
            }

            window.addEventListener ("popstate", function (event) {
                var state = event.state;

                if (state) {
                    document.getElementById ("content").innerHTML = state["content"];
                }
            });

            document.addEventListener ("DOMContentLoaded", function () {
                var content = document.getElementById ("content");
                var menu = document.getElementById ("menu");

                menu.addEventListener ("click", function (event) {
                    var target = event.target;

                    if (target.nodeName === "A") {
                        ajax (target.href, function (result) {
                            history.pushState ({"content": result}, target.innerHTML, target.href);

                            content.innerHTML = result;
                        });

                        event.preventDefault ();
                    }
                });
            });
        </script>

        <style>
            body {
                width: 400px;
            }

            div {
                border: 1px solid black;
                padding: 10px;
            }
        </style>
    </head>

    <body>
        <div id = "menu">
            <a href = "page1.html">Page 1</a>
            <a href = "page2.html">Page 2</a>
        </div>

        <div id = "content"></div>
    </body>
</html>

index.php index.php

<?php
    isset ($_GET["page"]) or exit ("Error !");

    $page = $_GET["page"];

    // Ajax request
    if (isset ($_SERVER["HTTP_X_REQUESTED_WITH"]) && strtolower ($_SERVER["HTTP_X_REQUESTED_WITH"]) === "xmlhttprequest") {
        if (file_exists ($page)) {
            require_once ($page);
        }
        else {
            header ("HTTP/1.1 404 Not Found");
        }
    }
    else {
        require_once ("index.html");
    }
?>

page1.html page1.html

Hello, I'm the Page 1. It's nice to meet you. 您好,我是第1页。很高兴认识您。

page2.html page2.html

Hi brother. 嗨,兄弟。 I'm page 2. 我在第2页。


Clicking (ok) 单击(确定)

在此处输入图片说明

Refresh (fails) 刷新(失败)

在此处输入图片说明

First of all you should really not use a GET parameter as input for a _require_once_. 首先,您实际上不应该将GET参数用作_require_once_的输入。 Really. 真。 Not. 不。 Use at least a simple whitelist of allowed names for pages and only include and output mapped files (or files with those whitelisted names). 至少对页面使用简单的允许名称白名单,并且仅包含和输出映射文件(或具有这些白名单名称的文件)。

Now to your history API problem. 现在到您的历史记录API问题。 Pushing things obviously seems to work for you so all that is missing is probably a simple ondomready event that reads the current URL and loads the content via AJAX or from existing history entries. 推送显然对您似乎有用,因此丢失的可能只是一个简单的ondomready事件,该事件读取当前URL并通过AJAX或从现有历史记录条目中加载内容。 The same whitelist approach should be used there. 此处应使用相同的白名单方法。 Also try to not fall into the trap of DOMXSS by using unvalidated input (the URL) as input for your javascript and DOM operations. 也请尝试通过使用未经验证的输入(URL)作为您的javascript和DOM操作的输入,以免落入DOMXSS的陷阱。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM