Ngiêm cấm sử đụng PROXY và VPS vào mục đích trái pháp luật bạn sẽ phải chịu toàn bộ trách nhiệm trước pháp luật khi sử dụng dịch vụ của chúng tôi tks!
HTTP Early Hints 103 trong proxy: timeline và giới hạn

HTTP Early Hints 103 trong proxy: timeline và giới hạn client

Chuyên viên Kỹ thuật ProxyVN 04-01-2026 Đang tính... phút đọc

HTTP Early Hints 103 trong proxy là chuyện một phản hồi tạm thời 103 đi qua proxy trước phản hồi cuối, và mỗi client, mỗi proxy xử lý nó theo cách riêng. Crawler cần biết điều này vì có client coi 103 là kết quả cuối, trả về body rỗng mà không báo lỗi gì. ProxyVN dựng một origin bằng socket gửi 103 rồi mới gửi 200, ba kiểu proxy tự viết, rồi đo timeline với socket thô, http.client, requests, httpx và curl thật trên Windows.

HTTP Early Hints 103 trong proxy: mục tiêu và phạm vi không lặp

Phần này chốt bài toán, đầu ra và ranh giới.

Bài toán cần giải

Một crawler chạy ổn nhiều tháng. Một ngày, trang chủ của một website bắt đầu trả về rỗng, mã 103, tỷ lệ lưu thành công tụt hẳn. Không có lỗi mạng, không có lỗi proxy. Website vừa bật Early Hints trên CDN, và thư viện của crawler đọc 103 như phản hồi cuối. Không ai nghĩ tới mã 1xx khi xem log.

Đầu ra nghiệm thu

Đầu ra là timeline từng phản hồi theo mili giây: lúc nhận 103, lúc nhận phản hồi cuối, số byte body. Timeline đo trên năm đường đi: thẳng tới origin, hai lần 103, qua proxy chuyển byte, qua proxy dùng http.client, qua proxy dùng httpx. Kèm theo là bảng hành vi của từng client và quy tắc lưu kết quả cho crawler.

Ranh giới với bài mã lỗi

Bài không phải bài giải thích mã lỗi HTTP. 103 là phản hồi thông tin, không phải lỗi, không phải kết quả. Phản hồi cuối mới mang mã trạng thái thật của request. Bài tập trung vào khoảng giữa hai phản hồi, nơi client và proxy có thể làm sai.

Không giả định mọi proxy chuyển tiếp

Chuẩn HTTP yêu cầu proxy chuyển tiếp phản hồi 1xx, nhưng thực tế có proxy làm, có proxy không. Bài không khẳng định proxy thương mại cụ thể nào hỗ trợ 103. Lab chỉ dựng ba kiểu proxy tiêu biểu để thấy ba kết quả khác nhau, rồi chỉ cách kiểm proxy thật của anh em.

Giới hạn của lab

Origin là máy chủ socket tự viết ở 127.0.0.1:9791, gửi 103 rồi chờ 0,6 giây mới gửi 200. Ba proxy cũng tự viết. Lab chỉ dùng HTTP/1.1 không mã hóa. Thứ thật trong lab là http.client của Python 3.12.10, requests 2.34.2 trên urllib3 2.8.0, httpx 0.28.1 trên h11 0.16.0, và curl 8.13.0 có sẵn trên Windows.

Ai nên đọc

Người viết crawler bằng Python dùng requests hoặc urllib. Người vận hành proxy chuyển tiếp cho đội dữ liệu. Người thấy mã 103 trong log và chưa biết nó từ đâu ra.

Quan sát HTTP Early Hints 103 trong proxy trước response cuối và giới hạn client

Phần này tóm tắt chuẩn, chỉ giữ ý cần cho crawler và proxy.

Định nghĩa 103

Theo RFC 8297, mã 103 Early Hints cho client biết server có khả năng sẽ gửi phản hồi cuối với các header có trong phản hồi tạm này. Mục đích chính là gửi sớm header Link với rel=preload, để trình duyệt tải trước CSS, JavaScript trong khi server còn đang tạo trang.

Chỉ là gợi ý

RFC nói header trong 103 chỉ là gợi ý, không thay header của phản hồi cuối. Việc đánh giá 103 ngoài mục đích tối ưu hiệu năng không được ảnh hưởng tới cách xử lý phản hồi cuối. Client không được hiểu header trong 103 như metadata của chính phản hồi 103.

