본문 바로가기
빌드노트 검색

빌드노트

명령에 없는 curl 헤더가 붙을 때: -q는 맨 앞에 둔다

명령에 없는 사용자 정의 헤더가 curl 요청에 붙을 때 기본 설정 파일을 판별한다. 같은 실행 파일과 loopback 요청에서 기본 실행, 첫 -q, 뒤쪽 -q를 비교하고 명시적 --config가 계속 적용되는 차이를 확인한다.

curl 스크립트에 -H로 넣은 적 없는 사용자 정의 헤더가 요청에서 보인다면 기본 설정 파일을 의심할 수 있다. curl은 명령행 인자 외에 기본 curlrc 파일에서도 옵션을 읽는다. 같은 요청을 비교할 때 실행 파일 바로 다음의 첫 인자로 -q를 두면 이 파일의 개입을 가려낼 수 있다. 다른 옵션 뒤에 붙인 -q는 같은 대조가 아니다. curl의 -q 설명 (새 탭에서 열림)

같은 실행 파일로 -q 위치만 바꾼다

먼저 문제가 생긴 스크립트와 같은 환경에서 어떤 curl을 실행하는지 확인한다. 다음은 Windows PowerShell용 조회다. 실행 파일을 하나 선택해 이후 요청에서도 같은 경로를 사용한다.

Get-Command curl -All | Select-Object Name, CommandType, Source | Format-List
$curlExe = (Get-Command curl.exe -CommandType Application | Select-Object -First 1).Source
& $curlExe -q --version

실제 비교에 사용한 Windows PowerShell 5.1에서는 curl이라는 별칭과 curl.exe 실행 파일이 함께 보였다. 따라서 이름이 curl이라는 이유만으로 실행 파일의 옵션이 적용됐다고 판단하지 않았다. 버전 출력은 curl 8.21.0 (Windows) libcurl/8.21.0으로 시작했다. 버전 조회에도 첫 인자에 -q를 넣었다.

다음 세 명령은 같은 URL에 같은 GET을 보내면서 -q의 유무와 위치만 바꾼다. 자신이 관리하는 로컬 서버의 읽기 전용 경로가 준비돼 있어야 한다. 8080/health를 그 포트와 경로로 바꾸고, 문제가 된 헤더를 확인하던 서버 로그 등에서 세 요청의 헤더를 비교한다. 아래 명령 자체가 요청 헤더를 출력하는 것은 아니다.

$url = 'http://127.0.0.1:8080/health'
& $curlExe -sS --noproxy '*' --connect-timeout 1 --max-time 3 $url
& $curlExe -q -sS --noproxy '*' --connect-timeout 1 --max-time 3 $url
& $curlExe -sS -q --noproxy '*' --connect-timeout 1 --max-time 3 $url

이 비교의 --noproxy '*'는 로컬 요청이 프록시를 거치지 않게 하는 조건이다. 시간 제한은 응답을 계속 기다리지 않게 한다. 기존 스크립트에 적용할 때도 -q는 공통 옵션 배열의 끝에 추가하지 말고 실행 파일 다음에 별도 인자로 둔다.

이 차이를 확인하기 위해 Windows 11에서 개인 설정과 분리한 실험도 했다. 자식 curl의 CURL_HOME을 새 소유 폴더로 지정하고, 그 안의 .curlrc에는 다음 한 줄만 넣었다. 긴 옵션의 이름, 등호, 인자를 한 줄에 적은 curl 설정 파일 문법이다. 공식 설정 파일 문법 (새 탭에서 열림)

header = "X-Lab: default"

다른 홈 관련 변수도 모두 새 폴더로 지정했고, 실행 파일 폴더로 탐색이 이어져도 개인 설정을 만나지 않도록 시스템 curl의 복사본을 사용했다. 수신기는 127.0.0.1에만 열었다. 위 세 요청과 같은 옵션을 이 수신기의 동일한 /headers 경로로 보내자 다음 응답을 받았다. 이 한 줄은 수신기가 받은 X-Lab 값을 돌려준 응답 본문이며 curl 자체의 진단 문구가 아니다.

  • 기본 실행: X-Lab=default
  • 첫 인자에 -q: X-Lab=<absent>
  • -sS 다음에 -q: X-Lab=default

세 요청 모두 curl 종료 코드는 0이었다. 서버에서 받은 헤더도 각각 default, 없음, default로 일치했다. 성공 여부만으로는 기본 설정을 읽었는지 구분할 수 없었다. 첫 -q에서만 사용자 정의 헤더가 사라지는 것이 이 실험의 판별 근거다. curl 8.21.0의 해당 버전 문서 (새 탭에서 열림)도 첫 인자라는 조건을 명시한다.

