2016-03-03 24 views
9

Tôi đang cố triển khai Service Worker trong trang thử nghiệm. Mục tiêu cuối cùng của tôi là một ứng dụng hoạt động ngoại tuyến. Cấu trúc thư mục dướiHiểu phạm vi công nhân dịch vụ

/myApp 
    ... 
    /static 
    /mod 
     /practice 
     service-worker.js 
     worker-directives.js 
     foopage.js 
    /templates 
    /practice 
     foopage.html 

Tôi đăng ký một nhân viên dịch vụ như hình dưới đây (trong vòng service-worker.js):

navigator.serviceWorker.register('../static/mod/practice/service-worker.js').then(function(reg) { 
    console.log('Registration succeeded. Scope is ' + reg.scope); 
    ... 
} 

và trong giao diện điều khiển tôi thấy

Registration succeeded. Scope is https://example.com/static/mod/practice/

Nếu tôi trang được đặt tại https://example.com/practice/foopage, tôi có cần đảm bảo rằng phạm vi service worker của tôi là https://example.com/practice/foopage?

Nếu tôi cố gắng để xác định phạm vi trong cuộc gọi register chức năng như

navigator.serviceWorker.register('../static/mod/practice/service-worker.js', { scope: '/practice/foopage/' }).then(function(reg) { 
    ... 
} 

tôi nhận được lỗi

Registration failed with SecurityError: Failed to register a ServiceWorker: The path of the provided scope ('/practice/foopage/') is not under the max scope allowed ('/static/mod/practice/'). Adjust the scope, move the Service Worker script, or use the Service-Worker-Allowed HTTP header to allow the scope. 

Câu hỏi là: Chính xác những gì phạm vi tham khảo? Có phải đó là tập hợp các URL mà service worker cuối cùng sẽ kiểm soát không? Tôi có cần di chuyển service-workers.js ở một nơi khác không? Nếu vậy, ở đâu?

Trả lời

12

Nhân viên dịch vụ về cơ bản là một proxy giữa ứng dụng web của bạn và internet, vì vậy nó có thể chặn các cuộc gọi đến mạng nếu muốn.

Phạm vi trong trường hợp này đề cập đến đường dẫn mà nhân viên dịch vụ có thể chặn cuộc gọi mạng. Thuộc tính scope có thể được sử dụng một cách rõ ràng xác định phạm vi nó sẽ bao gồm. Tuy nhiên:

Nhân viên dịch vụ chỉ có thể chặn các yêu cầu có nguồn gốc trong phạm vi của thư mục hiện tại mà tập lệnh của nhân viên dịch vụ ở trong và các thư mục con của nó. Or as MDN states:

Nhân viên dịch vụ sẽ chỉ nhận được yêu cầu từ khách hàng dưới phạm vi của nhân viên dịch vụ.

Phạm vi tối đa cho nhân viên dịch vụ là vị trí của nhân viên.

Khi nhân viên dịch vụ đặt tại /static/mod/practice/, bạn không được phép đặt phạm vi thành /practice/foopage/. Yêu cầu đối với các máy chủ khác, ví dụ: https://stackoverflow.com/foo, có thể bị chặn trong mọi trường hợp.

Cách dễ nhất để đảm bảo rằng nhân viên dịch vụ của bạn có thể chặn tất cả các cuộc gọi cần thực hiện, sẽ đặt nó vào thư mục gốc của ứng dụng web của bạn (/). Bạn cũng có thể ghi đè các giới hạn mặc định bằng cách sử dụng tiêu đề http và đặt phạm vi theo cách thủ công (xem câu trả lời của Ashraf Sabry).

+2

Tôi không nghĩ tệp 'js' trong thư mục gốc là thứ sẽ được thực hiện. Nhưng với các khái niệm mới đến mô hình mới, tôi đoán –

+1

Tôi nghĩ rằng đó là chủ yếu vì lý do an ninh. Nếu bạn chỉ có quyền truy cập vào '/ static', nhưng không truy cập vào root ('/'), ví dụ, nhân viên dịch vụ của bạn không thể chặn các yêu cầu tới thư mục gốc. – nils

+9

Điều này chỉ đúng một phần — phạm vi xác định những trang nào được nhân viên dịch vụ kiểm soát. Khi một trang được kiểm soát bởi một nhân viên dịch vụ, * tất cả * các yêu cầu HTTP có nguồn gốc từ trang, bất kể URL yêu cầu, sẽ kích hoạt sự kiện 'fetch' của nhân viên dịch vụ. Vì vậy, nếu một trang được kiểm soát thực hiện một yêu cầu AJAX cho 'https: // thirdpartyapi.com/api/test', nhân viên dịch vụ của bạn sẽ có cơ hội đánh chặn nó. –

2

Để tệp công nhân dịch vụ trong bất kỳ thư mục nào được cấu trúc dự án của bạn áp đặt và đặt tùy chọn scope thành / và thêm tiêu đề HTTP Service-Worker-Allowed vào phản hồi của tệp công nhân dịch vụ của bạn.

Tôi đang sử dụng IIS, vì vậy tôi sẽ thêm dòng sau vào file web.config:

<location path="static/mod/practice/service-worker.js"> 
    <system.webServer> 
     <httpProtocol> 
      <customHeaders> 
       <add name="Service-Worker-Allowed" value="/" /> 
      </customHeaders> 
     </httpProtocol> 
    </system.webServer> 
</location> 

Và đăng ký người lao động theo:

navigator.serviceWorker.register('/static/mod/practice/service-worker.js', { scope: '/' }) 
     .then(function (registration) 
     { 
      console.log('Service worker registered successfully'); 
     }).catch(function (e) 
     { 
      console.error('Error during service worker registration:', e); 
     }); 

Thử nghiệm trên Firefox và Chrome.

Tham khảo các ví dụ trong Service worker specification

Các vấn đề liên quan