Có thể có nhiều 103

Nhiều 103 trước phản hồi cuối

Nhiều 103 trước phản hồi cuối

RFC cho phép server gửi nhiều 103 trước phản hồi cuối, mỗi cái thêm header mới khi có thông tin. Header trong 103 có thể không xuất hiện trong phản hồi cuối, hoặc được thay bằng giá trị khác. Lab có ca hai lần 103 để kiểm client không dừng ở cái đầu.

Quy tắc chung của 1xx

Theo RFC 9110 mục 15.2, phản hồi 1xx kết thúc ở cuối phần header, không có body. Client phải parse được một hoặc nhiều phản hồi 1xx trước phản hồi cuối, kể cả khi không chờ. User agent có thể bỏ qua 1xx không mong đợi. Server không được gửi 1xx cho client HTTP/1.0.

Proxy phải chuyển tiếp

RFC 9110 cùng mục nói proxy phải chuyển tiếp phản hồi 1xx, trừ khi chính proxy yêu cầu tạo ra nó. Ví dụ proxy tự thêm Expect: 100-continue thì không cần chuyển 100 Continue. 103 do origin gửi không thuộc ngoại lệ này, nên proxy đúng chuẩn phải chuyển tới client.

103 không có body

Vì 1xx kết thúc ở cuối phần header, client đọc 103 không có gì để đọc thêm. Một thư viện coi 103 là phản hồi cuối sẽ không biết body dài bao nhiêu, vì 103 không có Content-Length. Thư viện phải chọn: coi body rỗng, hoặc đọc tới khi đóng kết nối. Cả hai đều sai với phản hồi 200 đang đến sau.

Rủi ro với client HTTP/1.1 cũ

RFC 8297 có phần bảo mật: client HTTP/1.1 xử lý sai phản hồi tạm như phản hồi cuối có thể coi mọi phản hồi sau trên cùng kết nối là phần của phản hồi cuối. Với client dùng chung một kết nối cho nhiều origin, đây có thể là lỗ hổng lộ thông tin chéo. Vì vậy server có thể không gửi 103 qua HTTP/1.1 nếu không biết client xử lý đúng.

RFC thuộc loại thử nghiệm

RFC 8297 có trạng thái Experimental. Trình duyệt hiện đại hỗ trợ 103, và nhiều CDN có tính năng gửi Early Hints. Điều đó không có nghĩa thư viện HTTP dùng trong crawler cũng hỗ trợ. Phần lab sẽ cho thấy khoảng cách này.

Ai gửi 103 trong thực tế

103 thường do CDN hoặc reverse proxy phía website gửi, dựa trên header Link đã biết từ các lần trước, trong lúc origin còn đang tạo trang. RFC 8297 có nhắc trường hợp intermediary có cache tạo 103 từ một phản hồi cũ trong khi đi xác thực lại với origin. Website có thể bật tính năng này mà không đổi gì ở origin.

Bảng các mã 1xx

Bảng dưới gom các mã 1xx crawler có thể gặp.

Bảng: Bảng các mã 1xx

Mã

Tên

Khi nào

Crawler cần làm

100

Continue

Client gửi Expect: 100-continue

Thư viện thường tự xử lý

101

Switching Protocols

Nâng cấp lên WebSocket

Chỉ khi client yêu cầu

103

Early Hints

Server gửi gợi ý sớm

Bỏ qua, chờ phản hồi cuối

Dựng origin lab gửi HTTP Early Hints 103 trong proxy trước response cuối

Phần này dựng origin, chạy thật trên Python 3.12.10.

Origin bằng socket

http.server của Python không có cách gửi 1xx tùy ý thuận tiện, nên origin dùng socket thô. Origin đọc request, gửi 103 với hai header Link, ngủ 0,6 giây, rồi gửi 200 với body HTML 57 byte và Connection: close.

EH = (b"HTTP/1.1 103 Early Hints\r\n"
      b"Link: </style.css>; rel=preload; as=style\r\n"
      b"Link: </app.js>; rel=preload; as=script\r\n\r\n")
 
def origin(conn):
    req = read_head(conn)
    first = req.split(b"\r\n", 1)[0]
    if b"HTTP/1.1" in first and b"/no-hints" not in first:
        conn.sendall(EH)
        if b"/two" in first:
            time.sleep(0.2)
            conn.sendall(b"HTTP/1.1 103 Early Hints\r\nLink: </font.woff2>; rel=preload; as=font\r\n\r\n")
    time.sleep(DELAY)
    conn.sendall(FINAL); conn.close()

