Jump to content
과거의 기술자료(읽기 전용): https://tech.devgear.co.kr ×
과거의 기술자료(읽기 전용): https://tech.devgear.co.kr
  • 0

Delphi 11 REST Client 동작 오류 문의드립니다.


가을이다

질문

안녕하세요.

아래 글 중 이번에 Delphi 11버전으로 업그레이드 되면서 POST방식이 안된다고

글을 남겨주신 회원분이 있는데, 저희도 앱도 해보니 문제가 있어 글을 남깁니다.

 

저희가 사진 데이터를 Base64로 인코딩해서 최종문자열을 POST 데이터로 보내서 , DB에 사진을 문자열로 저장하고 있었습니다.

이번에 11버전으로 업그레이드 이후

414 Request-URI Too Long   에러를 확인했습니다.

보통 이 에러는 Get로 요청 시 파라미터가 기본 설정값을 초과한 경우 나오는 메세지 입니다.

 

그래서 여러가지 기본 테스트를 해 본 결과 11버전에 문제가 있었습니다.

post로 요청시, 서버단에서 post로 못받고 get으로 인지를 하는 문제입니다.

 

개요 : 10.4.2 에서 잘 되던 앱이 11 버전 RestClient POST 방식에서 문제가 되어 여러가지 테스트 해본 결과

POST로 파라미터를 요청을 하면 서버쪽에서 POST로 파라미터 값을 못 받는 현상입니다.

 

 

[POST 테스트 ]

[서버단 - php소스] : POST 요청 파라미터 id 값을 출력


<?php

$id = $_POST['id'];

echo "result : ".$id;

?>

--------------------------------------------------------------------------------------------

아래와 같이 테스트를 해보았습니다.

호출주소  http://112.000.000.000/be.asp/test.php

파라미터  id = 12345

Method : POST

--------------------------------------------------------------------------------------------

기존 10.4.2 RESR Debugger 디버거 요청시  :

>>result : 12345 

잘 응답됩니다.

--------------------------------------------------------------------------------------------

최신 11  RESR Debugger 디버거 요청시  :

>>result

값이 안찍힙니다.

--------------------------------------------------------------------------------------------

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

이 댓글 링크
다른 사이트에 공유하기

3 answers to this question

Recommended Posts

  • 0

질문하신 내용을 요약하면 "델파이 11에서 POST로 요청 시 GET으로 메소드를 호출되는 이슈가 있다.로 이해됩니다.

질문의 답변에 앞서,
요구사항을 확인하면 "이미지 데이터를 서버로 전달"하는 것으로 보여 다음 2가지 답변을 드립니다.

1) POST 요청 시 GET으로 호출하는 원인 확인 및 조치사항(질문에 대한 답변)

2) REST 클라이언트로 이미지를 업로드하는 방안(요구사항 솔루션)

 

항목별로 답변드립니다.

1) POST 요청 시 GET으로 호출하는 원인 확인 및 조치사항

우선 현상과 원인 파악을 위해 PHP 페이지를 다음과 같이 작성 후 다시 시도해보시기 바랍니다.(정확히 어떤 메소드로 호출하는지 확인할 수 있습니다.)

<?php
$GetId = $_GET['id'];
$PostId = $_POST['id'];

echo $_SERVER["REQUEST_METHOD"]."<br />\n"; // HTTP 메소드(GET / POST)

echo "Get : ".$GetId."<br />\n";
echo "Post : ".$PostId."<br />\n";

echo "body: ".$HTTP_RAW_POST_DATA."<br />\n";
echo "body: ".file_get_contents("php://input")."<br />\n";
?>

제가 테스트한 결과는 다음과 같습니다.

image.png

두가지 버전 모두 POST로 요청함을 확인했습니다.
(응답 Body의 첫번째 항목은 HTTP 메소드 종류이며, 둘다 POST로 출력되었습니다.)

하지만 전송한 요청 파라미터(GETorPOST 파라미터)는, 10.4.2에서는 POST($_POST) 데이터로 11.0에서는 GET($_GET)으로 전달됩니다.
결과적으로, 두 버전간 전달하는 방식에 차이가 있는 것을 확인했습니다.

 

두 버전이 다른 결과가 나온 내용을 소스코드에서 분석한 내용을 설명합니다.(간단히 설명하니 참고만 하고, 아래의 결론의 내용을 적용하시기 바랍니다.)
11.0에서 REST 클라이언트의 주요 변경사항 중 ContentType을 문자열로 처리하도록 개선되었습니다.(상당히 많은 양의 코드가 변경되었습니다.)

특히, 파라메터 전송 방식을 판단하는 IsQueryParam은 아래와 같이 변경되었습니다.(좌: 10.4.2, 우: 11.0)

image.png

빨간 박스를 보면 파라메터의 컨텐트타입(APram.ContentType)이 ctNone(공백)인 경우 쿼리 파라메터로 인식되어 요청시 Get 형식의 파라메터가 전송됩니다.

위 로직을 피하기 위해서는 다음과 같은 조치를 취해야 합니다.

  1. TRESTRequest.Params 속성 선택
  2. POST 파라메터로 전달하려는 파라메터의 ContentTypeStr을 "multipart/form-data" 지정

 

image.png

위와 같이 지정 후 REQUEST 실행하면 다음과 같이 10.4.2와 동일한 방식으로 POST 파라메터로 전송되는 것을 확인할 수 있습니다.

image.png

