file_get_contents('php://input') no data 데이터 안 들어올 때 / postman으로 POST 요청을 보냈는데 GET으로 들어올 때 / php post json 받기

·2022년 3월 8일
0

API

목록 보기
2/2

문제상황

1. POST method 로 보낸 request body의 JSON data가 값이 들어오질 않는다?

늘 하던 대로 아래와 같이 코드를 넣고 포스트맨으로 테스트를 했는데 아무것도 없어서 당황했습니다.

$apimethod = $_SERVER['REQUEST_METHOD']; // http 메서드
$json = trim(file_get_contents('php://input'));
var_dump($json);

2. 분명히 method를 POST로 보냈는데 GET으로 들어온다?

분명히 POST로 보냈는데, method가 GET으로 들어오고 있는 걸 발견하고, 여기서 문제의 실마리를 찾을 수 있었습니다.

$apimethod = $_SERVER['REQUEST_METHOD']; // http 메서드
$json = trim(file_get_contents('php://input'));
var_dump($json);
echo $apimethod;

슬래시(/) 의 중요성

캡쳐화면을 보고 눈치 채셨나요? 그렇다면 고수 인정!
평소엔 아무 신경도 안 쓰던 맨 끝의 / 를 붙이고 안 붙이고에 따라 이런 크나큰 참사(?)가 벌어진 것이었습니다. 아니 https://www.google.co.kr 치나 https://www.google.co.kr/ 똑같은데

1. 끝에 / 를 붙이니 드디어 원하던 결과가 나왔습니다

2. 트레일링 슬래시 trailing slash

그냥 넘어갈 수(또 이런 삽질을 반복할 순) 없어서 찾아봤더니 이 끝에 붙는 슬래시(/)를 트레일링 슬래시라고 부르더군요. 아래 글에서 굉장히 재밌고 자세하게 설명해주신 걸 발견했습니다!(꿀같은 한글 자료! 압도적 감사!)
https://djkeh.github.io/articles/Why-do-we-put-slash-at-the-end-of-URL-kor/

워낙 재밌게 차이와 원리까지 설명해주셔서 읽어보시면 정말 좋을 것 같아요.

원리부분을 생략하고 간단히 요약문만 가져오면 이렇다고 합니다.

3. 트레일링 슬래시를 붙이지 않았을 경우

서버는 아래와 같이 받아들인다고 합니다.

해당 이름의 파일이 존재하는지를 먼저 확인합니다.
없을 경우, 해당 이름의 디렉토리를 확인합니다.
디렉토리가 있으면, 그 안의 기본 파일(기본값은 index.html이죠)을 확인합니다.

제가 ~/api/v1/index.php 라는 파일에 작업을 했기 때문에 https://~.com/api/v1 으로 접속했을 때 서버는
1. 해당 이름의 파일이 존재하는지 확인 -> api 폴더에 v1이라는 파일은 없습니다.
2. 해당 이름의 디렉토리 확인 api/v1 디렉토리를 확인 -> 존재
3. 그 안의 기본파일 index.php를 찾아준 것이죠.

4. 여전히 이해가 안 된 지점

가만! 근데 결국 트레일링 슬래시를 붙여도 위 과정에서 1번 과정을 생략할 뿐인데 대체 뭐가 문제인 거지!?

포스트맨

1. 트레일링 슬래시가 없을 때 웹브라우져 동작

위에서 소개한 트레링일 슬래시 글에 따르면, https://google.co.kr 로 웹브라우져에 요청을 보내도 개발자도구 - Network - Headers 항목을 찾아보면
https://google.co.kr/ 로 변경하여 요청한다고 합니다.
아니, 그렇다면 더더욱 문제가 없었어야하는 거 아닌가?

2. 의심

그러나 제가 요청을 보낸 툴은 웹브라우져가 아니라 포스트맨이고, 저는 POST method 로 요청을 보냈는데 이게 GET 요청으로 들어오고 있었죠. 혹시 포스트맨이 뒤에 트레일링 슬래시가 없을 경우 트레일링 슬래시를 붙이면서 GET으로 method를 바꿔서 요청하는 건가? 하는 킹리적 갓심의심을 하게 됩니다. 그리고 드디어

3. 포스트맨 세팅 Postman setting

포스트맨 Settings 메뉴에서 아래와 같은 세팅을 찾아냅니다. 포스트맨은 '리다이렉팅'시 default인 GET method로 요청request을 보내는 것이 기본설정값이라는 것을요.(포스트맨은 트레일링 슬래시가 없는 제 요청의 URL을 트레일링 슬래시를 붙인 URL로 '리다이렉팅'을 하고 있던 것이었습니다. 그리고 그 과정에서 method를 GET으로 바꿔 보낸 거죠. 누구 맘대로)
이 설정을 ON으로 (즉 리다이렉팅을 하더라도 original method, 내가 원래 설정한 method로 요청을 보내도록) 변경하면 트레일링 슬래시를 붙여서 리다이렉팅을 하게 되더라도 POST로 보낼 수 있게 되는 것입니다.

Follow original HTTP Method
Redirect with the original HTTP method instead of the default behavior of redirecting with GET.


결론

  1. POST로 요청을 보낼 때 body값이 제대로 전달되지 않는다면 URL 끝에 / (트레일링 슬래시)를 붙이지 않아서 발생한 현상일 수 있다.
  2. 포스트맨 테스트하면서 맨날 끝에 / 를 붙이는 게 너무 귀찮아서 못 참겠다면 설정을 통해 / 없이 테스트할 수 있다.
  3. 만약 이 문제가 아니면 다음으로 의심(+폭풍검색)해볼 만한 것은 .htaccess 설정이다.
profile
백엔드 개발자. 공동의 목표를 함께 이해한 상태에서 솔직하게 소통하며 일하는 게 가장 즐겁고 효율적이라고 믿는 사람.

0개의 댓글