Đường dẫn /two gửi hai lần 103, cách nhau 0,2 giây.

Không gửi 103 cho HTTP/1.0

Origin chỉ gửi 103 khi dòng request có HTTP/1.1, theo quy tắc của RFC 9110. Lab gửi một request HTTP/1.0 bằng socket thô, nhận đúng một phản hồi 200 sau 594 mili giây, không có 103.

Thời gian chờ 0,6 giây

Origin chờ 0,6 giây giữa 103 và 200 để mô phỏng thời gian tạo trang. Trên website thật, khoảng này có thể từ vài chục mili giây tới vài giây. Khoảng càng dài, lợi ích tải trước của trình duyệt càng lớn, và crawler đọc sai 103 càng trả về sớm một cách đáng ngờ.

Phản hồi cuối

Phản hồi 200 có Content-Type text/html, một header Link cho style.css, Content-Length 57 và Connection: close. Header Link trong phản hồi cuối ít hơn trong 103, đúng tinh thần RFC: 103 chỉ là dự đoán, phản hồi cuối có thể khác.

Client socket thô đo timeline

Để thấy chính xác byte nào đến lúc nào, lab viết một client socket đọc từng khối header, ghi thời điểm và mã. Client này không có logic HTTP nào ngoài tách header bằng dòng trống, nên nó cho thấy đúng thứ đi trên dây.

def raw_timeline(port, target, ver="HTTP/1.1"):
    s = socket.create_connection(("127.0.0.1", port)); t0 = time.monotonic()
    s.sendall(f"GET {target} {ver}\r\nHost: 127.0.0.1\r\n\r\n".encode())
    buf, events = b"", []
    while True:
        c = s.recv(4096)
        if not c:
            break
        buf += c
        while b"\r\n\r\n" in buf and (not events or events[-1][1] < 200):
            head, buf = buf.split(b"\r\n\r\n", 1)
            st = int(head.split(b" ")[1])
            events.append((round((time.monotonic() - t0) * 1000), st))
    return events, len(buf)

Mã đầy đủ trong lab còn đếm số header Link trong mỗi phản hồi.

Timeline thẳng tới origin

Client thô nhận 103 sau 15 mili giây với hai Link, nhận 200 sau 609 mili giây với một Link, body 57 byte. Ca hai lần 103 nhận 103 ở 0 mili giây, 103 thứ hai ở 203 mili giây, 200 ở 797 mili giây. Thời gian chờ do lab đặt, chỉ để hai phản hồi tách nhau rõ.

Đọc header bằng dòng trống

Mỗi phản hồi HTTP/1.1 kết thúc phần header bằng một dòng trống. Client thô tách theo dòng trống, đọc mã ở dòng đầu, và chỉ dừng tách khi gặp mã từ 200 trở lên. Phần còn lại sau phản hồi cuối là body. Cách này đơn giản nhưng đủ cho lab, vì phản hồi cuối có Connection: close.

Ba kiểu proxy

Proxy relay ở cổng 9792 đọc request, đổi URL đầy đủ thành đường dẫn, mở kết nối tới origin rồi chuyển byte nguyên văn về client. Proxy ở cổng 9793 dùng http.client gọi origin, đọc phản hồi mà http.client trả về, rồi dựng phản hồi mới cho client. Proxy ở cổng 9794 làm tương tự nhưng dùng httpx.

Proxy lab không qua mạng thật

Cả ba proxy chạy trên cùng máy với origin và client. Không có độ trễ mạng, không có mất gói. Timeline vì vậy chủ yếu phản ánh thời gian chờ do origin đặt và thời gian xử lý của từng proxy. Proxy httpx thêm khoảng 280 mili giây so với gọi thẳng, phần lớn do tạo client mới cho mỗi request.

Vì sao chọn ba kiểu này

Proxy chuyển byte đại diện cho proxy tầng thấp, hoặc tunnel CONNECT với HTTPS. Hai proxy còn lại đại diện cho proxy viết bằng thư viện HTTP cấp cao, kiểu hay gặp trong công cụ nội bộ. Proxy thương mại thường phức tạp hơn nhiều, nhưng hành vi với 1xx rơi vào một trong ba nhóm này.

Quan sát hỗ trợ interim response của client và HTTP Early Hints 103 trong proxy

