跨域请求

2018-05-24  本文已影响84人  SingleDiego

参考原文

知识点:




跨域指的是 JavaScript 通过 XMLHttpRequest 请求数据时,调用 JavaScript
的页面所在的域和被请求页面的域不一致。对于网站来说,浏览器出于安全考虑是不允许跨域。另外,对于域相同,但端口或协议不同时,浏览器也是禁止的。下表给出了进一步的说明:

URL 说明 是否允许请求
http://a.example.com/http://a.example.com/a.txt 同域下 允许
http://a.example.com/http://a.example.com/b/a.txt 同域下不同目录 允许
http://a.example.com/http://a.example.com:8080/a.txt 同域下不同端口 不允许
http://a.example.com/https://a.example.com/a.txt 同域下不同协议 不允许
http://a.example.com/http://b.example.com/a.txt 不同域下 不允许
http://a.example.com/http://a.foo.com/a.txt 不同域下 不允许

但这个规则如果同样限制 Chrome 扩展应用,就会使其能力大打折扣,所以
Google 允许 Chrome 扩展应用不必受限于跨域限制。但出于安全考虑,需要在 Manifest 的 permissions 属性中声明需要跨域的权限。

比如,如果我们想设计一款获取维基百科数据并显示在其他网页中的扩展,就要在 Manifest 中进行如下声明:

{
    ...
    "permissions": [
        "*://*.wikipedia.org/*"
    ]
}

这样Chrome就会允许你的扩展在任意页面请求维基百科上的内容了。

我们可以利用如下的代码发起异步请求。(详细 ajax 操作参见:原生 Javascript 收发 AJAX

function httpRequest(url, callback){
    var xhr = new XMLHttpRequest();
    xhr.open("GET", url, true);
    xhr.onreadystatechange = function() {
        if (xhr.readyState == 4) {
            var resp = JSON.parse(xhr.responseText);
            callback(resp);
        }
    }
    xhr.send();
}




鉴于原教程的网址早不提供服务了,下面来写一个新的小 Demo,利用异步请求原来写一个向豆瓣 API 查询图书信息的插件。

编写 manifest.json

{
    "manifest_version": 2,
    "name": "ISBN查询",
    "version": "1.0",
    "description": "根据ISBN查询书目信息",
    "icons": {
        "16": "images/icon.png",
        "48": "images/icon.png",
        "128": "images/icon.png"
    },

    "browser_action": {
        "default_icon": {
            "19": "images/icon.png",
            "38": "images/icon.png"
        },
        "default_title": "ISBN查询",
        "default_popup": "popup.html"
    },
    // 设置权限
    "permissions": [
        "*://api.douban.com/v2/book/isbn/*"
    ]
}

上面的 Manifest 定义了这个扩展允许对 "*://api.douban.com/v2/book/isbn/*"
发起跨域请求。

popup.html 的结构也完全可以按照时钟的扩展照抄下来,只是个别元素的 id 和脚本的路径根据当前扩展的名称稍加更改,不再赘述。

<html>

<head>
    <style>
    * {
        margin: 0;
        padding: 0;
    }

    body {
        width: 250px;
        height: 300px;
    }

    div {
        line-height: 50px;
        font-size: 20px;
        /*text-align: center;*/
    }
    </style>

</head>

<body>
    <div>
        <h4>ISBN: <input type="text" name="ISBN", id="ISBN"></h4>
    </div>
    
    <div>
        <h4 id="title">Title:</h4>
    </div>

    <br>

    <div>
        <button id="search">search</button>
    </div>

    <script src="js/isbn.js"></script>
</body>

</html>

下面编写 my_ip.js

// 对某 url 发起异步请求,接收返回的数据传给回调函数执行
function httpRequest(url, callback){
    var xhr = new XMLHttpRequest();
    xhr.open("GET", url, true);
    xhr.onreadystatechange = function() {
        if (xhr.readyState == 4) {
            var resp = JSON.parse(xhr.responseText);
            callback(resp);
        }
    }
    xhr.send();
}


var search = function() {
    var isbn = document.getElementById('ISBN').value // 获取输入框的 isbn 值
    var url = 'https://api.douban.com/v2/book/isbn/' + isbn // 构建豆瓣 api 的 url

    httpRequest(url=url, function(r) {
        // 把返回的数据显示在相应位置
        var title = r['title']
        document.getElementById('title').innerHTML = 'Title: ' + title
    })
}

// 选择到按钮
var search_button = document.getElementById("search")

// 把相关函数和点击按钮事件绑定
search_button.addEventListener("click", function(){
    search()
})

调试运行:


上一篇下一篇

猜你喜欢

热点阅读