해당 조치는 REST Debugger에서는 진행할 수 없으니, 소스코드 상에서 조치해야 합니다.

결론: 

델파이 11.0에서 POST 요청 시 파라메터를 POST 파라미터로 전달하려면, 파라메터의 ContentTypeStr을 "multipart/form-data"로 지정한다.

 

2) REST 클라이언트로 이미지를 업로드하는 방안

이미지를 Base64로 인코딩해 문자열로 전송하셨습니다.  멀티파트 폼데이터(multi-part/formdata)로 전송하는 방식도 검토해 보시기 바랍니다.

멀티파트 폼데이터로 전송 시 Stream을 그대로 파라미터로 설정할 수 있습니다.

다음은 클라이언트에서 멀티파트-폼데이터로 전송하는 샘플 코드입니다.
(파라미터에 파일(pkFILE)이 포함된 경우 multi-part/formdata로 전송됩니다.)

var
  Stream: TMemoryStream;
  Item: TRESTRequestParameter;
begin
  if not OpenDialog1.Execute then
    Exit;

  Stream :=  TMemoryStream.Create;
  Stream.LoadFromFile(OpenDialog1.FileName);

// 파라메터는 디자인타임에 생성되었습니다.
//  Item := RESTRequest1.Params.AddItem;
//  Item.Name := 'img';
//  Item.Kind := pkFILE;
  RESTRequest1.Params.ParameterByName('img').SetStream(Stream);

  RESTRequest1.Method := rmPOST;
  RESTRequest1.Execute;
end;

멀티파트 폼데이터로 전송 시 웹서버에서 파일 전송과 동일한 방식으로 받아 처리할 수 있습니다.

RAD 서버 11.0에서는 다음 코드를 이용해 멀티파트 폼데이터를 처리할 수 있습니다.

procedure TImgResource1.Post(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
var
  Stream: TStream;
begin
  Stream := ARequest.Body.GetPart('img', '').GetStream;

  if Stream.Size <= 0 then
    AResponse.RaiseBadRequest('no stream');

  TMemoryStream(Stream).SaveToFile('D:\Temp\test.jpg');
end;

위 샘플코드 프로젝트입니다.

RSX_FileUpload.zip

결론: 
이미지 등의 파일 업로드 구현 시 멀티파티 폼데이터로 전송할 수도 있습니다.
(델파이의 일반적인 데이터구조인 Stream을 바로 전송할 수 있어 별도 인코딩 없이 간단히 구현할 수 있습니다.)

 

두가지 방식을 안내드렸습니다.

제가 제안하는 방식은, 

업로드 방식을 변경할 수 있다면 2번항목을 참고해 업로드 방식을 변경하시길 권장드리며, 

서버의 인터페이스를 변경하지 못하는 경우 1번항목을 참고해 적용하시기 바랍니다.

----

내용 검토해 보시고 해결여부와 추가질문 및 의견 부탁드립니다.

 

이 댓글 링크
다른 사이트에 공유하기

  • 0

답변 감사드립니다.

조언에 해주신데로 적용하니, 동작이 잘 됩니다. ^^

기존 프로젝트에서 Rest 호출하는 곳이 상당히 많은데 소스를 다 수정해야 하는게 문제군요 ㅎㅎ

------

파일업로드 방식은 진작에 알았으면 적용했을텐데 이미 현재 방식으로 많은 시스템이 돌아가고 있어서 

아마도 다음 프로젝트에서 적용해야 할 것 같네요

 

바쁘실텐데 도움을 주셔서 감사드립니다.

이 댓글 링크
다른 사이트에 공유하기

  • 0

델파이11에서 RESTClient, RESTRequest, RESTResponse

사용시 위의 답변이 잘못된거 같습니다.

제가 테스트한 바로 파일첨부일 경우 저렇게 하면 되는듯한데

일반파라미터로만 전달될 경우 저렇게 하면 GET으로 인식합니다.

즉, 파일첨부가 없는 경우 파라미터로만 전달될 경우는

아래와 같이 하시는게 맞습니다.

Request.Method      := TRESTRequestMethod.rmPOST;

 Param := Request.Params.AddItem;
 Param.name := '이름';
 Param.Value:= 값;
 Param.Kind := TRESTRequestParameterKind.pkGETorPOST;
 Param.ContentType := TRESTContentType.ctAPPLICATION_X_WWW_FORM_URLENCODED;

위와 같이 파라미터의 형식과 컨텐츠타입을 저렇게 지정해주어야 정상적으로 POST형식으로 전달됩니다.

몇번의 테스트후 이 방식으로 할 경우 정상적으로 전달됩니다.

이 댓글 링크
다른 사이트에 공유하기

이 토의에 참여하세요

지금 바로 의견을 남길 수 있습니다. 그리고 나서 가입해도 됩니다. 이미 회원이라면, 지금 로그인하고 본인 계정으로 의견을 남기세요.

Guest
이 질문에 답변하기...

×   서식있는 텍스트로 붙여넣기.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   이전에 작성한 콘텐츠가 복원되었습니다..   편집창 비우기

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

중요한 정보

이용약관 개인정보보호정책 이용규칙 이 사이트가 더 잘 작동하기 위해 방문자의 컴퓨터에 쿠키가 배치됩니다. 쿠키 설정 변경에서 원하는 설정을 할 수 있습니다. 변경하지 않으면 쿠키를 허용하는 것으로 이해합니다.