Phần này là kết quả của từng client khi gọi thẳng origin.

http.client trả 103

requests dừng ở 103

requests dừng ở 103

http.client của Python 3.12.10 gửi GET, getresponse trả status 103, read trả 0 byte, header Link là của phản hồi 103. Phản hồi 200 và body 57 byte không bao giờ được đọc.

== 2. http.client (Python 3.12.10)
  status 103 | body 0 B | Link: </style.css>; rel=preload; as=style, </app.js>; rel=preload; as=script

Trong lab, http.client chỉ bỏ qua 100 Continue, các mã 1xx khác được trả về như phản hồi cuối. Kết quả này đúng với phiên bản đã chạy, phiên bản khác có thể đã đổi.

requests cũng trả 103

requests 2.34.2 dựa trên urllib3 2.8.0, mà urllib3 dựa trên http.client. Kết quả: status 103, body 0 byte, thời gian 0,02 giây, history rỗng, không ngoại lệ. requests qua proxy relay cũng trả 103, 0 byte.

== 3. requests 2.34.2
  status 103 | body 0 B | thoi gian 0.02 s | history [] | Link: </style.css>; rel=preload; as=style, </app.js>; rel=preload; as=script
  qua relay: 103 0 B

0,02 giây là dấu hiệu dễ nhận: request trả về nhanh hơn hẳn thời gian origin cần để tạo trang.

Ba request trên một Session

Lab dựng thêm một origin giữ kết nối, chỉ gửi 103 ở request đầu của mỗi kết nối. requests Session gửi ba request liên tiếp, cả ba đều trả 103 với body rỗng. Phía origin, kết nối bị client đóng sau mỗi request, nên mỗi request là một kết nối mới và lại nhận 103.

requests /trang-a -> 103 ''
requests /trang-b -> 103 ''
requests /trang-c -> 103 ''

Lab không thấy phản hồi 200 còn sót bị đọc nhầm sang request sau, vì urllib3 không dùng lại kết nối. Rủi ro mà RFC 8297 nói tới không xuất hiện trong lab này, nhưng mọi request đều mất kết quả.

httpx xử lý đúng

httpx 0.28.1 trả status 200, body 57 byte, header Link của phản hồi cuối. Event hook response chỉ thấy 200, nghĩa là 103 được bỏ qua ở tầng dưới, không lộ lên ứng dụng. Trên origin giữ kết nối, httpx gửi hai request trên cùng kết nối, cả hai nhận 200 với nội dung đúng.

== 4. httpx 0.28.1
  status 200 | body 57 B | event hook thay [200] | Link: </style.css>; rel=preload; as=style
httpx    /trang-a -> 200 'ket qua cua /trang-a (request thu 1 tren ket noi)'
httpx    /trang-b -> 200 'ket qua cua /trang-b (request thu 2 tren ket noi)'

httpx dùng h11 để parse HTTP/1.1, và h11 tách phản hồi thông tin khỏi phản hồi cuối.

curl thấy cả hai

curl 8.13.0 với -i in cả hai dòng trạng thái HTTP/1.1 103 Early Hints và HTTP/1.1 200 OK. Biến http_code của -w cho 200. curl vừa hiển thị 103 cho người xem, vừa dùng phản hồi cuối làm kết quả.

aiohttp và các thư viện khác

Lab chỉ chạy ba thư viện Python và curl. aiohttp, urllib3 bản 1.x, pycurl và các thư viện ở ngôn ngữ khác có thể xử lý khác. Bài không suy rộng. Cách kiểm nhanh nhất là chạy origin socket của lab và gọi bằng thư viện cần kiểm, mất chưa tới một phút.

Bảng hành vi client

Bảng dưới gom kết quả khi gọi thẳng origin.

Bảng: Bảng hành vi client

Client

Mã trả về

Body

Thấy 103?

http.client Python 3.12.10

103

0 byte

Coi là cuối

requests 2.34.2

103

0 byte

Coi là cuối

httpx 0.28.1

200

57 byte

Bỏ qua ở tầng dưới

curl 8.13.0

200

57 byte

In ra với -i

Vì sao lỗi không lộ ra

requests không ném ngoại lệ, mã 103 không phải lỗi theo r.ok, body rỗng là hợp lệ về mặt kỹ thuật. Ba điều này cộng lại làm lỗi im lặng trên giao diện. Chỉ có thống kê kích thước body hoặc thống kê mã trạng thái mới thấy bất thường.

