Protect Foodsafety Korea recall lookups with HTTPS

Review feedback found the MFDS food-safety helper and published
examples were still sending Foodsafety Korea recall traffic over
plain HTTP even though the upstream host already supports HTTPS.
This follow-up swaps the sample and live recall URLs to HTTPS and
adds narrow regressions that lock both the helper constants and
documented sample links against transport regressions.

Constraint: Keep the change limited to the approved PR #86 transport-safety follow-up
Rejected: Broader MFDS helper refactor | unnecessary for the HTTPS-only fix
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep Foodsafety Korea recall URLs on HTTPS in both helper constants and published examples, including API-key paths
Tested: python3 scripts/mfds_drug_safety.py --help; python3 scripts/mfds_drug_safety.py interview --question '타이레놀이랑 판콜 같이 먹어도 되나요?' --symptoms '두드러기와 어지러움'; python3 scripts/mfds_food_safety.py --help; python3 scripts/mfds_food_safety.py interview --question '이 김밥 먹어도 되나요?' --symptoms '복통과 설사'; python3 scripts/mfds_food_safety.py search --query '대장균' --sample-recalls --limit 1; PYTHONPATH=.:scripts python3 -m unittest scripts.test_mfds_drug_safety scripts.test_mfds_food_safety; node --test scripts/skill-docs.test.js; npm run ci
Not-tested: Live Foodsafety Korea authenticated recall lookup with an approved API key
This commit is contained in:
Jeffrey (Dongkyu) Kim 2026-04-08 23:08:30 +09:00
commit 40e0ad31b7
6 changed files with 19 additions and 5 deletions

View file

@ -23,7 +23,7 @@
- 부적합 식품 endpoint: `https://apis.data.go.kr/1471000/PrsecImproptFoodInfoService03/getPrsecImproptFoodList01`
- 식품안전나라 회수·판매중지 문서: `https://www.data.go.kr/data/15074318/openapi.do`
- 식품안전나라 API 안내: `https://www.foodsafetykorea.go.kr/api/openApiInfo.do?menu_grp=MENU_GRP31&menu_no=661&show_cnt=10&start_idx=1&svc_no=I0490&svc_type_cd=API_TYPE06`
- 식품안전나라 회수 sample: `http://openapi.foodsafetykorea.go.kr/api/sample/I0490/json/1/5`
- 식품안전나라 회수 sample: `https://openapi.foodsafetykorea.go.kr/api/sample/I0490/json/1/5`
## 권장 인터뷰 질문

View file

@ -36,7 +36,7 @@
- 식약처 부적합 식품 endpoint: https://apis.data.go.kr/1471000/PrsecImproptFoodInfoService03/getPrsecImproptFoodList01
- 공공데이터포털 식품 회수·판매중지 정보: https://www.data.go.kr/data/15074318/openapi.do
- 식품안전나라 I0490 안내: https://www.foodsafetykorea.go.kr/api/openApiInfo.do?menu_grp=MENU_GRP31&menu_no=661&show_cnt=10&start_idx=1&svc_no=I0490&svc_type_cd=API_TYPE06
- 식품안전나라 I0490 sample: http://openapi.foodsafetykorea.go.kr/api/sample/I0490/json/1/5
- 식품안전나라 I0490 sample: https://openapi.foodsafetykorea.go.kr/api/sample/I0490/json/1/5
- KRX OPEN API 메인: https://openapi.krx.co.kr/contents/OPP/MAIN/main/index.cmd
- KRX 종목 기본정보 API (KOSPI): http://data-dbg.krx.co.kr/svc/apis/sto/stk_isu_base_info
- KRX 일별 매매정보 API (KOSPI): http://data-dbg.krx.co.kr/svc/apis/sto/stk_bydd_trd

View file

@ -55,7 +55,7 @@ red flag 가 있으면 식품 조회보다 **즉시 응급실·119·의료진
- 부적합 식품 endpoint: `https://apis.data.go.kr/1471000/PrsecImproptFoodInfoService03/getPrsecImproptFoodList01`
- 식품안전나라 회수·판매중지 문서: `https://www.data.go.kr/data/15074318/openapi.do`
- 식품안전나라 API 안내: `https://www.foodsafetykorea.go.kr/api/openApiInfo.do?menu_grp=MENU_GRP31&menu_no=661&show_cnt=10&start_idx=1&svc_no=I0490&svc_type_cd=API_TYPE06`
- 식품안전나라 회수 sample: `http://openapi.foodsafetykorea.go.kr/api/sample/I0490/json/1/5`
- 식품안전나라 회수 sample: `https://openapi.foodsafetykorea.go.kr/api/sample/I0490/json/1/5`
## Workflow

View file

@ -12,8 +12,8 @@ from html import unescape
from typing import Any
IMPROPER_FOOD_ENDPOINT = "https://apis.data.go.kr/1471000/PrsecImproptFoodInfoService03/getPrsecImproptFoodList01"
FOOD_RECALL_SAMPLE_URL = "http://openapi.foodsafetykorea.go.kr/api/sample/I0490/json/{start}/{end}"
FOOD_RECALL_LIVE_URL = "http://openapi.foodsafetykorea.go.kr/api/{api_key}/I0490/json/{start}/{end}"
FOOD_RECALL_SAMPLE_URL = "https://openapi.foodsafetykorea.go.kr/api/sample/I0490/json/{start}/{end}"
FOOD_RECALL_LIVE_URL = "https://openapi.foodsafetykorea.go.kr/api/{api_key}/I0490/json/{start}/{end}"
class ApiError(RuntimeError):

View file

@ -1914,6 +1914,7 @@ test("MFDS public-health skill docs require interview-first safety flow and offi
const foodSkill = read(path.join("mfds-food-safety", "SKILL.md"));
const drugFeatureDoc = read(path.join("docs", "features", "mfds-drug-safety.md"));
const foodFeatureDoc = read(path.join("docs", "features", "mfds-food-safety.md"));
const sources = read(path.join("docs", "sources.md"));
for (const doc of [drugSkill, drugFeatureDoc]) {
assert.match(doc, /증상.*바로 단정하지 말고.*먼저 되묻/);
@ -1931,5 +1932,10 @@ test("MFDS public-health skill docs require interview-first safety flow and offi
assert.match(doc, /I0490/);
assert.match(doc, /DATA_GO_KR_API_KEY/);
assert.match(doc, /python3 scripts\/mfds_food_safety\.py/);
assert.match(doc, /https:\/\/openapi\.foodsafetykorea\.go\.kr\/api\/sample\/I0490\/json\/1\/5/);
assert.doesNotMatch(doc, /http:\/\/openapi\.foodsafetykorea\.go\.kr/);
}
assert.match(sources, /https:\/\/openapi\.foodsafetykorea\.go\.kr\/api\/sample\/I0490\/json\/1\/5/);
assert.doesNotMatch(sources, /http:\/\/openapi\.foodsafetykorea\.go\.kr/);
});

View file

@ -1,6 +1,8 @@
import unittest
from scripts.mfds_food_safety import (
FOOD_RECALL_LIVE_URL,
FOOD_RECALL_SAMPLE_URL,
build_food_interview,
filter_food_items,
normalize_food_recall_row,
@ -86,5 +88,11 @@ class FoodServiceKeyResolutionTest(unittest.TestCase):
self.assertEqual(resolve_data_go_service_key(None, env={"DATA_GO_KR_API_KEY": "xyz"}), "xyz")
class FoodRecallTransportTest(unittest.TestCase):
def test_food_recall_urls_use_https(self):
self.assertTrue(FOOD_RECALL_SAMPLE_URL.startswith("https://"))
self.assertTrue(FOOD_RECALL_LIVE_URL.startswith("https://"))
if __name__ == "__main__":
unittest.main()