자신의 비교에서도 첫 -q에서만 차이가 사라지면 기본 설정 파일의 옵션을 조사할 근거가 생긴다. 그대로라면 먼저 실제 인자 순서와 뒤에서 설명할 명시적 --config를 확인한다. -q 하나로 모든 설정 원인을 배제했다고 볼 수는 없다. 연결 자체가 실패했다면 헤더가 없다는 결과로 세지 말고 URL과 서버의 수신 상태부터 확인한다.

설정 파일은 현재 폴더만 찾지 않는다

어느 파일이 적용됐는지는 curl을 실행한 프로세스의 환경에서 확인한다. IDE나 작업 실행기가 호출했다면 그 실행 환경을 대상으로 봐야 한다. 다음 조회는 파일 내용을 열지 않고 탐색에 쓰이는 환경 변수 값을 보여 준다.

'CURL_HOME', 'XDG_CONFIG_HOME', 'HOME', 'USERPROFILE', 'APPDATA' |
    ForEach-Object { Get-Item "Env:$_" -ErrorAction SilentlyContinue } |
    Format-List Name, Value | Out-String -Width 4096

curl 8.21.0의 공식 문서에 나온 Windows 기본 파일 탐색 순서는 다음과 같다. 변수 값이 없으면 그 항목은 건너뛴다. 아래는 문서의 규칙이며, 이번 실험에서 각 위치의 우선순위를 모두 재검증한 것은 아니다.

  1. CURL_HOME 아래 .curlrc
  2. XDG_CONFIG_HOME 아래 curlrc — 이 위치 지원은 7.73.0부터다.
  3. HOME 아래 .curlrc
  4. USERPROFILE 아래 .curlrc
  5. APPDATA 아래 .curlrc
  6. USERPROFILE 아래 Application Data 폴더의 .curlrc
  7. 앞선 위치에서 찾지 못하면 curl 실행 파일과 같은 폴더

Windows에서는 .curlrc 외에 _curlrc라는 이름도 확인하며 .curlrc를 우선한다. 따라서 현재 작업 폴더에 설정 파일이 없거나, 자신이 예상한 홈에 파일이 없다는 것만으로 기본 설정을 배제할 수 없다. curl 8.21.0의 설정 파일 탐색 규칙 (새 탭에서 열림)

첫 -q로 차이를 확인한 뒤에는 이 경로들과 파일의 관련 옵션을 대조해 출처를 좁힌다. 비교 결과만으로 특정 파일 이름까지 알아낸 것은 아니다. 반복 실행할 스크립트는 첫 인자 -q를 고정하고 필요한 옵션을 명령이나 의도적으로 지정한 설정 파일에 적으면, 사용자별 기본 파일의 영향을 줄일 수 있다.

-q를 써도 명시한 --config는 읽는다

-q는 기본 curlrc의 자동 로드를 막는 옵션이다. --config 또는 -K로 직접 지정한 파일까지 무시하게 만들지는 않는다. 반대로 --config를 쓴다고 기본 파일을 자동으로 대체하는 것도 아니다. curl의 --config 설명 (새 탭에서 열림)

같은 실험에서 별도 파일 explicit.cfg에 다음 한 줄을 저장했다. 기본 파일의 X-Lab: default는 그대로 두었다.

header = "X-Lab: explicit"

이 파일이 있는 작업 폴더에서, 같은 $url에 아래 두 요청을 보냈다. 직접 확인할 때도 ./explicit.cfg가 실제로 존재해야 하며 $curlExe와 $url은 앞에서 정한 값을 사용한다.

& $curlExe -q -sS --config './explicit.cfg' --noproxy '*' --connect-timeout 1 --max-time 3 $url
& $curlExe -sS --config './explicit.cfg' --noproxy '*' --connect-timeout 1 --max-time 3 $url

첫 요청은 X-Lab=explicit, 두 번째는 X-Lab=default,explicit를 반환했다. 두 요청 모두 종료 코드는 0이었다. 두 번째 응답의 쉼표는 수신기가 두 X-Lab 헤더 값을 이어서 보여 준 표기다. 실제 요청에는 같은 이름의 헤더가 두 줄 있었다.

즉, 첫 -q는 자동으로 들어오던 default를 제외했지만 명시적으로 요청한 explicit는 남겼다. 스크립트에 이미 --config가 있다면 그 파일도 확인해야 한다. 이번에 실행한 범위는 Windows curl 8.21.0의 합성 헤더와 loopback HTTP 요청이다. 개인 curlrc나 자격 증명은 읽지 않았으며, Linux·macOS의 실제 파일 탐색은 실행하지 않았다.

← 전체 글 보기