1Lo Hong Sql Injection Trong Cac Ung Dung Su Dung Graph Ql1Lo Hong Sql Injection Trong Cac Ung Dung Su Dung Graph Ql1Lo Hong Sql Injection Trong Cac Ung Dung Su Dung Graph Ql1Lo Hong Sql
Trang 1HỌC VIỆN CÔNG NGHỆ BƯU CHÍNH VIÊN THÔNG
KHOA CONG NGHE THONG TIN I
Trang 2LOI CAM ON
Lời đầu tiên, em xin gửi lời biết ơn sâu sắc tới Thầy giáo TS Nguyễn Ngọc Điệp đã tận tình chỉ bảo, hướng dẫn em trong không chỉ quá trình thực hiện đô án này, nhờ sự giúp đỡ và những chia sẻ của Thây, em đã có những định hướng riêng cho tương lai của mình
Em xin chân thành cảm ơn các Thầy, Cô trong Khoa Công nghệ Thông tin 1 nói riêng và toàn thê các cán bộ của Học viện Công nghệ Bưu chính Viễn thông nói chung đã tạo điều kiện dé em cé thé hoc tap va phat triển bản thân trong một môi trường rất tốt Cảm ơn các Thây Cô đã cung cấp cho em không chỉ kiến thức mà còn là kỹ năng sông, đó là những hành trang hữu ích cho em trên chặng đường dài phía trước của cuộc đời
Em xin gửi lời cảm ơn đến anh chị làm việc tại Trung tâm an ninh mạng Cyber Security Division thuộc Công ty Cổ phân Hệ thống Thông tin FPT Information System đã cung cấp cho em những kiến thức về lập trình, an ninh mạng, kiểm thử xâm nhập và tạo điều kiện cho em hoàn thiện đồ án này
Cuôi cùng, em xin cảm ơn gia đình, bạn bè, những người đã luôn ở cạnh, quan tâm, giúp đỡ và ủng hộ đê bản thân em có thê hoàn thành được đô án này
Em xin chân thành cảm ơn]
Hà Nội, ngày 31 tháng 12 năm 2021
Sinh viên thực hiện
Phạm Hải Vũ
Trang 3
NHAN XET, DANH GIA, CHO DIEM
(Của Người hướng dẫn)
ĐH 2 Đ 0 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000660000600e0ee°eee°e0ee°e°e°ee°e°e°e Á ĐH 2 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600060000ee°ee ĐA 2 20 000000000000000000000000000000000000000000000000400000000000000000000400000000000000000000000000000000000000000000000000000606060600e006ee°66 Đ 00 000000000000000000900000000000000000000000000000000000000000000000000000000000000000000000000900009090000000900000000060000060096090eeeee0eeee°eee°e°e
9 0000000000009000000900000000000000000000000000000000000000000000000000000000000000000900000000900009090009600009060009600006060000600606090e0eee°eeeee°eee°e°e 99 00000000000090000000000600000000000000000000000000000000000000000000000000000000000000000009000000000000090000000090000009000060009006006060900906616© Á ĐH Đ ĐO 2 ĐC C0 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600090000600ee°ee°e°ee Á ĐH 6 2 A0 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060060006060600006e°66
0 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090000000000000900000909090000009000000090090060909°e°e°ee :
(ký và ghi rõ họ tên)
Trang 4
NHAN XET, DANH GIA, CHO DIEM
(Của Người phản biện)
ĐH 2 Đ 0 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000660000600e0ee°eee°e0ee°e°e°ee°e°e°e Á ĐH 2 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600060000ee°ee ĐA 2 20 000000000000000000000000000000000000000000000000400000000000000000000400000000000000000000000000000000000000000000000000000606060600e006ee°66 Đ 00 000000000000000000900000000000000000000000000000000000000000000000000000000000000000000000000900009090000000900000000060000060096090eeeee0eeee°eee°e°e
9 0000000000009000000900000000000000000000000000000000000000000000000000000000000000000900000000900009090009600009060009600006060000600606090e0eee°eeeee°eee°e°e 99 00000000000090000000000600000000000000000000000000000000000000000000000000000000000000000009000000000000090000000090000009000060009006006060900906616© Á ĐH Đ ĐO 2 ĐC C0 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600090000600ee°ee°e°ee Á ĐH 6 2 A0 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060060006060600006e°66
0 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090000000000000900000909090000009000000090090060909°e°e°ee :
(ký và ghi rõ họ tên)
Trang 5
MỤC LỤC
M.9s80)00/905)0)°0200 vii DANH MUC CAC TU VA THUAT NGU VIET TAT wu ecsesssesssesssessseesseesneesneesneesnes ix €)/9089:0096909Ẽ 9 007 .- 1
CHUONG 1: CONG!NCHIFZGRAPHOP! 101 xin Henhe: lethikim32079 @hotmail.cony
1.1 Tong quan về GraphQLL - - ¿ % + SE SE SE+E£E£EEEEE+EEEEEEEEEErkrkeEerkrkrkrkrree 2 JJZN (c1 nốe 2 1.1.2 Lịch sử phát triển của GrapnQL - - + + +s+s+E+E£EkEk+keEeEererkrkexererees 2
1.1.3 Kiến trúc triển khai GraphQLL . - - + 2 SsS‡ESE‡E‡EEEE‡EeEEEEekerrrkererered 4
1.1.3.a Máy chủ GraphQL kết nối trực tiếp với cơ sở dữ liệu - 5 1.1.3.b Máy chủ GraphQL tích hợp với các hệ thống săn Có . - 5
1.1.3.c Kiến trúc kết HỢpD - «+ sec SSkSEEEEEEEEEEEEEEEEEEEEEErrkrkrkrkrkrkeree 6
1.1.4 Các thành phần của Graph(QI - - - St E‡EvEvEEEEEEEkrkeketeteeeeerrrsrrree 6
1.1.5 Hệ thống kiểu dữ liệu (Tp€ SySÉ€INI) .- <5 EEEEEEEEeErkekekererrree 7
1.1.5.a Kiều dữ liệu đối J150/1⁄1(0)/)14511A)/-2T Ta 7
1.1.5.b Kiểu dữ liệu truy vấn và đột biến (Query and Mutation tfype) 9 1.1.5.c Kiểu dữ liệu vô hướng (ScaÌ4r fyJ0€) c-¿- -cc+c+EeEeEeEeEerererererereeeeed 10
1.1.5.d Kiểu dữ liệu liệt kê (Enumeration a2 em 10
1.1.5.e Bổ nghĩa List và Non-null (List and Non-null type modifier) II ITBNNI/12/i 5 0 aưudầẪddẪẢ L II ằ số 12 I.1.5.g Dạng liên hợp (UHIOH ÍJD€) c1 1 ke 13 1.1.5.h Dạng đâu vào (HH fVJD€) ¿- - + 5£ k+E+E‡E+E£EEEEeEeEkeEerkexerkererkd 13 1.1.6 Ngôn ngữ truy vấn (Query ÏaI1g1Iđ8€) 5-5-5 Sxct‡EEekeEerrterereeeee 14
NT n6 22
l.1.8 Thực Hi (EXX€CHẨ[OHH)) 0 1113113311111 11111 vn ky 26
1.1.9 Chỉ tiết cấu hình kiểu (Type infr0sp€€fÏOHI) - Set ct+keteteeerereree 27
1.2 Đánh giá ưu điểm và nhược điểm . 2 2-5 + E2 £E+EzEeEerrsrkrrrree 29
An, an 30 1.2.2 Nhurợc đÏỄHM - - -kSSt+k EEEEEEEEEEETEEEETET E1 T111 1111111110111 crerrrkg 31
1.3 Kết chươnggg - ¿St SE+ESx‡ SE EEEEEEE12111 2111121111111 11111111111 31
Trang 6
CHUONG 2: LO HONG SQL INJECTION TRONG GRAPHQL, API 32 2.1 Cac van đề về bảo mật trong GraphQ\L . - 2 2 2 s+seEeE£x+x+xererees 32 2.1.1 Rị rỉ các Ait TEU NNAY CẲHH 11v vn re 32 2.1.2 Kiểm sốt quyên truy cập dữ liệu - + St SE+k+EeEeEerrtekererred 33
2.1.3 Tan cơng từ chối zdịch VWile-bi-loi xản-Hienhe:lethieim34039@hotmail:eột
2.1.4 Lơ hơng báo mật trong các thành phân tích hợp 36 2.1.5 Lỗ hồng bảo mật xuất phát từ dữ liệu đầu vào -¿- - s©s+ssee: 36 2.2 Lỗ hồng SQL Injection trong GraphQL API ¿5-5 2 5+ =2 5+2 37 2.2.1 LO hong SOL Irije€fiOH - - + SE E‡E‡EEEEEEEEEEEEEEEEEEEEEEEEEErkrkrkererrkrkd 37 X»Z/nẴ con, 2n 6 nan 37 2.2.1.b Tấn cơng In-bandl SQL Ïnj€CfÏOH - c6 St +k‡E‡EeEeEEEkrteterererered 38
2.2.1.c Tấn cơng Blind SQL ÏnjeCtiOH -.: 5c+©5c>c+ccxt+eterrtsrxrrrvsrresee 38
2.2.1.d Tấn cơng Out-of-band SQL Inj€CfÌOII .- «+ 255k +t+E+E+EeEexereeei 39 2.2.2 NGUYEN TNA a4 sa 39 2.2.3 Các bước KÏidL ÍÏLẮC - - 111111 081111 1111 11 111 vn keo 39 2.2.3.a Thu thập thƠng ẨITI - - - - - «<< 099991191 011 1 1 ket 39
»2 80:1 i10 ỶÀäõŸcŨaiaiiii 40
2.2.4 Cơng cụ hỗ trợ khiai thác - +55 SE SE EEEEEEEEEEEEErrrkgrerrrerrkg 40
N1 J'c.//02/ 000, 0n 41 2.2.5 PRONG CHONG o.cccccccccccccccscsssccsssssssssessevsvsvevevsvsvavavsvevssasasacacacecsensvsvavsvevseens 42 2.3 K@t CHUOTG oo ccceccccccccsccscsesesscecscsvsvsscecavsvsvsucecavsvsvsusecavsvsvsesacavavsveveasavevaeess 42
CHUONG 3: XAY DUNG MOI TRUONG LAB DE THU NGHIEM TAN CONG
SQL INĐJECTION TRONG GRAPHQL, API - 5 5333322 £++eeeeeeeeeeeeees 43 “n9: 5 hs (a(liÍ1ÍiIƠOƠƠ 43 3.1.1 Damn Vulnerable GraphQL Application - 5555555 ssss+ 43 3.1.2 Generic UNIVeP ity 30000 TH gen 45 SN ) 008nnnee “31T 46 3.2 Phát triển mơi trường lab - - - sStx+E+E#EvEEEE+EeEEEEEEEEskrEeEererkrkerrrrrees 47 “TC 1 8 .ố ố 47 3.2.1.a Mục tiêu phát tFÏÊ HN -c- SE SE *EEEEEEEEEEEEEEEEEEEEEEEEEEEErkrkrkekrrererkred 47 3.2.1.b Đối trợng hướng AEN veccecccccccccsscsvssesvessvevssssvsvssssvsssessvssevsvsrsevsvereaveee 47 3.2.2 MO ta chive nang CÏHÍHÏH ng net 48
Trang 7
3.2.2.a Cung cấp các thông tin và cách cài đặt lab - + 2-5 s5s+s sec: 48
3.2.2.b Tự động thiết [Gp CO SO AU lIỆU S555 S5 S511 1155555555555 48 3.2.2.c Thiết lập mức độ bảo mật cho các dạng kỹ thuật khai thac SQL Injection
3.2.2.d Thực hành các kỹ thuật khai thác SQL ÏInJeCHOH << <+ 49
3.2.2 G10 điỆH ÏŒÖ, 0 1H nh 49
3.3 Thử nghiệm khai thác SQL Injection trên môi trường lab phát triển 54
SShI (I1 4, ,.18n6n6e.ốẶeẶaa ốẮỐa 54 3.3.1.a Error-based SQLL ÏHJ€CÍIOTN << << + + ‡**vv£+veeeeeeeeeeeeeeess 54 3.3.1.b Union-based SQL ÏHJ€CÍIOH << + 13388831 VVEEEsseeeeeeeess 55 3.3.1.c Boolean-based SQL ÏHJ€CHHOlH <1 EEEEttseeeeeees 56 3.3.1.d Time-based SQL ÏnJ€CHOH 5 << + + *+*+vvv+veeeeeeeeeeeeeeeeeeeees 57 3 1.e Quf-oƒ-band SQL ÏTIJ€CÍÍOHH c5 << 133388833911 VVEEEsseeeeeeeeeres 59
k2 115.171, TT NỹẺẺ ốố.é.aaaŨ 61
3.4 K@t CHUONG oo ccccccccccesscscecscscececscscscscscscsesssssssescscscsvscsvsvstsvsvsvscsesssseseeess 61
4100090000127 62 IM.9)58)/10/94V.9080508957.2) 0.3: 63
Trang 8
DANH MỤC HÌNH VẾ
Hình 1.1: Một số công ty đang sử dụng GraphQL - 2 + 2k E+E£E£EE+EeEzEeErEEerxrxees +
Hình 1.2: Máy chủ GraphQL kết nối trực tiếp với cơ sở dữ liệu - - ¿2 + z+x+s+£z£+zx2 5
Hình 1.3: Máy chủ GraphQL tích hợp với các hệ thống sẵn có - + 2s 2+2 £z£szxze: 6
Hình 1.4: Kiến trúc kết hợpp - ¿- - + + kE£SE+E+k£EEE+EEEEEEEEEEEEE E1 1151111111111 111111 6
Hình 1.5: Thống kê mức độ phổ biến của GraphQL trong năm 2020 ¿2 252: 30 Hình 2.1: Báo cáo về lỗ hồng tại HackerOne 2 ¿2 2S E+E£EE+EE+E£EE+EEEeEEzEerxrrerveei 34
Hình 2.2: Báo cáo về lỗ hồng tại Gitlab 2-5-5 kSSk‡EEEE*EEEEEEEEEEEEEEEEEEEEEEEEEEEkrkerkrkrrred 35
Hình 2.3: Báo cáo về lỗ hồng tại HackerOne -¿- - 2+ £©E+E£EE+E£EE+E+EEEEEEEEEEEEEErEeEerkrers 36
Hình 2.4: SQLi vẫn là vecor tân công web hàng đầu trong các cuộc tân công mạng 37 Hình 2.5: Giao diện chính của công cụ SQ map - - G5 E332 EEESSEEerseseekke 4] Hình 2.6: Giao diện chính của công cụ GraphQQLmap << << + 11 *+ssssseeeeeese 4] Hình 3.1: Giao diện chính của Damn Vulnerable GraphQL Application 44 Hình 3.2: Giao diện chính của GenerIC nIV€TSIVY c5 522 VVVEExseeeeeeeeeeeese 45 Hình 3.3: Giao diện đăng nhẬp - - - - - 1118331111183 111118 9 1111 ng ng ve 50 Hình 3.4: Giao diện chính sau khi đăng nhập thành công - + «+ ++++++*eex++ 50 Hình 3.5: Giao diện cung cấp các thông tin và cách cài đặt lab ¿- - 2 s+sec+zszxszxd 51
Hình 3.6: Giao diện chức năng thiết lập cơ sở dữ lIỆU S22 1 111v 51 Hình 3.7: Giao diện thực hành các kỹ thuật khai thac SQL Injection . - 52 Hình 3.8: Giao diện xem mã nguôn của một mức bảo mật với từng kỹ thuật khai thác 52
Hình 3.9: Giao diện xem gợi ý giúp người dùng có thể thực hiện khai thác lỗ hồng 53
Hình 3.10: Giao diện xem mã nguồn của các mức tất cả các bảo mật với từng kỹ thuật khai ¡2 53
Hinh 3.11: Giao dién thiét lập mức độ bảo mật cho các dạng kỹ thuật khai thác SQL Injection
Hình 3.12: Truy vẫn GraphQL có chứa payload khai thác . ¿- - + + +x+xe£zEezzxerrxd 54 Hinh 3.13: Tén cơ sở dữ liệu đang sử dụng - - << SH kg 55 Hình 3.14: Truy van GraphQL có chứa payload khai thác . - 2-5 2s ££szE+£zxzzzzxd 55 Hình 3.15: Thông tin của toàn bộ các tài khoản người dùng có trong cơ sở dữ liệu 56 Hình 3.16: Truy vấn GraphQL có chứa payload khai thác ¿2-5 2 2 s+s+££££+x+Ez£ezxzx4 57
Trang 9
Hình 3.17: Kết quả cho thấy câu truy vấn SQL với payload trả về kết quả true - 57 Hình 3.18: Truy van GraphQL có chứa payload khai thác . - 2 + 2+ z£s+£+£zxexszxd 58
Hình 3.19: Thời gian máy chủ trả về phản hôi là 3,4s - ¿2 52s 2+E+£££szEe£zxzzsred 59
Hình 3.20: Truy van GraphQL có chứa payload khai thác 2-5 2+s+sz+s£s+£zzxze: 60
Hình 3.21: Yêu cầu DNS chứa thông tin về phiên bản MySQL mà lab đang sử dụng 60
Trang 10
DANH MUC CAC TU VA THUAT NGU VIET TAT
CWE Common Weakness Enumeration
Mot hé thống phân loại các
điểm yếu và lỗ hồng của phần
mềm
HTML, Hypertext Markup Language Ngôn ngữ đánh dấu Siêu văn
JSON JavaScript Object Notation
Định dạng lưu trữ thông tin có cau tric duoc str dung dé truyén
dữ liệu giữa máy chủ và máy
khách
REST Representational State Transfer
Kiéu kién tric phan mém duoc tạo ra đê hướng dân thiệt kê và
phát triên kiên trúc cho ứng
Một loại lỗ hông bảo mật có thé
được tìm thấy trong một số ứng
dụng web
Trang 11
GIỚI THIỆU ĐỎ ÁN
Hiện nay, ứng dung web đang ngày càng phổ biến và phát triển mạnh mẽ đề đáp ứng các yêu cầu của các doanh nghiệp, tổ chức và thỏa mãn nhu cầu của người dùng Các ứng dụng web ngày nay có khả năng cung cấp dịch vụ kinh doanh nói riêng và các dịch vụ quản lý nói chung cho các doanh nghiệp hay tổ chức một cách vô cùng hiệu quả Trong bối cảnh chuyền đôi số đang được đây mạnh thì đã và đang có một số lượng
rất lớn các loại hình dịch vụ được cung cấp thông qua ứng dụng web và hiệu suất của
chúng được đảm bảo thông qua thời gian xử lý và các chức năng cung cấp thông tin Đi kèm với sự phát triển đó các công nghệ mới đề phát triển các ứng dụng web cũng ngày càng được ra đời nhiều hơn, giúp đơn giản hóa quá trình phát triển ứng dụng đề đáp ứng nhu cầu ngày một mạnh mẽ của các doanh nghiệp, tổ chức Một trong số những công nghệ đáng chú ý gần đây là GraphQL Đây là một giải pháp mới được phát triên bởi Facebook, cung cấp cung cấp cho các lập trình viên một phương thức hoàn toàn mới để phát triển các web API sử dụng cho ứng dụng web Với những thế mạnh của mình, GraphQL được dự đoán sé là tương lai mới của web API
Nhưng cũng giống như tất cả các công nghệ mới, GraphQL cũng đi kèm với những vấn đề về bảo mật Các vẫn đề này hoàn toàn có thể gây ra những ảnh hưởng về mặt an toàn bảo mật cho các API sử dụng GraphQL, khiến chúng trở thành mục tiêu tiềm năng cho các cuộc tấn công mạng
Đây là lý do em lựa chọn đề tài “Lỗ hỗng SQL Injection trong các ứng dụng sử dụng GraphQL” với mục đích tập trung nghiên cứu về công nghệ GraphQL và lỗ hồng SQL Injection trong cac tng dung web su dung GraphQL API
Đồng thời, nhằm nâng cao hiểu biết của các bạn sinh viên ngành công nghệ thông tin nói chung về GraphQL và lỗ hồng SQL Injection, em cũng sẽ ứng dụng GraphQL để phát triển một môi trường lab hỗ trợ thực hành khai thác đầy đủ các dạng SQL
Injection trong GraphQL, API Môi trường lab này được tạo ra với mục tiêu cung cấp một môi trường hỗ trợ giảng viên/sinh viên giảng dạy/thực hành về bảo mật GraphQL nói chung và lỗ hồng SQL Injection nói riêng Bên cạnh đó cũng giúp các lập trình viên mới tiếp cận với GraphQL hiểu rõ hơn về các quy trình bảo mật ứng dụng web sử dung
GraphQL API
Với những mục tiêu như trên, bô cục đô án của em sẽ bao gôm 4 chương theo câu trúc như sau:
e Chương 1: Công nghệ GraphQL
e Chwong 2: Lé hong SQL Injection trong GraphQL API
e Chuong 3: X4y dung mdi trudng lab thử nghiệm tan cong SQL Injection trong GraphQL API
e Chuong 4: Két luan
Trang 12
CHƯƠNG 1: CÔNG NGHỆ GRAPHQL
Chương I trình bày tổng quan về công nghệ GraphQL, bao gồm các mục như: lịch sử phát triển, các thành phần của GraphQL Đồng thời chương này phân tích tu điểm và nhược điểm của GraphQL so với phương thức giao tiếp API hiện có, cụ thể hơn là REST
1.1 Tổng quan về GraphQL
1.1.1 Gioi thiéu
GraphQL là một ngôn ngữ thao tác và truy vấn dữ liệu mã nguồn mở cho các API [1] OraphQLL không có gì liền quan với các dạng cơ sở dữ liệu nói chung hay các dạng cơ sở dữ liệu dạng đồ thị như Neo4j nói riêng Từ “Graph” xuất phát từ ý tưởng thu
thập dữ liệu trên lược đồ API (API graph) thông qua các trường và trường con, còn
“Q17 là viết tắt của ngôn ngữ truy vấn (guery language) Chính vì vậy mà GraphQL có thê được sử dụng rất hiệu quả trong bất kỳ ngữ cảnh nào mà API cần được sử dụng
GraphQL được Facebook phát triển nội bộ vào năm 2012 và được phát hành rộng
rãi vào năm 2015 Vào ngày 7 tháng 11 năm 2018, dự án GraphQL đã được chuyền từ
Facebook sang GraphQL Foundation mới được thành lập bởi hiệp hội thương mại công
nghệ phi lợi nhuận Linux Foundation Từ năm 2012, quá trình phát triển của GraphQL tudn theo mét “timeline” trién do Lee Byron - tác giả của GraphQL đặt ra Mục tiêu của Byron là làm cho GraphQL phô biến hơn trên các nên tảng web
GraphQL cung cấp cho các lập trình viên một phương thức khác so với REST và các kiến trúc dịch vụ web khác đề phát triển các web API Giống với các API sử dụng REST thông thường, các API sử dụng GraphQL cũng hoạt động theo mô hình máy khách-máy chủ GraphQL cho phép máy khách (cliem:) xác định câu trúc của dữ liệu cần truy vấn khi gửi yêu cầu HTTP(MTTP requesi) lên máy chủ (server) Máy chủ sau đó sẽ trả về dữ liệu có cấu trúc tương ứng thông qua phản hồi HTTP(MTTP response)
Từ đó sẽ ngăn chặn được việc có quá nhiều dữ liệu được trả về cho máy khách Lý do
cho việc này đến từ tính linh hoạt và phong phú của các ngôn ngữ truy vấn cơ sở dữ liệu như SQL Hai tính chất này của các ngôn ngữ truy vấn cơ sở dữ liệu sẽ làm tăng thêm độ phức tạp không cần thiết đối với các API đơn giản
Hiện nay, GraphQL đã hỗ trợ rất nhiều các ngôn ngữ lập trình, bao gồm Haskell, Javascript, Perl, Python, Ruby, Java, C++, C#, Scala, Go, Rust, Elixir, Erlang, PHP, E,
D va Clojure [2]
1.1.2 Lịch sử phát triển của GraphQL GraphQL bắt đầu được nhen nhóm phát triển vào thời điểm xuất hiện sự chuyền dịch sang các thiết bị di động Đây là thời điểm mà chiến lược phát triển ứng dụng trên
Trang 13
các thiết bị của Facebook không khả thi do các vấn đề liên quan đến mức sử dụng mạng cao khi áp dụng HTML5 trên các thiết bị di động Do đó, Facebook đã quyết định xây dựng lại các ứng dụng trên các thiết bi di động từ đầu băng cách sử dụng các công nghệ hoàn toàn mới
Vấn đề chính của Facebook khi triển khai ứng dụng trên các thiết bi di dong nam 6 tính năng Bảng tin (News Feed) Đây là một chức năng có yêu cầu rất phức tạp khi phải nó yêu câu rất nhiều thông tin như các bài đăng, tác giả của các bài đăng, nội dung bài đăng, danh sách các bình luận và những người đã thích bài đăng Mỗi bài đăng đều được
kết nói, long vào hoặc đệ quy với nhau Các API hiện tại không được thiết kế để cho
phép các lập trình viên tạo ra tính năng Bảng tin với số lượng bài đăng phong phú trên
các thiết bị di động Chúng không có tính chất phân cấp, không cho phép các lập trình
viên chọn những øì họ cần và cũng không có khả năng hiển thị danh sách các bài đăng với nguồn cấp dữ liệu không đồng nhất
Vào năm 2012, Facebook quyết định răng họ cần phải xây dựng một API hoàn toàn mới cho chức năng News Feed đề có thẻ tiếp tục việc triển khai ứng dụng trên các thiết bị di động Đây chính là lúc GraphQL bắt đầu được phát triển và vào tháng 8 năm 2012, ứng dụng Facebook cho iOS 5.0 đã được ra mắt cùng với công nghệ GraphQL mới Nó cho phép các lập trình viên giảm mức sử dụng mạng bang cach thay đổi phương pháp tìm nạp đữ liệu Trong vòng chưa đến 2 năm tiếp theo, GraphQL đã được sử dụng trên phần lớn các chức năng khác của ứng dụng Facebook trên iOS Lần đầu tiên Facebook công khai thông báo về GraphQL là tại hội nghị React.js Conf2015 và ngay sau đó, họ công bố kế hoạch đưa GraphQL thành giải pháp mã nguồn mở
Trên thực tế, trước đây các công ty khác như Netflix hay Coursera cũng đã nghiên cứu các ý tưởng khác nhau đề tạo nên phương pháp tương tác API hiệu quả hơn và cũng đã có một số thành quả nhất định Coursera đã từng thử nghiệm một công nghệ tương
tự GraphQL, cho phép máy khách yêu câu chính xác các dữ liệu cần thiết Netflix cũng
đã cung cấp giải pháp mã nguồn mở của họ có tên Falcor Tuy nhiên, sau khi GraphQL trở thành giải pháp mã nguồn mở, Coursera đã hoàn toàn hủy bỏ dự án thử nghiệm của họ và áp dụng GraphQL trên các sản phẩm của mình Tính đến nay, GraphQL đã được sử dụng trong sản phẩm của rất nhiều các công ty công nghệ lớn như Github, Twitter hay Shopify [3]
Trang 14
Who's using GraphQL?
Facebook's mobile apps have been powered by GraphQL since 2012 A GraphQL spec was open sourced in 2015 and is now available in
any environments and used by teams of all sizes
HOOm ma
Hình 1.1: Một số công ty đang sử dụng GraphQL 1.1.3 Kiến trúc triển khai GraphQL
GraphQL được phát hành dưới dạng một đặc tả mô tả hoạt động của một máy chủ
GraphQL (GraphQL server) Đây là một tập hợp các nguyên tắc về cách xử lý các yêu
cầu và phản hồi cũng như các giao thức được hỗ trợ, định dạng đữ liệu có thê được máy
chủ chấp nhận, định dạng của phản hồi do máy chủ trả về,
Đề gửi một truy vấn đến máy chủ GraphQL, máy khách có thể sử dụng bắt cứ giao thức mạng nào trong tầng giao vận miễn là giao thức đó khả dụng Thông thường, các
giao thức thường được sử dụng sẽ là TCP hoặc WebSocket Một điều cần chú ý nữa, máy chủ GraphQL là độc lập với cơ sở dữ liệu vì vậy, lập trình viên có thé str dụng nó
với bất cứ dạng cơ sở dữ liệu nào
Như vậy, có thể thấy luồng hoạt động của mô hình máy khách-máy chủ trong
GraphQL như sau: -_ Máy khách thực hiện gửi truy vẫn GraphQL đến máy chủ thông qua các yêu cầu
HTTP Các truy vẫn này thường sẽ được gửi dưới dạng một chuỗi
- May chủ sẽ nhận yêu cầu HTTP và trích xuất chuỗi truy vấn Sau đó, máy chủ
xác thực và xử lý truy vẫn GraphQL dựa theo cú pháp GraphQL mặc định và
lược đồ GraphQL (GraphQL schema)
- Gidng với các máy chủ API khác, máy chủ GraphQL cũng thực hiện các lệnh
gol đến cơ sở dữ liệu hoặc các dịch vụ khác đề truy xuất dữ liệu được máy khách
yêu cầu
- _ Cuối cùng, máy chủ sẽ tổng hợp lại dữ liệu và trả về cho máy khách dưới dang
một đối tượng JSON thông qua phản hồi HTTP
Một máy chủ GraphQLL có thê được triển khai bang một trong ba kiến trúc sau: máy
chủ GraphQL kết nói trực tiếp với cơ sở dữ liệu, máy chủ GraphQL tích hợp với các hệ
thống sẵn có hoặc kiến trúc kết hợp từ 2 kiến trúc trên Từng loại kiến trúc sẽ được trình bày chỉ tiết sau đây
Trang 15
1.1.3.a Máy chủ GraphQL kết nối trực tiếp với cơ sở dữ liệu Đây là dạng kiến trúc phố biến nhất cho các dự án không quá phức tạp về mặt hệ thông Đề triển khai, lập trình viên chỉ cần một máy chủ web Máy chủ web này sẽ đảm nhiệm vai trò là máy chủ GraphQL lẫn vai trò là máy chủ cơ sở dữ liệu
Khi máy khách gửi truy vẫn đến máy chủ GraphQL, nó sẽ tiễn hành đọc truy vẫn
và tìm nạp dữ liệu từ cơ sở dữ liệu Quá trình này được gọi là thực thi truy vấn Sau khi
thực thi truy vẫn, máy chủ sẽ trả về cho máy khách một phản hồi HTTP chứa dữ liệu
mà máy khách yêu câu
Với dạng kiến trúc này, GraphQL cũng sẽ không quan tâm đến loại cơ sở dữ liệu
hoặc định dạng được sử dụng đề lưu trữ dữ liệu Điều này có nghĩa là lập trình viên có
thể triển khai kiến trúc này với bất cứ loại cơ sở dữ liệu này, từ các dạng cơ sở dữ liệu
quan hệ như MySQL cho đến các dạng cơ sở dữ liệu phi quan hệ như MongoDB
1.1.3.b Máy chủ GraphQL tích hợp với các hệ thống săn có
Đây là dạng kiến trúc được sử dụng cho các dự án phức tạp về mặt hệ thống Các
dự án này thường đòi hỏi kết nối với các các cơ sở hạ tầng và API sẵn có của doanh nghiệp Những thành phân có thể đã được phát triển và sử dụng trong nhiều năm, khiến cho việc triển khai các dự án mới trên chúng gặp rất nhiều khó khăn Trong dạng kiến trúc này, máy chủ GraphQL có thể được sử dụng để hợp nhất cdc “microservice”, co so
hạ tầng và các API khác trong hệ thống hiện tại Điều nay sẽ ø1úp giấu sự phức tạp của
các bước tìm nạp dữ liệu Băng cách này, máy khách sẽ chỉ cần thực hiện giao tiếp với máy chủ GraphQL đề lấy các đữ liệu cần thiết Sau đó, máy chủ GraphQL sẽ chịu trách
nhiệm tìm nạp dữ liệu từ các hệ thống được tích hợp và trả về cho máy khách
Trang 16
Với dạng kiên trúc này, máy chủ GraphQLL cũng sẽ không quan tâm đên các nguôn
dữ liệu mà nó cân đê tìm nạp các dữ liệu cân thiệt nhăm thực hiện một truy van
Đây là dạng kiến trúc kết hợp từ 2 dạng đã nêu trên Trong dạng kiến trúc này, máy
chủ GraphQL được kết nối trực tiếp với một cơ sở dữ liệu và đồng thời cũng sẽ được
sử dụng để tích hợp các hệ thống sẵn có Lúc này, khi máy chủ GraphQL nhận được
truy vẫn, nó sẽ truy vấn đữ liệu từ cơ sở dữ liệu được kết nối trực tiếp hoặc từ các hệ
1.1.4 Các thành phân của GraphQL
Các thành phần của GraphQL bao gồm: hệ thống kiều dữ liệu (fype sysfem), ngôn
ngữ truy van (query language), xac thuc (validation), thuc thi (execution) và xem xét
Trang 17
nội dung kiểu (/ype introspection) Từng thành phần sẽ được trình bày chỉ tiết trong các
mục tiếp theo [4]
1.1.5 Hé thong kiéu dit ligu (Type system)
Hệ thống kiểu dữ liệu là thành phần có chức năng xác định các kiểu dữ liệu khác
nhau có thể được sử dụng trong một GraphQL API Hệ thống sẽ đóng vai trò chính
trong việc tạo nên lược d6 (schema) cho GraphQL API
Lược đồ là cốt lõi của một GraphQL API Máy chủ GraphQL sẽ sử dụng lược đồ
để xác định và mô tả hình dạng đô thị dữ liệu của API đó Lược đồ sẽ thiết lập hệ thông
phân cấp các loại dữ liệu với các trường cũng như mô tả các chức năng sẵn có cho máy
khách Nói một cách đơn giản hơn, lược đồ được sử dụng để xác định một tập hợp các
kiểu dữ liệu và mối quan hệ giữa các kiều dữ liệu này Nó cũng được dùng để xác định
các tác vụ mà máy khách có thể sử dụng
Như đã trình bày ở trên, hiện nay, GraphQL đã hỗ trợ rất nhiều ngôn ngữ lập trình khác nhau Đề thuận tiện cho việc sử dụng với nhiều ngôn ngữ, GraphQL sẽ sử dụng một loại cú pháp chung để tạo nên lược đồ Cú pháp này được gọi là Ngôn ngữ định nghia luoc d6 (Schema Definition Language) Cu phap nay sé duoc str dung dé khai bdo lược đồ cho các GraphQL API theo hướng độc lập với ngôn ngữ lập trình
Một thành phân được định nghĩa trong lược đồ cần thuộc một trong các kiểu dữ liệu sau:
- _ Kiểu dữ liệu déi tuong (Object type) - Kiéu dé liéu truy van (Query type) - Kiéu dit liéu d6t bién (Mutation type)
- Kiểu đữ liệu vô hướng (Secalar fype)
- Kiéu dit liéu liét ké (Enumeration type) Ngoài các kiểu dữ liệu kế trên thì một thành phần trong lược đồ cũng có thê được
định nghĩa là một /nterface hoac mot dang lién hop (Union type) hay mot dang dau vao
(Input type) Cac thanh phan trong lugc d6 c6 thé sir dung thêm các bồ nghĩa như 1⁄5 và Non-nuil, tùy theo yêu cầu về mặt cấu trúc dữ liệu cho dữ liệu các thành phần đó
Từng kiêu dữ liệu sẽ được trình bày chỉ tiết sau đây
1.1.5.a Kiểu dữ liệu đối tượng (Object type)
Thành phần cơ bản nhất của lược đồ GraphQL 1a kiểu dữ liệu đối tượng, đại diện
cho một đối tượng mà máy khách có thể tìm nạp từ GraphQL API Một kiêu dữ liệu đối
tượng sẽ có thể có nhiều trường, mỗi trường có thê thuộc một kiêu dữ liệu khác nhau
Nói cách khác, kiêu dữ liệu này sẽ bao gồm nhiều trường, các trường này có thê thuộc
các kiểu dữ liệu vô hướng hoặc các kiểu dữ liệu đối tượng khác Cú pháp cơ bản đề định nghĩa một kiểu dữ liệu đối tượng như sau:
Trang 18
type object type name
{
fieldl: data_type field2:data_type fieldn:data_type
Vi du dinh nghia kiểu dữ liệu đối tượng Character trong lugc đồ GraphQL:
type Character { name: String!
- Ménh đề Síring! đại diện cho việc trường øze thuộc kiéu di liéu String va
trường này sẽ không thể mang giá trị rỗng Với định nghĩa như vậy thì máy
khách sẽ luôn nhận được dữ liệu của trường nzne dưới dạng một chuỗi ký tự - Ménh dé / Episode]! đại diện cho việc truong appearsIn ánh xạ tới một mảng
các đối tượng thuộc kiểu dữ liệu Episode và mảng này sẽ không thé mang gid trị rỗng Kiểu dữ liệu Episode cũng là một kiểu đôi tượng được định nghĩa trong
lược đồ Với định nghĩa như vậy thì máy khách sẽ luôn nhận được dữ liệu của trường apppearsin dưới dạng một mảng của các phần tử thuộc kiểu dữ liệu
Episode
Cac truong thudc kiểu đối tượng có thể không có hoặc có nhiều tham số, ví dụ như
trường /eng:h trong ví dụ dưới đây:
type Starship { id: ID!
name: String! length(unit: LengthUnit = METER): Float
Trang 19GraphQL sẽ truyền giá trị vào tham số theo tên cụ thể của tham số đó Trong ví dụ trên
trường /engfh sẽ có một tham số với tén 1a unit
Khi định nghĩa một trường có tham số thì lập trình viên có thể lựa chọn xem việc
máy khách phải cung cấp giá trị cho tham số đó là tùy chọn hay bắt buộc Khi một tham
số không bắt buộc máy khách phải cung cấp giá trị, lập trình viên có thể khởi tạo một
giá trị mặc định Trong ví dụ trên, nếu gia tri cua tham s6 unit khong duoc may khach
`
cung cấp thi gia tri cua né sé dugc mac dinh coi la “METER”
1.1.5.b Kiểu dữ liệu truy vấn và đột biến (Query and Mutation type) Giống với các API khác, GraphQL API cũng cho phép máy khách thực hiện hai
loại tác vụ chính với dữ liệu bao gôm tìm nạp dữ liệu và thay đôi dữ liệu Các tác vụ cụ
thể mà máy khách sử dụng sẽ được xác định trong lược đồ của GraphQL API Đề có thể định nghĩa một tác vụ, GraphQL sẽ cung cấp 2 kiểu dữ liệu đặc biệt là kiểu dữ liệu
truy van và kiểu đữ liệu đột biến Trong đó, kiêu dữ liệu truy vấn sẽ đại diện cho các
loại tác vụ tìm nạp dữ liệu và kiều dữ liệu đột biến đại diện cho các loại tác vụ thay đổi
dữ liệu Một GraphQL API đều có một hoặc nhiều kiểu dữ liệu truy van và có thể có
hoặc không có kiểu dữ liệu đột biến Kiểu dữ liệu truy vẫn và đột biến là các kiều dữ liệu đặc biệt do chúng sẽ xác định
các diém dau vao (entry point) cho 2 tác vụ tìm nạp đữ liệu và thay đổi dữ liệu Ngoài
đặc điểm đó ra thì kiểu truy vẫn và đột biến hoàn toàn giống với kiêu dữ liệu đối tượng và các trường của chúng cũng hoạt động tương tự như các trường của kiêu dữ liệu đối
tượng
Cú pháp để cơ bản để định nghĩa các tác vụ tìm nạp dữ liệu sử dụng kiểu dữ liệu truy vẫn như sau:
type Query {
fieldl: data type
Ví dụ, định nghĩa các tác vụ tim nap dt ligu hero va droid:
type Query { hero (episode: Episode): Character droid(id: ID!): Droid
Trong vi du trén, kiểu dữ liệu truy vấn đã định nghĩa tác vụ tìm nạp dữ liệu hero là
một truy vấn có tham số là episode là một đối tượng thuộc kiêu đữ liệu Episode và sẽ trả về dữ liệu là một đối tượng thuộc kiêu dữ liệu Characrer còn tác vụ tìm nạp đroid
Trang 20
sẽ có tham số là ¿đ có kiểu dữ liệu vô hướng 7D và trả về dữ liệu là một đối tượng có
kiểu dữ liệu Droid Cú pháp cơ bản để định nghĩa các tác vụ thay đổi dữ liệu sử dụng kiểu đữ liệu đột
biến cũng sẽ tương tự:
type Mutation { fieldl: data type
}
1.1.5.c Kiểu dữ liệu vô hướng (Scalar type)
Kiêu đữ liệu vô hướng là kiêu đữ liệu cơ sở (primitive fype) chỉ có thê lưu trữ một giá trị duy nhất Các kiểu dữ liệu vô hướng mặc định mà GraphQL cung cấp là:
- Int: Dai dién cho cdc giá trị số nguyên 32-bit có dấu - _ Floar: Đại diện cho các giá trị số thực dấu phây động có dấu
- String: Dai dién cho cac chuỗi ky tu duoc ma hda theo UTF-8 - Boolean: Dai dién cho cac gia tri true hoac false
- ID: Đại điện cho một số nhận dạng duy nhất, thường được sử dụng đề tìm nạp
một đối tượng hoặc làm khóa cho bộ nhớ cache Kiểu dữ liệu này thường được tuần tự hóa (serialize) giống nhu String
1.1.5.d Kiểu dữ liệu liét ké (Enumeration type)
Kiểu dữ liệu liệt kê cũng gần tương tự như kiêu dữ liệu vô hướng, chỉ khác là kiểu
dữ liệu liệt kê có thê lưu trữ một tập hợp các giá trị khác nhau Kiểu dữ liệu này rất hữu
ích khi dữ liệu của một trường phải nam trong danh sách các tùy chọn được chỉ định Cú pháp đề định nghĩa một kiểu đữ liệu liệt kê như sau:
JEDI
Trang 21
Với định nghĩa trên, bất cứ trường hay tham số nào thuộc kiểu đữ liệu Episode sé có giá trỊ là một trong ba chuỗi “NEWHOPE”, “EMPIRE” hoặc “JEDT'
1.1.5.e Bồ nghia List va Non-null (List and Non-null type modifier) List duoc dinh nghia la mot bổ nghĩa (type modifier), được biểu diễn băng một cặp
dẫu ngoặc vuông bao bọc tên các kiểu dữ liệu đối tượng, kiểu dữ liệu vô hướng và kiểu
dữ liệu liệt kê Bồ nghĩa này có thê được sử dụng đề biêu diễn cho một mảng các giá trỊ
thuộc một kiểu cụ thể Cú pháp để xác định một thành phần có bồ nghĩa /¡s/ như sau:
liệu liệt kê Bổ nghĩa này có thể được sử dụng để biểu diễn cho việc một thành phần
nào đó yêu cầu giá trị khác giá trị rỗng Điều này nhằm đảm bảo sự hiện diện của giá trị trong kết quả truy vấn Cú pháp để xác định một thành phần có bồ nghĩa khác rỗng Non-null như sau:
Cé thé thay trudng name sé thuéc kiéu dit liéu String va cé b6 nghia Non-null Điều này có nghĩa là máy chủ sẽ luôn trả về một giá trị khác rỗng cho trường này Trong trường hợp giá trị của „zne là rỗng, máy chủ sẽ kết thúc quá trình xử lý truy vấn và trả
về thông báo lỗi thực thi cho máy khách
Trường apppearsỉn sẽ thuộc kiêu đữ liệu Episode và có bô nghĩa L¡sr Điều này có nghĩa là máy chủ sẽ luôn trả về một mảng các đối tượng thuộc kiểu dữ liệu cho trường này Đồng thời kiểu trường này cũng được đánh dấu là /Episode!J, có nghĩa là các đối
tượng thuộc kiểu dữ liệu Episode trong mảng kết quả trả về cũng bắt buộc phải có giá
trị khác rỗng Ví dụ:
appearsiIn: null // valid
appearsiIn: [] // valid appearsiIn: ['NEWHOPE', 'EMPIRE'] // valid
Trang 22
Dau chấm than ngay sau /Episode!]! cũng thê hiện rằng mảng dữ liệu trả về cho trường appearsÏn cũng phải luôn khác giá trị rỗng Từ đó có thể suy ra các giá trị thỏa mãn với truong appearsIn:
apbearsIn: null // error
appearsiIn: [] // valid
appearsiIn: ['NEWHOPE', null, 'EMPIRE'] // error
1.1.5.f Interface
Giống như nhiều hệ thống kiểu dữ liệu khác, GraphQL cũng hỗ trợ các Interface Interface là một kiêu dữ liệu trừu tượng, bao gồm một tập hợp các trường nhất định
phải có mà một kiểu dữ liệu khác phải có khi kiểu dữ liệu đó được định nghĩa là sử dụng
giao dién Vi du dinh nghia Interface Character dai dién cho bất cứ nhân vật nào trong
một chuỗi phim:
interface Character { id: ID!
Bắt cứ kiêu đữ liệu nào sử dung Interface Character déu sé co cac truong xuất hiện
trong giao diện này Các trường đó sẽ có các đối số và kiểu trả về giống như đã được
định nghĩa trong Iwerface Character Dưới đây là ví dụ về một số kiểu đữ liệu có thể
Trang 23Kiéu dit ligu Human dai dién cho các nhân vật là con người còn kiểu dit ligu Droid
đại diện cho các nhân là người máy Có thể thấy 2 kiểu đữ liệu này đều có tất cả các
truong tir Interface Character, nhưng chúng cũng có thêm các trường bồ sung như totalCredits, starships cho cac nhan vat la con nguoi va primaryFunction cho cac nhan vật là người máy
1.1.5.g Dang lién hop (Union type) Dang liên hợp gần giống với giao diện, nhưng chúng sẽ không yêu câu các kiểu đữ liệu có trường chung Ví dụ định nghĩa dạng liên hợp Search Ñesulr:
răng các thành viện trong một dạng liên hợp phải là một kiêu dữ liệu cụ thé Khong thé
tạo dạng liên hợp từ các giao diện hoặc các dạng liên hợp khác
1.1.5.h Dang dau vao (Input type) Trong các ví dụ trên, hầu như tham số của các trường sẽ nhận giá trị là các kiểu dữ liệu vô hướng như /z hay Sring Tuy nhiên, trên thực tế đôi khi máy khách sẽ cần truyền giá trị là các đối tượng phức tạp cho các trường Điều này thường xảy ra với các
tác vụ thay đối dữ liệu, khi máy khách có thê tạo một đối tượng và chuyên thành giá trị
cho một trường Lúc này, lập trình viên có thê định nghĩa một dạng đầu vào đề chứa đối tượng mà máy khách tạo ra Cú pháp đề định nghĩa một dạng đầu vào như sau:
Trang 24commentary: String
}
1.1.6 Ngôn ngữ truy vấn (Query language) Query language là thành phần tạo nên các câu truy vấn trong GraphQL Máy khách có thê sử dụng query language để thực hiện tương tác dữ liệu từ máy chủ Trong GraphQL, có hai tác vụ chính mà máy khách có thê thực hiện với ngôn ngữ truy vấn:
— Tim nap dir liéu (query)
— Thay d6i dit ligu (mutation)
Cú pháp của một câu truy vân như sau:
can thay d6i di liéu Query_operation là bắt buộc phải có với mỗi câu truy vấn
- Operation_name là mệnh đề xác định tên cho các câu truy vẫn Operation_name chỉ bắt buộc phải có với các API yêu cầu nhiều tác vụ khác nhau để tương tác
với dữ liệu Nhưng nó cũng được khuyến khích sử dụng vì sự hữu ích cho việc
gỡ lỗi và ghi log phía máy chủ Khi xuất hiện lỗi, việc xác định các câu truy vấn
trong mã nguồn theo tên sẽ dễ dàng hơn so với việc phải xác định dựa vào nội dung
- _ Fields là mệnh đề xác định các dữ liệu mà máy khách cần tương tác
Trang 25query_ name {
máy chủ thực hiện song song
- Ménh dé query_fields là thành phần giúp cho máy khách xác định những dữ
liệu cần lây từ máy chủ
Dưới đây là ví dụ một câu g„ery và kết quả khi thực hiện thành công:
Trong ví dụ trên, tác vụ tìm nạp dữ liệu hero sẽ trả vê gia tri cua truong name cua
một đôi tượng có kiêu dir ligu Character Một trường cũng có thê ánh xạ đến một đối tượng khác Khi đó, máy khách chỉ cần
tạo thêm các trường còn trong trường đó đề lấy dữ liệu từ đối tượng nó ánh xạ đến GraphQL sẽ duyệt các đối tượng có liên quan và các trường của chúng và cho phép máy khách tìm nạp nhiều dữ liệu liên quan chỉ trong một truy vấn Ví dụ câu øery dưới đây có trường #iends ánh xạ đến một mảng các đối tượng thuộc kiểu dữ liệu Character:
{ hero {
Trang 26"name": "Han Solo"
}, {
"name": "Leia Organa"
khách phải gọi API đề tìm nạp dữ liệu Tham số cũng có thể có nhiều kiểu dữ liệu khác
nhau Dưới đây là ví dụ về một query có sử dụng tham số đề tìm nạp dữ liệu:
Trong mot s6 truong hop, khi c4u query tir may khach co nhiéu tac vu tim nap dit
liệu giống nhau, ví dụ với câu truy van str dung tac vu tim nap human dé lay dữ liệu về
2 đôi tượng có kiểu dữ liệu Human với tham số ¿đ là 1000 và 1001 Với cách viết như
các ví dụ trên, ta sẽ có câu g⁄ery như sau:
Trang 27Lúc này, sẽ xuất hiện xung đột do máy chủ thực hiện các tác vụ tìm nạp song song
nên không thể phân biệt được máy khách cần lấy dữ liệu từ tác vụ nào Để tránh điều
này xảy ra, máy khách có thê sử dụng bí danh (zias) để đổi tên các tác vụ bị trùng lặp
Ví dụ, với bí danh, câu øuery trên có thê được viết lại như sau:
{
human1000: human(id: "1000") name
height
}
humanl001: human(id: "1001") name
by
"humanlOO1": { "name": "Darth Vader", "height": 2.02
Tiêp tục xét đên một trường hợp khác, giả sử với câu truy vân trên, máy khách sẽ
cân lây dữ liệu về tên và chiêu cao của 100 đôi tượng thuộc kiêu dữ liệu Human Lúc
này câu truy vấn sẽ trở nên phức tạp hơn do sẽ phải liên tục gọi các trường name va heighr ở mỗi tác vụ Đề giải quyết trường hợp này, GraphQL cho phép lập trình viên tao ra cdc Fragment Fragment cho phép máy khách tạo ra nhóm các trường cần phải lấy dữ liệu và đưa chúng vào các tác vụ Fragmen thường được sử dụng để chia các yêu cầu dữ liệu phức tạp thành các phần nhỏ hơn Ví dụ để giải quyết trường hợp trên, có thê su dung cau query nhu sau:
{ human1000: human (1d: "1000")
{
comparisonFields }
humanl001: human(id: "1001")
comparisonFields
}
fragment comparisonFields on Human {
"name": "Luke Skywalker", "height": 1.72
by
"human1001": { "name": "Darth Vader",
"height": 2.02
Trang 28
Trong tất cả các ví dụ ở trên, các tham số đều được cung cấp bên trong câu gwery Tuy nhiên, trong hầu hết các ứng dụng, các tham số cho các trường sẽ động Ví dụ, người dùng có thể cung cấp tham số tùy ý thông các ô tìm kiếm dữ liệu hoặc các bộ lọc
dữ liệu Máy khách có thể chuyền trực tiếp các tham số động vào câu query Tuy nhiên
khi làm như vậy, máy khách sẽ cần tác động vào câu truy vấn trong thời gian chạy và chuyền câu query thành dạng xác định cho GraphQL Thay vào đó GraphQL cung cap một phương pháp khác để xác định các tham số động và cung cấp cho câu query bằng
cách đưa chúng thành giá trị dưới dạng từ điển riêng biệt Các giá trị này được gọi là bién (variable)
Một biến có thể được khai báo như sau:
dữ liệu vô hướng, các giá trị hằng số hoặc một đối tượng đầu vào mà người dùng
có thê định nghĩa trong lược đồ của API Ngoài ra, nếu một biến yêu cầu một giá trị đầu vào khác rỗng thì sẽ cần thêm ký tự ! vào sau variableType
Khi sử dụng các biên, có ba điêu cân thực hiện:
- _ Thay thế các tham số trong câu query bang $variableName
- _ Khai báo §variableName là một trong các biến được chấp thuận bởi câu guery
- ua gia tri cua variableName vao cau query
Vi du cu thé nhu sau:
query HeroNameAndFriends (Sepisode: Episode) { | {
"episode": "JEDI"
"name": "Leia Organa"
Trang 29
}
Trong ví dụ trên, biến $episode đã được khai báo là 1 đối tượng thuộc kiểu dữ liệu
đầu vào Episode được định nghĩa trong lược đồ của API Biến này không yêu cầu một giá trị đầu vào khác rỗng Lúc này, câu guery HeroNameAndFriends sẽ chấp thuận biến $episode Khi đó, máy khách sẽ chỉ cần cung cấp giá trị của biến này dudi dang JSON thay vì cần phải tạo một câu zery hoàn toàn mới Khi thực hiện câu truy vấn với câu query trên, máy chủ sẽ đưa giá trị nhận từ máy khách vào biến $episode trong câu gwery,
thực hiện và trả về dữ liệu cho máy khách
Ngoài ra, lập trình viên cũng có thể gán một giá trị mặc định cho biến Ví dụ, gán giá trị mặc định cho biến §episode:
Khi giá trị mặc định được gán cho một biến, máy khách có thể thực hiện gọi câu
query mà không cần truyền vào giá trị của biên đó Nếu có bât cứ giá trị nào được truyền
vào thì máy chủ sẽ ghi đè giá trị đó lên giá trị mặc định
Việc sử dụng các biến đã giải quyết rất nhiều vẫn đề khi cần phải tạo các câu gwery
với tham số động Tuy nhiên, trong một vài trường hợp, máy khách cần thêm một phương pháp để thay đổi cấu trúc và hình dạng của câu gery bằng cách sử dụng biến Ví dụ, ở máy khách xuất hiện một thành phần giao diện người dùng có chế độ xem tóm tắt và chỉ tiết, trong đó chế độ xem chỉ tiết sẽ yêu cầu nhiều trường cần lấy dữ liệu hơn chế độ xem tóm tắt Lúc này, máy khách sẽ cần phải sử dụng một tính năng mới trong
GraphQL duoc goi la Directive Mot Directive c6 thé được đính kèm với trường hoặc
Fragment Directive c6 thé tac dong dén viéc thu thi tac vu ma cau query yéu cau theo bất cứ cách nào mà máy chủ mong muốn Đặc tả lõi của GraphQL bao gồm 2 loại
Trang 30Directive rất hữu ích khi máy khách cần hạn chế tình huống cần phải thực hiện thao
tác chuỗi để thêm hoặc xóa các trường ra khỏi kết quả nhận được từ máy chủ Ví dụ,
cau query khi cần thực hiện tác vụ tìm nap hero voi Directive @ include dé bo qua dữ
liệu của trường ƒiend ra khỏi kết quả trả về:
Trong vi du trén, biến $withFriends được khai báo là một biến thuộc kiểu dữ liệu Boolean và được sử dụng làm giá trỊ đề xác định việc thực hién Directive @include di
kèm với trường ƒiends để xác định xem có đưa dữ liệu lẫy từ trường này vào kết quả
trả về hay không Trong trường hợp giá trị bién $withFriends 1a false, két quả trả về sẽ không có đữ liệu lây từ trường #iends
Trong trong hop, trong cau query có một trường trả về một đối tượng là một
Interface hoặc thuộc dạng liên hợp, máy khách sẽ cần sử dụng các /mline fragmen: đề truy cập vào dữ liệu của các trường thuộc một kiểu cụ thể Xem xét ví dụ dưới đây:
Trang 31
Interface Có nghĩa là các đối tượng thuộc kiểu dữ liệu này thể được chia nhỏ thành
thuộc một trong hai kiểu dữ liệu khdc 18 Human hoac Droid, tuy thudc vao bién
$episode Với câu query trực tiếp, máy khách sẽ chỉ có thê lây được dữ liệu của các
trường trong kiêu dữ liệu Character, ví dụ như trường name Đề có thể lây được dữ liệu của một trường trong một kiểu dữ liệu cụ thẻ, máy khách sẽ cần sử dụng một Iniine
fragment với điều kiện về kiêu đữ liệu Trong ví dụ trên, máy khách đã sử dụng 2 Inline
fragment, bao gồm: - .0n Droid: Inline ffagment này sẽ trả về trường prinaryFunction trong trường
hợp đối tượng có kiêu dữ liệu Character mà hero trả về thuộc kiêu dit liéu Droid
- .0n Human: Inline fragment nay sé tra vé truong height trong truéng hop déi
tượng có kiêu dữ liệu Character mà hero trả về thuộc kiểu dữ liệu Human
Các Fragmenr được đặt tên cũng có thé duoc str dụng theo cách tương tự, vì một
Fragmenr được đặt tên luôn có một kiêu được đính kèm
Tuy nhiên cũng có một số tình huống mà máy khách sẽ không thể biết được máy chủ sẽ trả về đối tượng thuộc kiều dữ liệu nào Lúc này, GraphQL cung cấp một ““wera
field' là typename với tác dụng giúp cho máy khách có thê lấy được tên kiểu dữ liệu
của đối tượng trong dữ liệu Ví dụ:
; name "typename": "Human",
Trang 32Trong cau guery trén, tac vu tim nap df ligu search sé trả về một đôi tượng thuộc
dạng liên hợp Déi tuong nay co thé thudc mét trong ba kiéu dir ligu Human, Droid
hoặc Starship Vi vay, may khách sẽ không thể phân biệt được các kiểu dữ liệu khác
nhau nếu không c6 “meta field” typename
Ménh dé mutation_name 1a tac vu thay đối dữ liệu cần thực hiện Giống với
q„ery, một câu mufafion cũng có thể bao gồm nhiều tác vụ thay đổi dữ liệu Tuy nhiên, trong trường hợp câu mutation c6 nhiéu tac vu thay thi cdc tac vu do sé
được thực hiện lần lượt Điều này nghĩa là nêu máy khách gửi 2 tác vụ giống
nhau trong một truy vấn thì tác vụ thứ hai chỉ được thực hiện khi tác vụ đầu tiên được thực hiện sau đề tránh xảy ra hiện tượng tình huống tương tranh (race conditions)
Mệnh đề param: dafa_value sẽ xác định các tham số và giá trị của các tham số đó cho tác vụ Giống với guery, máy khách có thể trực tiếp cung cấp giá trị các tham số hoặc cung cấp giá trị tham số thông qua các biến
Mệnh đề ƒields xác định các trường máy khách cần lẫy dữ liệu sau khi thực hiện
tác vụ được thực hiện thành công Mệnh đề này rất hữu ích khi thực hiện tác vụ
thay đổi trên các dữ liệu sẵn có, chăng hạn như khi thay đổi giá trị của một
Trang 33
trường, máy khách có thể thay đổi và lay gid trị mới của trường đó chỉ bằng một truy vân
Dưới đây là ví dụ về một câu mwfafion nhận vào giá trị cho các tham số cho tác vụ
thay đôi dữ liệu và thực hiện truy vấn giá trị của các trường đã thực hiện thay đổi thông
1.1.7 Xac thuc (Validation) Bằng cách sử dụng hệ thống kiểu dữ liệu, GraphQL có thể kiểm tra xem một truy vấn có hợp lệ hay không Khi cần thực hiện các truy vấn lồng nhau phức tạp thì thành phần này sẽ cho phép máy chủ và máy khách có một cách thông báo cho các lập trình viên khi truy vấn không hợp lệ đã được khởi tạo mà không cần phải kiểm tra thời gian chạy của truy vẫn đó Giả sử một câu query không hợp lệ như sau:
"message": "Cannot spread fragment
}
Trang 34
Câu guery trên không hợp lệ do một Fragment khong thé tu tham chiéu dén chinh
nó Một lỗi khác thường xảy ra khiến cho một truy vẫn trở thành đó là gọi đến các
trường không t6n tai trong một kiểu dữ liệu Ví dụ:
# INVALID: favoriteSpaceship does not exist on Character
field \"favoriteSpaceship\" on type
Trong câu guery trên, tác vụ tìm nạp dữ liệu hero sẽ trả về một đối tượng thuộc kiểu
dữ liệu Characfer Tuy nhiên, câu query lại yêu cầu lấy dữ liệu về trường
favoriteSpaceship Trường này không có trong định nghĩa của kiểu dữ liệu Character Vì vậy truy vấn với câu query trên là không họp lệ
Một điều khác cũng cần chú ý là bất cứ khi nào truy vẫn một trường và trường đó
trả về đối tượng không thuộc các kiểu dữ liệu như vô hướng hoặc kiểu liệt kê, lập trình viên cần phải chỉ định đâu là đữ liệu cần lấy từ trường đó Ví dụ:
# INVALID: hero is not a
scalar, so fields are needed
hero
"message": "Field \"hero\" of
selection of subfields Did you mean
\"hero { }\"2",
Trang 35
Trong câu query trén, tac vu tim nap dt li€éu hero sé tra về một đối tượng thuộc kiểu
dữ liệu Character, bao gồm 2 trường là name và apppearsln Tuy nhiên, câu query trên
không hề chỉ ra đâu là trường cần lẫy dữ liệu Vì vậy, truy vẫn với câu g/ery trên là
không hợp lệ
Tương tự như vậy, nếu một trường được định nghĩa là thuộc kiểu đữ liệu vô hướng
thì việc truy vấn các trường con trong trường đó sẽ khiến cho truy vấn trở thành không hợp lệ:
{ "line": 4, "column": 10 }
]
}
] }
Điều cần lưu ý tiếp theo khi khởi tạo một truy vấn là chỉ có thể truy vấn dữ liệu
thuộc các trường đã được định nghĩa trong kiều một kiểu đữ liệu cụ thể Giả sử khi cần
truy vấn trường prừnaryFunction thuộc kiểu dữ liệu Droid Kiểu dữ liệu này sử dụng Interface Character nén sé co các trường đã được định nghĩa trong giao diện Characfer và có thêm trường prừnaryFunction được định nghĩa mới:
Trang 36
# INVALID: primaryFunction does
not exist on Character
ero
primaryFunction
\"Character\" Did you mean to use an inline fragment on \"Droid\"?",
{
"line": 5, "column": 5
Câu guery trên là gọi đến tác vụ tìm nạp hero trả về một đối tượng thuộc kiểu dữ
liệu Character Trường prữnaryFunction là một trường riêng của kiêu dữ liệu Droid va không phải là một trường được định nghĩa hợp lệ trong kiểu dữ liệu Characrer Do đó,
truy vấn với câu gwery trên là không hợp lệ Đề giải quyết vấn đề này, lập trình viên có
thé str dung Inline fragment dé viét cau query hop 1é
1.1.8 Thực thi (Execution)
Sau khi xác thực là hợp lệ, truy vẫn sẽ được máy chủ GraphQL thực thi và trả về
kết quả dựa theo hình dạng của truy vẫn Thông thường kết quả sẽ được trả về cho máy khách dưới dạng JSON
GraphQL sẽ không thể thực thi truy vấn nếu không có lược đồ được tạo thành bởi
hệ thống kiểu dữ liệu Mỗi trường trong truy vấn có thể được coi là một hàm hoặc một
phương thức của một kiểu dữ liệu nào đó Các trường trong một kiểu dữ liệu sẽ được bồ trợ bởi một hàm được gọi là hàm xử lý (resoi»er) Các hàm xử lý này sẽ do lập trình
viên tạo ra băng các ngôn ngữ lập trình Khi một trường được thực thi, máy chủ sẽ thực
hiện hàm xử lý tương ứng cho trường đó đề trả về dữ liệu cho máy khách
Nếu một trường trả về kiểu dữ liệu vô hướng nhu String hay Int thi quá trình thực
thi sẽ hoàn tất Tuy nhiên, nếu một trường trả về một đối tượng thì truy vẫn sẽ cần phải
chứa các trường thuộc kiểu đữ liệu của đối tượng đó Điều này sẽ lặp lại cho đến khi đạt được các giá trị vô hướng Việc thực thi các truy vẫn GraphQL, chỉ dừng lại khi tất
cả các trường đều nhận giá trị là một giá trị vô hướng