Hệ quả cho crawler

Crawler viết bằng requests gặp website bật 103 sẽ lưu một bản ghi mã 103 với nội dung rỗng. Nếu crawler chỉ kiểm r.ok, 103 nhỏ hơn 400 nên ok là True. Bản ghi rỗng đi thẳng vào kho như một trang hợp lệ.

Ghi timeline HTTP Early Hints 103 trong proxy và status cuối riêng biệt

Phần này là kết quả qua ba kiểu proxy.

Proxy chuyển byte giữ đúng

Ba kiểu proxy

Ba kiểu proxy

Qua proxy relay, client thô nhận 103 ở 0 mili giây và 200 ở 609 mili giây, body 57 byte. Timeline giống hệt khi gọi thẳng. httpx qua relay nhận 200, 57 byte. curl qua relay in cả 103 và 200. Proxy không hiểu HTTP sâu nên không làm hỏng gì.

Proxy dùng http.client làm mất phản hồi cuối

Qua proxy ở cổng 9793, client thô nhận đúng một phản hồi 103 rồi kết nối đóng, body 0 byte. Không có 200 nào. Lý do: http.client trong proxy trả 103 như phản hồi cuối, proxy đóng gói nó, thêm Content-Length 0, gửi cho client rồi đóng.

qua proxy http.client    [(0, 103, 2)] | body 0 B

Lỗi ở đây nằm trong proxy, không phải ở client hay origin. Client dùng thư viện nào cũng chỉ nhận được 103.

Vì sao proxy cấp cao dễ sai

Proxy viết bằng thư viện HTTP cấp cao nhận về một đối tượng phản hồi đã parse, rồi dựng phản hồi mới. Thư viện quyết định giữ hay bỏ 1xx, proxy không có cơ hội chuyển tiếp. Muốn đúng chuẩn, proxy phải dùng thư viện có cơ chế báo phản hồi thông tin, hoặc làm việc ở tầng byte như proxy relay.

Proxy dùng httpx bỏ 103

Qua proxy ở cổng 9794, client thô nhận một phản hồi 200 ở 891 mili giây, body 57 byte, không có 103. Kết quả cuối đúng, nhưng gợi ý sớm bị mất. Với crawler, đây là kết quả chấp nhận được. Với trình duyệt, lợi ích tải trước biến mất.

Bảng timeline

Bảng dưới gom timeline của năm đường đi với client socket thô, đơn vị mili giây tính từ lúc gửi request.

Bảng: Bảng timeline

Đường đi

103 lần 1

103 lần 2

Phản hồi cuối

Body

Thẳng origin

15

không

200 ở 609

57

Thẳng, hai lần 103

0

203

200 ở 797

57

Proxy chuyển byte

0

không

200 ở 609

57

Proxy http.client

0

không

không có

0

Proxy httpx

không

không

200 ở 891

57

Thẳng, request HTTP/1.0

không

không

200 ở 594

57

Phản hồi cuối là thứ duy nhất được lưu. Phản hồi tạm chỉ được ghi vào timeline.

Ghi riêng hai loại sự kiện

Crawler nên ghi hai loại sự kiện tách nhau: các phản hồi thông tin với thời điểm và header, và phản hồi cuối với mã, header, body. Timeline cho thấy proxy nào làm mất gì. Nếu chỉ ghi phản hồi cuối, ca proxy http.client sẽ hiện thành một trang 103 rỗng, không ai biết 200 từng tồn tại.

Đo thời gian tới phản hồi cuối

Thời gian tới byte đầu tiên thường được đo làm chỉ số độ trễ. Với 103, byte đầu tiên đến rất sớm, chỉ số này trông đẹp mà không phản ánh thời gian tạo trang. Crawler nên đo thời gian tới phản hồi cuối. Trong lab, chênh lệch giữa hai mốc là khoảng 600 mili giây.

HTTP/2 khác HTTP/1.1

Trên HTTP/2, 103 là một khung HEADERS riêng trên cùng luồng trước khung HEADERS của phản hồi cuối. Việc đóng khung rõ ràng giúp client ít nhầm hơn, như RFC 8297 có nhắc. httpx chỉ dùng HTTP/2 khi bật tùy chọn và cài thêm gói. Lab không thử HTTP/2.

HTTPS và CONNECT

