Hiện tại trang medium.com khá là khó truy cập ở Việt Nam, mọi người muốn truy cập hầu như đều phải dùng đến VPN.
Cũng không rõ nguyên nhân là gì, nhưng mình nghĩ là có thể làm một công cụ để proxy request đến Medium và trả về nội dung để có thể xem được. Ý tưởng này không phải của mình, trước đó có một site là medium0.com đã làm rồi, mình cũng sử dụng được một thời gian, nhưng gần đây thì không dùng được nữa, không biết là do chi phí duy trì hay vấn đề gì khác. Do đó, mình sẽ tự làm một cái để dùng cũng như chia sẻ với bạn bè. Nếu có vấn đề về bản quyền hay bất cứ vấn đề gì khác thì mình sẽ đóng lại, chỉ để dùng một mình thôi.
Trước khi bắt tay vào code thì cùng ngâm cứu xem để làm được công cụ này thì mình cần xử lý những vấn đề gì. Luồng tổng quan sẽ như thế này:
Tiếp theo là đi xem thử một bài xem nội dung Medium đang trả ra thế nào. Mình thử với bài này: https://medium.com/upday-devs/kubernetes-on-a-high-traffic-environment-3-key-takeaways-39d3852fb515. À từ đoạn này phải bật VPN lên nhé.
Xem qua source và test thử thì thấy Medium render từ server rồi, mấy cái JS kia không cần load cũng được luôn. Vậy công việc của mình là chỉ cần lấy HTML này và trả về cho user luôn, không phải xử lý gì thêm.
Cách để proxy requests thì mình dùng cách giống với đã làm ở phần Custom domain cho Uptimerobot, nginx muôn năm.
Để cấu hình nginx proxy request đến medium.com thì cũng khá đơn giản, chỉ cần cấu hình proxy_pass và proxy_ssl_server_name on;
server {
listen 80 default_server;
server_name _;
location / {
proxy_pass https://medium.com;
proxy_ssl_server_name on;
}
}Do mình chạy Nginx bằng docker container và chỉ có một server block nên không cần phải cấu hình server_name. Ngoài ra, mình có sử dụng OrbStack để chạy docker trên MacOS nên chỉ cần chạy nginx container với tên là mediumz thì có thể truy cập qua domain: https://mediumz.orb.local/.
Thử ngay với bài ở trên: https://mediumz.orb.local/upday-devs/kubernetes-on-a-high-traffic-environment-3-key-takeaways-39d3852fb515
Tada, được luôn rồi nè. Nhưng chớ vội mừng, phải kiểm tra thêm xem mấy cái ảnh trên trang là dùng domain nào, nếu tắt VPN đi thì có xem được không.
Inspect lên thì thấy Medium dùng domain miro.medium.com cho link ảnh. Thử tắt VPN đi xem thử và kết quả là không tải được ảnh.
Để proxy được cả link ảnh thì sẽ cần làm 2 việc:
- Khi trả ra HTML thì thay thế tất cả link
miro.medium.comthànhmiro.mediumz.orb.local - Update nginx để proxy request đến
miro.medium.com
Nginx config được sửa thành
server {
listen 80 default_server;
server_name _;
location / {
proxy_pass https://medium.com;
proxy_ssl_server_name on;
proxy_set_header Accept-Encoding "";
sub_filter 'miro.medium.com' 'miro.mediumz.orb.local';
sub_filter_once off;
}
}
server {
listen 80;
server_name miro.mediumz.orb.local;
location / {
proxy_pass https://miro.medium.com;
proxy_ssl_server_name on;
}
}Mình dùng hàm sub_filter của module ngx_http_sub_module sẽ thay thế tất cả (sub_filter_once off;) miro.medium.com thành miro.mediumz.orb.local. Chú ý mình có set thêm Accept-Encoding ""; vào proxy request để response trả về từ medium.com là dạng plain text thì mới replace được.
Còn proxy request đến miro.medium.com thì đơn giản rồi, mình không giải thích thêm.
Kết quả sau khi sửa config, link ảnh đã được thay thế bằng link proxy, đảm bảo sẽ tải được ảnh mà không cần VPN.
Đến đây là xong mất tiêu rồi, mỗi tội là chưa đủ 100 dòng code. Thôi bonus thêm Dockerfile để build image nginx kèm ngx_http_sub_module vậy:
# Dockerfile
FROM nginx:stable as builder
WORKDIR /tmp
RUN export nginx_version=$(nginx -v 2>&1 | awk '{split($0, a); print a[3]}' | awk '{split($0, a, "/"); print a[2]}') && \
apt-get update && \
apt-get install -y curl gnupg2 ca-certificates lsb-release git gcc libpcre3 libpcre3-dev zlib1g zlib1g-dev build-essential && \
echo "deb http://nginx.org/packages/debian `lsb_release -cs` nginx" \
| tee /etc/apt/sources.list.d/nginx.list && \
curl -fsSL https://nginx.org/keys/nginx_signing.key | apt-key add - && \
git clone https://github.com/yaoweibin/ngx_http_substitutions_filter_module.git && \
curl https://nginx.org/download/nginx-$nginx_version.tar.gz -o nginx.tar.gz && \
echo https://nginx.org/download/nginx-$nginx_version.tar.gz && \
tar -xzvf nginx.tar.gz && \
cd nginx-$nginx_version && ./configure --with-compat --add-dynamic-module=../ngx_http_substitutions_filter_module && make modules && \
cp /tmp/nginx-$nginx_version/objs/ngx_http_subs_filter_module.so /tmp/ngx_http_subs_filter_module.so
FROM nginx:stable-alpine as runner
COPY --from=builder /tmp/ngx_http_subs_filter_module.so /etc/nginx/modules/
COPY templates /etc/nginx/templatesVà cuối cùng vẫn chưa được 100 dòng code 😀
Code mình có để ở trên github, mọi người cùng tham khảo. Tuy nhiên đây chỉ là source code demo cho bài viết này thôi nhé.