fix(utils): check_robots 가 robots.txt 404 를 "가져오지 못함" 으로 오보 — 404 분기가 죽은 코드였다 - #2
Open
Gforce10-design wants to merge 1 commit into
Open
Gforce10-design wants to merge 1 commit into
Gforce10-design wants to merge 1 commit into
Conversation
… 죽은 코드였다
_fetch_robots 가 urllib.request.urlopen 을 그대로 쓰는데, urllib 은 4xx/5xx 에서
반환하지 않고 HTTPError 를 던진다. 그래서 check_robots 의
`if status == 404 or not body.strip(): return result # 제한 없음` 은 영원히
도달하지 못했고, robots.txt 가 없는 사이트(404)가 allowed=True 이면서 error 가
채워진 채로 돌아왔다 — "확인 못 함" 으로 보고된다.
실측 2026-09-01 books.toscrape.com:
{"allowed": true, "error": "robots.txt 를 가져오지 못했습니다: HTTP Error 404: Not Found"}
수정: _fetch_robots 에서 HTTPError 중 404 만 ("", 404) 로 돌려준다. 그 외
HTTPError(5xx)·URLError·timeout·OSError 는 그대로 던진다 — "허용된 것(allowed)"
과 "가져오지 못한 것(error)" 의 구분(SKILL.md Step 2-0)은 그대로 check_robots 몫이다.
모든 HTTPError 를 (body, code) 로 돌리면 5xx 의 HTML 에러 페이지가 Protego 로
들어가 error=None 이 되어 그 구분이 깨진다 — 그래서 404 로만 좁혔다.
왜 기존 테스트가 못 잡았나: test_robots_missing_file_allows 가 _fetch_robots 를
("", 404) 를 *반환* 하도록 모킹했다. 실제 함수는 그 경우 반환하지 않고 던지므로
존재하지 않는 경로를 검증하고 있었다. 새 테스트 3건은 urllib.request.urlopen 을
모킹해 진짜 _fetch_robots 를 태운다(네트워크 없음). 기존 테스트에는
`error is None` 단언을 추가해 계약을 고정했다.
범위 밖(별도 논의): RFC 9309 §2.3.1 은 4xx 전체를 "제한 없음", 5xx 를 "전면
disallow" 로 다루라 한다. 현재 코드는 404 이외 4xx 와 5xx 를 error 로 보고한다.
Co-Authored-By: Claude Code <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KoBwBJZ5FyNxkbcX2RpCZT
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
요약
check_robots()가 robots.txt 가 없는(404) 사이트를 "허용됨" 이 아니라 "가져오지 못함(error 채워짐)" 으로 돌려준다._fetch_robots가urlopen을 그대로 쓰는데 urllib 은 4xx 에서 반환하지 않고HTTPError를 던지므로,check_robots의if status == 404 ... # 제한 없음분기는 도달 불가능한 죽은 코드였다.재현 (upstream
c64cfbf, scrapling 0.4.15)SKILL.md Step 2-0 규칙대로면 에이전트는 이걸 "확인 못 함" 으로 사용자에게 보고한다 — 실제로는 robots.txt 가 없어 제한이 없는데.
원인
scripts/utils.py:350-355_fetch_robots—urlopen호출(354). 4xx/5xx 는HTTPErrorraise.scripts/utils.py:378if status == 404 or not body.strip(): return result— 위 때문에 404 로는 절대 도달 못 함.왜 기존 테스트가 못 잡았나
test_robots_missing_file_allows가_fetch_robots를("", 404)를 반환하도록 모킹한다. 실제 함수는 그 경우 반환하지 않고 던지므로 존재하지 않는 경로를 검증하고 있었다. 게다가error is None을 단언하지 않아 계약이 못 박혀 있지 않았다.수정
_fetch_robots:HTTPError중 404 만("", 404)로 반환. 5xx·URLError·timeout·OSError는 그대로 raise — "허용된 것" 과 "가져오지 못한 것" 의 구분은check_robots가 계속 맡는다.HTTPError를(body, code)로 돌리면 5xx 의 HTML 에러 페이지가Protego.parse로 들어가error=None이 되어 그 구분이 깨진다 → 404 로만 좁혔다.urllib.request.urlopen을 모킹해 진짜_fetch_robots를 태우는 테스트 3건 추가(404 → allowed·error None / 503 → error 유지 / URLError → error 유지). 기존 테스트에error is None단언 추가. 네트워크 호출 없음.검증
1 failed, 8 passed).pytest -q -k "not e2e"→ 418 passed.sync_codex_mirror.py --checkexit 0.범위 밖 (별도 논의 제안)
RFC 9309 §2.3.1 은 4xx 전체를 "제한 없음", 5xx 를 "전면 disallow" 로 다루라 한다. 현재 코드는 404 이외 4xx 와 5xx 를 error 로 보고하고 allowed=True 로 둔다. 계약 변경이라 이 PR 에선 손대지 않았다.
🤖 Generated with Claude Code
https://claude.ai/code/session_01KoBwBJZ5FyNxkbcX2RpCZT