Với HTTPS qua proxy kiểu CONNECT, proxy chỉ chuyển byte đã mã hóa, giống proxy relay của lab. 103 đi tới client nguyên vẹn. Khi đó mọi chuyện phụ thuộc vào thư viện của client. Đây là lý do bảng hành vi client quan trọng hơn bảng proxy với phần lớn crawler dùng HTTPS.

Kiểm crawler không lưu HTTP Early Hints 103 trong proxy như nội dung hoàn tất

Phần này đưa ra quy tắc lưu và cách sửa cho requests.

Quy tắc lưu

Crawler chỉ lưu phản hồi có mã từ 200 trở lên. Phản hồi 1xx không bao giờ là kết quả. Nếu thư viện trả về 1xx, đó là lỗi của thư viện hoặc của proxy, cần ghi riêng và thử lại bằng đường khác.

def accept(resp_status, body):
    if 100 <= resp_status < 200:
        raise RuntimeError(f"thu vien tra phan hoi tam {resp_status} lam ket qua cuoi")
    return resp_status, body

Hàm này là ví dụ triển khai, chặn đúng ca requests trả 103.

Bản ghi kết quả của lab

Với ca hai lần 103, lab dựng bản ghi gồm mã cuối, thời điểm phản hồi cuối, thời điểm gợi ý đầu, danh sách gợi ý và số byte body. Gợi ý được giữ để chẩn đoán, không gộp vào header của phản hồi cuối.

record: {'status': 200, 't_final_ms': 797, 't_first_hint_ms': 0,
 'hints': ['Link: </style.css>; rel=preload; as=style', 'Link: </app.js>; rel=preload; as=script',
           'Link: </font.woff2>; rel=preload; as=font'], 'body_bytes': 57}

font.woff2 có trong gợi ý nhưng không có trong phản hồi cuối, đúng như RFC cho phép.

Proxy không sửa được lỗi client

Đổi proxy không làm requests đọc đúng 103, vì lỗi nằm trong thư viện. Ngược lại, client đúng như httpx vẫn có thể nhận kết quả hỏng khi đi qua proxy dùng http.client. Phải kiểm cả hai phía, và bảng timeline của lab giúp tách hai nguyên nhân này.

Chọn thư viện

Với website có thể gửi 103, httpx là lựa chọn an toàn hơn requests trong lab này. Đổi thư viện là thay đổi lớn. Cách nhỏ hơn: giữ requests, thêm kiểm mã 1xx như hàm accept, gặp thì thử lại đường dẫn đó bằng httpx. Bài httpx proxy có cách cấu hình proxy cho httpx.

Thử lại không cùng thư viện

Gặp 103 làm kết quả cuối, thử lại bằng requests sẽ nhận lại 103, vì website vẫn bật Early Hints. Thử lại phải đổi thư viện hoặc đổi đường đi. Trong lab, ba lần requests trên Session đều nhận 103, xác nhận thử lại cùng cách là vô ích.

Đừng dùng header Link trong 103 làm dữ liệu

Crawler thu thập liên kết từ header có thể bị cám dỗ đọc Link trong 103. RFC nói các header này chỉ là gợi ý, có thể không đúng với phản hồi cuối. Nếu cần danh sách tài nguyên của trang, đọc từ phản hồi cuối và từ HTML.

Kiểm proxy của anh em

Dựng origin socket như lab, chạy trên một máy mà proxy với tới được. Gọi qua proxy bằng client socket thô và bằng curl -i. Thấy 103 rồi 200 là proxy chuyển tiếp đúng. Chỉ thấy 200 là proxy bỏ 103. Chỉ thấy 103 là proxy đang làm hỏng phản hồi, cần báo người vận hành proxy.

Kích thước body là chỉ số rẻ

Thống kê body 0 byte theo tên miền là cách rẻ nhất để bắt lỗi này, không cần đọc mã trạng thái. Một trang chủ bình thường vài chục KB bỗng thành 0 byte là dấu hiệu rõ ràng, dù nguyên nhân là 103, lỗi parser hay chặn bot.

Theo dõi trong log

Thêm bộ đếm mã 1xx trong kết quả cuối theo tên miền. Bộ đếm này bình thường bằng 0. Tăng lên ở một tên miền là dấu hiệu website vừa bật Early Hints và client đang đọc sai. Tăng lên ở mọi tên miền qua một proxy là dấu hiệu proxy đó đang làm hỏng phản hồi.

Đầu ra nghiệm thu của HTTP Early Hints 103 trong proxy: timeline interim và final response

