UTL_HTTP Package trong Oracle 11g
1. Giới thiệu sơ lược về Package. a. Khái niệm Package là một tập hợp các kiểu dữ liệu, biến lưu giữ giá trị và các thủ tục, hàm có mối liên hệ với nhau, được gộp chung lại. Đặc điểm nổi bật nhất của package là khi một phần tử trong package được gọi thì toàn bộ nội dung của package sẽ được ...
1. Giới thiệu sơ lược về Package.
a. Khái niệm
- Package là một tập hợp các kiểu dữ liệu, biến lưu giữ giá trị và các thủ tục, hàm có mối liên hệ với nhau, được gộp chung lại.
- Đặc điểm nổi bật nhất của package là khi một phần tử trong package được gọi thì toàn bộ nội dung của package sẽ được nạp vào trong hệ thống. Do đó, việc gọi tới các phần tử khác trong package sau này sẽ không phải mất thời gian nạp lại vào hệ thống, giúp nâng cao tốc độ thực hiện lệnh của toàn bộ hàm, thủ tục có trong package.
b. Cấu trúc của package
Một package có cấu trúc gồm 2 phần:
• Phần mô tả (specification): Định nghĩa các giao tiếp có thể có của package với bên ngoài. • Phần thân (body): Là phần cài đặt cho các giao tiếp có trong phần mô tả trên.
c. Sử dụng:
- Sử dụng package khi các kiểu dữ liệu, biến lưu giữ giá trị và các thủ tục, hàm có mối liên hệ với nhau.
- Package giúp:
- Đơn giản trong việc thiết kế ứng dụng: tất cả các thông tin cần thiết đều được đặt trong phần đặc tả của package. Nội dung phần này có thể được soạn thảo và biên dịch độc lập với phần thân của package. Do đó, các hàm hay thủ tục gọi tới các thành phần của package có thể được biên dịch tốt.
- Ẩn thông tin: Package cho phép sử dụng các thành phần bên trong dưới dạng public hay private. Tùy theo thiết kế, ta có thể truy cập hay ẩn dấu thông tin. Từ đó, có thể bảo vệ được tính năng toàn vẹn dữ liệu.
- Nâng cao hiệu suất sử dụng: Ngay khi gọi một hàm hay thủ tục bất kỳ trong package lần đầu tiên, toàn bộ nội dung của package sẽ được nạp vào bộ nhớ. Do vậy, các hàm và thủ tục con trong package gọi đến sau có thể thực hiện ngay mà không cần nạp lại bộ nhớ. Làm giảm thao tác truy xuất vào, ra, nâng cao tốc độ.
- ...
2. UTL_HTTP package.
a. Tổng quan
- Với UTL_HTTP package, có thể viết các chương trình bằng PL/SQL dùng để giao tiếp với Webserver(dùng giao thức HTTP).
- UTL_HTTP package có khả năng truy cập tài nguyên trên HTTPS cũng như HTTP.
- Bao gồm các hàm REQUEST, REQUEST_PIECES để lấy địa chỉ trang web, kết nối tới trang và trả về dữ liệu lấy từ trang web.
b. Các hằng số:
- HTTP Version: có kiểu dữ liệu là varchar2(10), được dùng trong hàm BEGIN_REQUEST. Gồm có: • HTTP_VERSION_1_0: • HTTP_VERSION_1:
- Port: • Cổng mặc định của giao thức HTTP(DEFAULT_HTTP_PORT) là 80. • Cổng mặc định của giao thức HTTPS (DEFAULT_HTTPS_PORT) là 443.
- Một số hằng số trạng thái: đều có kiểu dữ liệu là PLS_INTEGER(tham khảo trong link https://docs.oracle.com/cd/B19306_01/appdev.102/b14258/u_http.htm#i1012366)
c. Các loại dữ liệu:
- REQ Type: sử dụng kiểu Record trong PL/SQL để chứa một HTTP request. • Cú pháp:
TYPE req IS RECORD ( url VARCHAR2(32767),--địa chỉ trang web method VARCHAR2(64), http_version VARCHAR2(64));
• Các thông tin trả về cho req ở trạng thái chỉ đọc, sự thay đổi giá trị các thuộc tính trong bản ghi không ảnh hưởng đến yêu cầu.
- Kiểu RESP: sử dụng kiểu Record trong PL/SQL để chứa một phản hồi HTTP. • Cú pháp:
TYPE resp IS RECORD ( status_code PLS_INTEGER, reason_phrase VARCHAR2(256), http_version VARCHAR2(64));
Trong đó: Status_code: mã trạng thái được trả về bởi Web server, là số nguyên có 3 chữ số, đại diện cho kết quả của việc xử lý các yêu cầu từ web server. Reason_phrase: các đoạn văn bản để mô tả cho status code được trả về bởi web server. http_version: phiên bản của giao thức HTTP.
- Kiểu Cookie và Cookie table: • Cookie có kiểu record trong PL/SQL(Cookie là các tệp mà trang web đã truy cập, lưu trữ thông tin duyệt Web).
TYPE cookie IS RECORD ( name VARCHAR2(256), value VARCHAR2(1024), domain VARCHAR2(256), expire TIMESTAMP WITH TIME ZONE), path VARCHAR2(1024), secure BOOLEAN, version PLS_INTEGER, comment VARCHAR2(1024));
Trong đó:
- Name: tên của HTTP cookie.
- value :giá trị của cookie.
- domain :miền mà cookie có hiệu lực.
- expire : thời gian cookie hết hạn.
- path :các tập hợp con của URL
- Kiểu connection:dùng kiểu record để lưu kết nối cho các máy chủ và các cổng TCP/IP của một kết nối mạng, được giữ bền vững kể cả sau khi request hoàn tất. • Cú pháp:
TYPE connection IS RECORD ( host VARCHAR2(256), port PLS_INTEGER, proxy_host VARCHAR2(256), proxy_port PLS_INTEGER, ssl BOOLEAN);
d. Hoạt động:
- Luồng hoạt động:
e. Một số hàm và thủ tục:
e1 ) Request và Request_pieces:
- Từ chuỗi URL, kết nối với trang web và trả về dữ liệu lấy được từ trang Web đó(thường ở dạng HTML).
- Hàm Request: • Cú pháp:
UTL_HTTP.REQUEST ( url IN VARCHAR2, proxy IN VARCHAR2 DEFAULT NULL, wallet_path IN VARCHAR2 DEFAULT NULL wallet_password IN VARCHAR2 DEFAULT NULL) RETURN VARCHAR2;
Trong đó:
- url: địa chỉ URL của trang Web.
- wallet_path: đường dẫn đến Oracle Wallet chứa chứng chỉ truy cập vào địa chỉ URL.
- wallet_password: mật khẩu truy cập wallet. • Trả về chuỗi có độ dài đến 2000 bytes, hàm này có thể sử dụng trực tiếp trong câu truy vấn SQL. Nếu trang Web được truy cập có dữ liệu hơn 2000 bytes thì hàm REQUEST trả về 2000 bytes đầu tiên. • Ví dụ: Lấy thông tin(dạng HTML) trang Web có địa chỉ: http://guides.rubyonrails.org/working_with_javascript_in_rails.html SELECT UTL_HTTP.REQUEST('http://guides.rubyonrails.org/working_with_javascript_in_rails.html') FROM DUAL; Kết quả:
- Hàm Request_Pieces: • Cú pháp:
TYPE html_pieces IS TABLE OF VARCHAR2(2000) INDEX BY BINARY_INTEGER; UTL_HTTP.REQUEST_PIECES ( url IN VARCHAR2, max_pieces IN NATURAL DEFAULT 32767, proxy IN VARCHAR2 DEFAULT NULL, wallet_path IN VARCHAR2 DEFAULT NULL, wallet_password IN VARCHAR2 DEFAULT NULL) RETURN html_pieces;
• Kết quả: Nội dung của toàn bộ trang Web được trả về thành nhiều phần, mỗi phần lên đến 2000 bytes. Thường được lưu theo kiểu table của PL/SQL. • Ví dụ:
DECLARE x UTL_HTTP.HTML_PIECES; len PLS_INTEGER; i INTEGER; BEGIN x := UTL_HTTP.REQUEST_PIECES('http://guides.rubyonrails.org/working_with_javascript_in_rails.html', 100); DBMS_OUTPUT.PUT_LINE(x.count || ' pieces were retrieved.'); IF x.count < 1 THEN DBMS_OUTPUT.PUT_LINE('0'); ELSE len := 0; FOR i in 1..x.count LOOP DBMS_OUTPUT.PUT_LINE(x(i)); END LOOP; DBMS_OUTPUT.PUT_LINE(i); END IF; END;
e2) Hàm GET_RESPONE:
- Dùng để đọc HTTP response.
- Cú pháp:
UTL_HTTP.GET_RESPONSE ( r IN OUT NOCOPY req) RETURN resp;
e3) Thủ tục READ_LINE:
- Dùng để đọc và trả về nội dung 1 dòng của HTTP response.
- Cú pháp:
UTL_HTTP.READ_LINE( r IN OUT NOCOPY resp, data OUT NOCOPY VARCHAR2 CHARACTER SET ANY_CS, remove_crlf IN BOOLEAN DEFAULT FALSE);
Trong đó: • r: HTTP response • data: nội dung của thân HTTP response. • Remove_crlf: xóa kí tự xuống dòng nếu có giá trị TRUE.
e4) Thủ tục READ_TEXT
- Dùng để đọc và trả về nội dung của HTTP response.
- Cú pháp:
UTL_HTTP.READ_TEXT( r IN OUT NOCOPY resp, data OUT NOCOPY VARCHAR2 CHARACTER SET ANY_CS, len IN PLS_INTEGER DEFAULT NULL);
e5) Thủ tục SET_AUTHENTICATION
- Thủ tục này thiết lập thông tin xác thực trong tiêu đề của HTTP request. Web server cần thông tin này để cấp quyền.
- Cú pháp:
UTL_HTTP.SET_AUTHENTICATION( r IN OUT NOCOPY req, --request username IN VARCHAR2, password IN VARCHAR2, scheme IN VARCHAR2 DEFAULT 'Basic', for_proxy IN BOOLEAN DEFAULT FALSE);
e6) Thủ tục SET_RESPONSE_ERROR_CHECK
- Nếu SET_RESPONSE_ERROR_CHECK được bật(có giá trị true), thì hàm GET_RESPONES sẽ thiết lập các ngoại lệ khi Web server trả về các mã trạng thái của các lỗi(từ 4xx- 5xx).
- Cú pháp:
UTL_HTTP.SET_RESPONSE_ERROR_CHECK ( enable IN BOOLEAN DEFAULT FALSE);
e7) Thủ tục SET_WALLET
- Khi UTL_HTTP giao tiếp với HTTP server thông qua SSL(Secured Socket Layer), HTTP server phải cung cấp một chứng chỉ bản quyền truy cập. Oracle Wallet là bắt buộc khi thực hiện một HTTPS request.
- Để tạo một wallet, dùng Oracle Wallet Manager.
- Cú pháp:
UTL_HTTP.SET_WALLET ( path IN VARCHAR2,--đường dẫn đến wallet password IN VARCHAR2 DEFAULT NULL);--mật khẩu để thiết lập/mở wallet
f) Ví dụ:
a) Trường hợp với các trang web không yêu cầu chứng thực chứng chỉ:
- Thực hiện truy cập và lấy nội dung(dưới dạng HTML) trên trang Web có địa chỉ: http://stackoverflow.com/questions/1235679/ora-29270-too-many-open-http-requests
DECLARE req utl_http.req; resp utl_http.resp; value VARCHAR2(1024); BEGIN req := utl_http.begin_request('http://stackoverflow.com/questions/1235679/ora-29270-too-many-open-http-requests'); utl_http.set_header(req, 'User-Agent', 'Mozilla/4.0'); resp := utl_http.get_response(req); LOOP utl_http.read_line(resp, value, TRUE); dbms_output.put_line(value); END LOOP; utl_http.end_response(resp); EXCEPTION WHEN utl_http.end_of_body THEN utl_http.end_response(resp); WHEN UTL_HTTP.TOO_MANY_REQUESTS THEN UTL_HTTP.END_RESPONSE(resp); END;
Kết quả: