Nội dung bài viết
Video học lập trình mỗi ngày
JSONP là gì?
JSONP (json with padding) là một phương pháp hay còn gọi là phương tiện giao tiếp giải quyết vấn đề truy cập dữ liệu giữa các domain khác nhau. Do chính sách cùng nguồn gốc chính vì vậy các trang web có thể lấy dữ liệu JSON được tạo động từ các nguồn khác và chế độ sử dụng này được gọi là JSONP. Dữ liệu được thu thập bằng JSONP không phải là JSON, mà là JavaScript tùy ý, được trình thông dịch JavaScript thực thi thay vì được phân tích cú pháp bởi trình phân tích cú pháp JSON.
JSONP và AJAX
Đây có có thể là một khái niệm mới đối với những developer JavaScript(devjs) mới. Vì đại đa số thực hiện việc truy cập dữ liệu giữa các domain khác nhau đều thông qua API và họ sẽ chọn thư viện JQuery với phương pháp AJAX quen thuộc và nhanh chóng. Trong thực tế, trong JavaScript việc thực hiện riêng AJAX không khó nhưng nó có một vấn đề đó là "chính sách không nguồn gốc" của các browser hiện đại ngày nay.
Chính vì vậy nhiều trường hợp chúng ta sẽ bắt gặp những error như thế này.
Access to fetch at 'http://localhost:8080/' from origin 'https://fiddle.jshell.net' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Lỗi trên còn gọi là CORS là một tiêu chuẩn W3C hay còn gọi là Chia sẻ tài nguyên không cùng nguồn gốc.
CORS là gì
CORS yêu cầu cả hỗ trợ trình duyệt và phụ trợ. IE8 và IE9 cần được hiện thực hóa thông qua XDomainRequest
. Browser sẽ tự động thực hiện giao tiếp CORS. CORS có thể được bật bằng cách đặt Access-Control-Allow-Origin ở phía máy chủ. Thuộc tính này cho biết tên miền nào có thể truy cập tài nguyên. Nếu ký tự đại diện được đặt, điều đó có nghĩa là tất cả các trang web có thể truy cập tài nguyên.
Hầu hết ngày nay, một tập lệnh chạy trong browser của người dùng sẽ chỉ cần truy cập các tài nguyên trên cùng một nguồn gốc. Vì vậy, việc JavaScript thường không thể truy cập tài nguyên trên các nguồn gốc khác là một điều tốt cho bảo mật. Những trường hợp xuất hiện lỗi CORS :
- - Khác nhau về phương thức (http hay https)
- - Khác nhau về domain
- - khác nhau về port
Chính vì vậy JSONP ra đời để phục vụ những trường hợp như thế này.
So sánh JSONP và AJAX
JSONP và AJAX giống nhau, cả hai đều là cách mà client gửi yêu cầu đến server và lấy dữ liệu từ server. Nhưng AJAX thuộc về chính sách cùng nguồn gốc và JSONP thuộc về chính sách không nguồn gốc (CORS)
Ưu điểm và nhược điểm của JSONP
JSONP có ưu điểm là đơn giản và tương thích tốt, có thể được sử dụng để giải quyết vấn đề truy cập dữ liệu giữa các miền trong các browser chính. Nhược điểm là chỉ hỗ trợ phương thức get có những hạn chế và không an toàn có thể bị các cuộc tấn công XSS.
Quy trình triển khai JSONP
- - Khai báo hàm callback, có tên hàm (như hiển thị) được sử dụng làm giá trị tham số, được chuyển đến server yêu cầu dữ liệu trên các miền và tham số chức năng là để lấy dữ liệu đích (dữ liệu được server trả về)
- - Tạo thẻ
script src
, gán địa chỉ giao diện dữ liệu API tên miền chéo cho src của tập lệnh và chuyển tên hàm cho server trong địa chỉ này (bạn có thể chuyển tham số qua dấu hỏi? Callback = show). - - Sau khi server nhận được yêu cầu, nó cần thực hiện xử lý đặc biệt: nối tên hàm được truyền vào và dữ liệu cần cung cấp cho bạn thành một chuỗi, ví dụ: tên hàm được truyền vào được hiển thị và dữ liệu mà nó chuẩn bị được hiển thị ('blog JavaScript anonystick.com').
- - Cuối cùng, server trả về dữ liệu đã chuẩn bị cho client thông qua giao thức HTTP và sau đó client gọi hàm callback (hiển thị) được khai báo trước khi thực hiện để vận hành trên dữ liệu được trả về.
Ví dụ về thực hiện JSONP
Ở đây tôi có thực hiện một code tại back-end sử dụng nodejs + expressjs
var express = require('express') var app = express() app.get('/jsonp', function (req, res) { const {callback, wd, from} = req.query; let data = { msg: 'Get data here', word: wd, referer: from, data: [1, 2, 3] }; data = JSON.stringify(data); res.end(callback + '(' + data + ')'); }) app.listen(8080, function () { console.log('App listening on port http://localhost:8080/!') })
Phía client tôi sử dụng https://jsfiddle.net/ để truy cập vào link "http://localhost:8080/jsonp" để get data.
fetch('http://localhost:8080/') .then(response => response.json()) .then(data => console.log(data)).catch((error) =>
Thì chúng ta sẽ xuất hiện một lỗi về Access-Control-Allow-Origin
đó chính là CORS policy. Chình vì vậy tôi sẽ chuyển sang dùng JSONP để tránh lỗi này.
## JSONP
const jsonp = (opts = {}) => { opts.url = `${opts.url}?callback=${opts.callback}`; for (let key in opts.data) { if (opts.data.hasOwnProperty(key)) { opts.url += `&${key}=${opts.data[key]}`; } } const script = document.createElement('script'); script.src = opts.url; script.onload = () => { document.body.removeChild(script); } document.body.appendChild(script); }; jsonp({ url: 'http://localhost:8080/', data: { wd: 'nba', from: 'home' }, callback: 'getData' }); function getData(data) { console.log(data); } //Output: {msg: "Get data here", word: "nba", referer: "home", data: Array(3)}
Bạn có thể xem code tại đây https://jsfiddle.net/us6hmra9/