Phần này gom tiêu chí và giới hạn.

Danh sách kiểm tra

Danh sách nghiệm thu

Danh sách nghiệm thu

Crawler đạt khi mọi dòng dưới đây đúng.

  • Không lưu phản hồi có mã 1xx làm kết quả.
  • Thư viện dùng cho website có 103 đã được kiểm như lab.
  • Timeline ghi riêng phản hồi thông tin và phản hồi cuối.
  • Độ trễ đo tới phản hồi cuối, không tới byte đầu.
  • Header trong 103 không trộn vào header của phản hồi cuối.
  • Proxy đang dùng đã được kiểm có chuyển, bỏ hay làm hỏng 103.
  • Có bộ đếm mã 1xx trong kết quả cuối.

Những gì lab chưa chạy

Chưa thử website hay CDN thật gửi 103. Chưa thử HTTP/2 và HTTP/3, nơi 103 là một khung HEADERS riêng. Chưa thử HTTPS. Chưa thử proxy thương mại, Squid, Nginx. Chưa thử aiohttp, urllib3 bản khác. Thời gian chờ 0,6 giây do lab đặt. Hàm accept là ví dụ triển khai.

Đưa ca 103 vào test

Origin socket của lab nhỏ, chạy trong tiến trình test. Thêm một ca test gọi origin này bằng hàm tải của crawler và kỳ vọng mã 200, body 57 byte. Khi ai đó đổi thư viện hoặc nâng phiên bản, test này bắt ngay nếu hành vi với 103 thay đổi.

Chạy lại trên máy của anh em

Script lab chỉ dùng thư viện chuẩn, requests và httpx. Chạy lại với đúng phiên bản thư viện đang cài trong dự án, so bảng hành vi. Nếu requests hay http.client ở phiên bản của anh em đã trả 200, ghi lại số phiên bản và bỏ hàm accept khỏi danh sách việc cần làm.

Proxy ở đâu trong luồng

Proxy chuyển tiếp phải chuyển 103, theo RFC 9110. Proxy tầng thấp và tunnel HTTPS làm điều này một cách tự nhiên. Khi cần IP tại Việt Nam để thu thập trang trong nước, anh em có thể mua proxy tại trang chủ ProxyVN, rồi kiểm đường đi bằng origin socket như lab. Vai trò của proxy có ở bài Web Scraping proxy là gì, cách ghi chuỗi cấu hình có ở bài định dạng proxy.

HTTP Early Hints 103 trong proxy: câu hỏi thường gặp

Các câu dưới đây gom những điểm hay bị hỏi.

103 có phải lỗi không?

Không. 103 là phản hồi thông tin gửi trước phản hồi cuối. Kết quả thật nằm ở phản hồi sau.

Vì sao requests trả mã 103?

Trong lab, http.client của Python 3.12.10 chỉ bỏ qua 100 Continue và trả 103 như phản hồi cuối. requests dựa trên nó nên cũng trả 103.

httpx có bị ảnh hưởng không?

Không trong lab. httpx 0.28.1 bỏ qua 103 và trả 200 với body đầy đủ.

Proxy có bắt buộc chuyển 103 không?

RFC 9110 yêu cầu proxy chuyển tiếp 1xx. Lab có một proxy bỏ 103 và một proxy làm mất phản hồi cuối.

Header Link trong 103 có dùng được không?

Chỉ như gợi ý. Lab có Link font.woff2 trong 103 mà không có trong phản hồi cuối.

Server có gửi 103 cho mọi client không?

Không nên gửi cho HTTP/1.0. Lab không nhận 103 khi gửi request HTTP/1.0.

Đo độ trễ thế nào khi có 103?

Đo tới phản hồi cuối. Byte đầu tiên đến từ 103, sớm hơn khoảng 600 mili giây trong lab.

HTTP Early Hints 103 trong proxy và những điều cần nhớ

HTTP Early Hints 103 trong proxy là phản hồi tạm, không bao giờ là kết quả. Kiểm thư viện của crawler, ghi timeline tách hai loại phản hồi, không lưu mã 1xx, và kiểm proxy chuyển, bỏ hay làm hỏng 103. Proxy.vn - Nhà cung cấp dịch vụ proxy chất lượng hàng đầu Việt Nam khuyên anh em chạy lại lab với thư viện đang dùng để kiểm HTTP Early Hints 103 trong proxy.

TIN TỨC LIÊN QUAN