Klien HTML + JS untuk Sistem Pengawasan Garis



Di Geektimes, saya sering bertemu dan menikmati membaca posting dari seri DIY. Setelah memutuskan untuk memberikan kontribusi kecil pada perbendaharaan pengalaman berharga yang dikumpulkan di sini, saya akan menjelaskan secara terperinci proses menciptakan klien untuk web berdasarkan server Line.

Sistem pengawasan garis menyediakan API terbuka, dan pengembang mengatakan bahwa memungkinkan untuk menulis klien Anda sendiri berdasarkan pada itu untuk melihat arsip video dan kamera online. Juga, jika diinginkan, Anda dapat mengimplementasikan fungsi-fungsi seperti menambahkan acara ke arsip, overlay OSD di atas video. Deskripsi semua fitur disajikan dalam spesifikasi di situs web resmi .

Artikel ini adalah contoh nyata tentang bagaimana saya, pengguna dengan pengetahuan awal tentang JS, HTML, menulis aplikasi saya sendiri yang mengimplementasikan prinsip-prinsip dasar bekerja dengan server Line melalui server web bawaan.

Masukkan data

Penulis adalah pemula dalam pengembangan klien HTML, dan terlibat dalam pengembangan sistem pengawasan video Line.
Tingkat pengetahuan JS, HTML - awal.
Tugasnya adalah menulis klien HTML untuk bekerja dengan perangkat berdasarkan perangkat lunak Line menggunakan spesifikasi dari situs.

Saya akan mengungkapkan intrik utama segera - Saya sampai pada dua kesimpulan:

  1. Spesifikasinya nyata, dijelaskan dengan sangat jelas, Anda dapat menulis klien menggunakan C ++, PHP.
  2. Anda tidak dapat menulis klien HTML lengkap hanya menggunakan JS - hanya pemantauan online sesuai spesifikasi sebelum RPC.

Kesimpulan pertama cukup logis, mengingat banyaknya integrasi dengan program pihak ketiga. Semuanya dijelaskan di situs: ada sistem kontrol akses , berat , sistem POS , program untuk menentukan nomor mobil dan 1C .

Kesimpulan kedua lebih menarik, simak di bawah ini.

Mengapa Anda tidak dapat membuat klien lengkap dalam HTML + JS?


Jawab: permintaan lintas-domain.

Saat ini, server web Line terbatas, dan hanya dengan menyalin kode ke folder www, akses tidak dapat diperoleh. Namun, pengembang berjanji bahwa dalam versi baru untuk Linux dan di "Line 8.0" server web akan berfungsi sebagai standar: jika ada permintaan, jika ada file, itu akan mengembalikannya.

Sekarang buat proyek baru dan mulai coding. Seperti semua pendatang baru dalam pemrograman untuk web, menetapkan bahwa server "Lines" menjawab "*" di header Access-Control-Allow-Origin, saya mulai bekerja keras pada kode, memeriksa hasilnya pada Firefox 57.0.4 (64-bit). Permintaan ke server dikirim oleh XMLHttpRequest.

Awalnya, akan berguna untuk mempelajari informasi tentang sumber daya ini . Semuanya dijelaskan dengan sangat terperinci di sana, tetapi saya benar-benar ingin menyelesaikan tugas dengan cepat. Dan, sayangnya, karena kurangnya informasi, setengah hari hilang karena hantaman keras di dinding kebijakan keamanan browser modern.

Pada saat penulisan ini, empat browser modern utama tidak memungkinkan untuk membaca header yang diterima dari server. Menurut spesifikasi, perlu untuk mengimplementasikan otentikasi Digest, yang tidak mungkin tanpa header.

Pada akhir hari pertama, saya menyadari bahwa tanpa menambahkan pemrosesan OPSI ke server web Line, tidak ada yang akan berhasil, karena untuk permintaan dengan metode "sulit" atau tajuk khusus, browser membuat pra-permintaan OPSI, menunjukkannya dalam Access-Control-Request-Method dan Header Akses-Kontrol-Permintaan. Jadi saya mulai mencari opsi otorisasi lain, tetapi Basic atau Digest yang asli tidak lepas landas.

Metode alternatif telah dijelaskan dalam spesifikasi, itu masih menghabiskan beberapa waktu korespondensi dengan departemen program "Lines". Karena kesulitan semacam itu muncul bukan untuk pertama kalinya, sudah ada penopang untuk otorisasi, dan bahkan disebutkan dalam spesifikasi:
Pada klien yang tidak mungkin mengotorisasi permintaan menggunakan cara standar (HTTP Digest / Otentikasi Dasar), tajuk Otorisasi dapat dikirim menggunakan salah satu parameter permintaan, misalnya
/kfd3ado1sdrms/streaming/main.flv?authorization=Basic%20d2ViOg==

Setelah semua manipulasi, permintaan lintas domain standar mulai dijalankan dengan benar! Anda juga perlu menambahkan header Terima dengan jenis yang benar ke permintaan - Saya memutuskan untuk menggunakan JSON.

Kode Permintaan:

function get_request_url(method,current_server_data, resource, additional){ var request = current_server_data.server_ip + ':' +current_server_data.port +resource+'?authorization=Basic '+ utf8_to_b64(current_server_data.user+':'+current_server_data.password); if (additional != '' && typeof additional != "undefined") { request += '&' + additional; } return request; } function http_request_of_resource (server_index , resource, auth_attempt) { var request = get_request_url('GET', servers_array[server_index], resource,''); var req_ = new XMLHttpRequest(); req_.open('GET', 'http://'+ request, true); //req_.timeout = 9000; //  ,    req_.onreadystatechange = function() { if (this.readyState == 2) { if (this.status == 401) { //console.log('---unauthorized'); hideModal(); update_nessecary_structure(resource, 'unauthorized', server_index); } } else if (this.readyState === 4) { if (this.status === 0) { hideModal(); update_nessecary_structure(resource, 'server_down',server_index) } if (this.status == 200) { if (auth_attempt) hideModal(); else resource =(resource =='/cameras') ? resource+'_update_info': resource; //console.log('200' + this.responseText); update_nessecary_structure(resource, this.responseText, server_index); } else if (this.status == 404) { //console.log('404'); update_nessecary_structure(resource, '404', server_index); } } }; //   req_.setRequestHeader('Content-type', 'text/plain; charset=utf-8'); req_.setRequestHeader('Accept', 'application/json'); req_.send(); } 

Kami mengubah sumber daya ke yang kami butuhkan sesuai dengan spesifikasi dan mendapatkan data ini atau itu. Variabel tambahan berisi parameter tambahan untuk permintaan, jika perlu. Mengenai hal ini, pengembangan spesifikasi paruh pertama, yaitu penerimaan / pengiriman data teks melalui permintaan GET, dapat dianggap tertutup.

Lebih jauh, saya menemukan fakta bahwa tag IMG di IE tidak memutar aliran MJPEG, dan Anda perlu mengimplementasikan secara mandiri memperbarui gambar dari kamera. Kode terbuka, dapat dilihat dan diubah jika diinginkan. Dalam implementasi saat ini, pemutaran simultan dari maksimum enam stream MJPEG tersedia, sehingga Anda harus melakukan pekerjaan dengan tampilan yang menampilkan lebih banyak kamera. Semua ini ada dalam contoh , jika Anda mau, Anda dapat menemukan dan memahami, tetapi jika Anda memiliki pertanyaan, pastikan untuk bertanya di komentar.

Spesifikasi RPC


Kami diundang untuk mengirim dan menerima data baik dalam JSON (versi server "Baris 7.1.1" dan lebih tinggi) atau MessagePack (versi "Baris 7.0" dan lebih tinggi). Disebutkan bahwa MessagePack memiliki bobot lebih sedikit dan bekerja lebih cepat, tetapi jujur ​​saja, saya akan memilih JSON (sudah dibangun di JS), jika bukan karena satu hal tetapi dalam spesifikasi: menerima bingkai dari arsip hanya mungkin di MessagePack. Saya harus pergi ke situs web resmi mereka dan mengunduh file JS, yang memiliki metode encode dan decode di papan.

Fungsi pengiriman permintaan sudah siap! Tetapi terlalu dini untuk merayakan kemenangan: ketika Anda mencoba mengubah tajuk permintaan tipe konten, browser bersumpah dan tidak mengirim data ke server. Faktanya adalah bahwa server Lines menganalisis bidang ini dan mem-parsingnya tergantung pada jenisnya. Saya tidak bisa melakukannya sendiri.

Saya mengirim permintaan ke departemen program, dan setelah diskusi, mereka menambahkan kruk kepada saya, seperti dalam kasus otorisasi, - Tipe konten akan dikirim dalam permintaan url:

 function rpc_request_of_resource (current_server_data , rpc_method, rpc_request) { var request = get_request_url('POST', current_server_data, '/rpc',''); //console.log("i'm here request = " + request + ' '+ current_server_data.user); request += "&content-type='application/x-msgpack'"; var req_ = new XMLHttpRequest(); req_.open('POST', 'http://'+ request, true); //  ,    req_.responseType = 'arraybuffer'; req_.onreadystatechange = function() { if (this.readyState == 2) { if (this.status == 401) { //console.log('401' + this.getAllResponseHeaders()); console.log('unauthorized'); } } else if (this.readyState == 4) { if (this.status == 200) { //if (auth_attempt) hideModal(); //console.log('200' + this.responseText); rpc_update_nessecary_method(rpc_method, this.response); } else if (this.status == 404) { console.log('404'); } else if (this.status == 500) { //console.log('500'); rpc_update_nessecary_method(rpc_method, '500'); } } }; //   //req_.setRequestHeader('Content-type', 'text/plain; charset=utf-8'); //req_.setRequestHeader('Content-type', 'application/x-msgpack'); req_.setRequestHeader('Accept', 'application/x-msgpack'); req_.send(rpc_request); } 

Perubahan ini akan bekerja dengan versi "Baris 7.4.1" dan lebih tinggi. Untuk semua server di bawah versi ini, bekerja dengan sumber daya / rpc tidak akan tersedia.

Pada akhirnya, saya ingin mengucapkan terima kasih kepada semua pelanggan yang mengirimi kami pertanyaan / keinginan terkait dengan penerapan aplikasi berdasarkan API kami. Terima kasih kepada Anda, sebuah penelitian dilakukan, dalam kerangka di mana beberapa kekurangan diidentifikasi dan diperbaiki.

Contoh yang dijelaskan dalam artikel ini secara bertahap akan tumbuh menjadi klien HTML lengkap untuk Lines. Semua kode dapat dibaca, Anda dapat mengubahnya atau menggunakannya sebagai dasar untuk membangun solusi Anda sendiri. API, seiring waktu, akan diisi dengan lebih banyak fitur, yang pasti akan kami informasikan.

Source: https://habr.com/ru/post/id409999/


All Articles