문제

Wininet 기능을 사용하여 Delphi의 HTTP 요청을하려고합니다.

지금까지 나는 다음과 같습니다.

function request:string;
var
  hNet,hURL,hRequest: HINTERNET;
begin
  hNet := InternetOpen(PChar('User Agent'),INTERNET_OPEN_TYPE_PRECONFIG or INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  if Assigned(hNet) then 
  begin
  try
    hURL := InternetConnect(hNet,PChar('http://example.com'),INTERNET_DEFAULT_HTTP_PORT,nil,nil,INTERNET_SERVICE_HTTP,0,DWORD(0));
    if(hURL<>nil) then
      hRequest := HttpOpenRequest(hURL, 'POST', PChar('param=value'),'HTTP/1.0',PChar(''), nil, INTERNET_FLAG_RELOAD or INTERNET_FLAG_PRAGMA_NOCACHE,0);
    if(hRequest<>nil) then
      HttpSendRequest(hRequest, nil, 0, nil, 0);
    InternetCloseHandle(hNet);
  except
    on E : Exception do
      ShowMessage(E.ClassName+' error raised, with message : '+E.Message);
  end;
  end
end;

그러나 이것은 아무것도하지 않습니다 (나는 그것이 작동하는지 확인하기 위해 네트워크 HTTP 트래픽을 스니핑하고 있습니다). InternetOpenUrl을 성공적으로 사용했지만 사후 요청을 보내야합니다. 그 기능은 그렇게하지 않습니다.

누군가 나에게 간단한 예를 보여줄 수 있습니까? 내가 원하는 결과는 HTTP 응답 페이지를 var로 문자열로 가져 오는 것입니다.

도움이 되었습니까?

해결책

모든 URL/Filename 부분이 이전 코드를 엉망으로 만들었습니다. 나는 이것을 사용하고있다 Jeff Devore에서 이제 잘 작동합니다.

function request(const AUrl, AData: AnsiString; blnSSL: Boolean = True): AnsiString;
var
  aBuffer     : Array[0..4096] of Char;
  Header      : TStringStream;
  BufStream   : TMemoryStream;
  sMethod     : AnsiString;
  BytesRead   : Cardinal;
  pSession    : HINTERNET;
  pConnection : HINTERNET;
  pRequest    : HINTERNET;
  parsedURL   : TStringArray;
  port        : Integer;
  flags       : DWord;
begin
  ParsedUrl := ParseUrl(AUrl);

  Result := '';

  pSession := InternetOpen(nil, INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);

  if Assigned(pSession) then
  try
    if blnSSL then
      Port := INTERNET_DEFAULT_HTTPS_PORT
    else
      Port := INTERNET_DEFAULT_HTTP_PORT;
    pConnection := InternetConnect(pSession, PChar(ParsedUrl[0]), port, nil, nil, INTERNET_SERVICE_HTTP, 0, 0);

    if Assigned(pConnection) then
    try
      if (AData = '') then
        sMethod := 'GET'
      else
        sMethod := 'POST';

      if blnSSL then
        flags := INTERNET_FLAG_SECURE or INTERNET_FLAG_KEEP_CONNECTION
      else
        flags := INTERNET_SERVICE_HTTP;

      pRequest := HTTPOpenRequest(pConnection, PChar(sMethod), PChar(ParsedUrl[1]), nil, nil, nil, flags, 0);

      if Assigned(pRequest) then
      try
        Header := TStringStream.Create('');
        try
          with Header do
          begin
            WriteString('Host: ' + ParsedUrl[0] + sLineBreak);
            WriteString('User-Agent: Custom program 1.0'+SLineBreak);
            WriteString('Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'+SLineBreak);
            WriteString('Accept-Language: en-us,en;q=0.5' + SLineBreak);
            WriteString('Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7'+SLineBreak);
            WriteString('Keep-Alive: 300'+ SLineBreak);
            WriteString('Connection: keep-alive'+ SlineBreak+SLineBreak);
          end;

          HttpAddRequestHeaders(pRequest, PChar(Header.DataString), Length(Header.DataString), HTTP_ADDREQ_FLAG_ADD);

          if HTTPSendRequest(pRequest, nil, 0, Pointer(AData), Length(AData)) then
          begin
            BufStream := TMemoryStream.Create;
            try
              while InternetReadFile(pRequest, @aBuffer, SizeOf(aBuffer), BytesRead) do
              begin
                if (BytesRead = 0) then Break;
                BufStream.Write(aBuffer, BytesRead);
              end;

              aBuffer[0] := #0;
              BufStream.Write(aBuffer, 1);
              Result := PChar(BufStream.Memory);
            finally
              BufStream.Free;
            end;
          end;
        finally
          Header.Free;
        end;
      finally
        InternetCloseHandle(pRequest);
      end;
    finally
      InternetCloseHandle(pConnection);
    end;
  finally
    InternetCloseHandle(pSession);
  end;
end;

Parseurl은 "hostname / filename"에서 URL을 분할하는 함수이며 TStringArray는 다양한 문자열입니다. 나는 여전히 내일 코드를 검토해야하지만 괜찮아 보이며 스나이퍼에서는 게시물 데이터와 헤더가 전송되는 것을 보았습니다.

다른 팁

개인적으로 나는 사용하는 것을 선호합니다 시냅스 내 모든 TCP/IP 작업에 대한 라이브러리. 예를 들어 간단한 HTTP 게시물은 다음과 같이 코딩 할 수 있습니다.

uses
  httpsend;

function testpost;
begin
  stm := tStringstream.create('param=value');
  try
    HttpPostBinary('http://example.com',Stm);
  finally
    stm.free;
  end;
end;

도서관은 특정 요구 사항에 맞게 잘 쓰여지고 매우 쉽게 수정할 수 있습니다. 최신의 Subversion 릴리스는 Delphi 2009와 Delphi 2010 모두에 아무런 문제가없는 경우 작동합니다.이 프레임 워크는 구성 요소 기반이 아니라 다중 스레드 환경에서 잘하는 일련의 클래스 및 절차입니다.

세 번째 매개 변수 (lpszobjectname) to HttpOpenRequest 해야합니다 URL 당신은 요청하고 싶습니다. 그렇기 때문에 문서가 다섯 번째 매개 변수 (lpszreferer)를 "요청 (lpszobjectname)의 URL의 URL을 지정하는 NULL 용어 문자열에 대한 포인터"로 설명합니다.

게시 된 데이터는 함께 전송됩니다 HttpSendRequest; lpoptional 매개 변수는 다음과 같이 설명됩니다.

요청 헤더 직후에 전송 될 선택적 데이터가 포함 된 버퍼에 대한 포인터. 이 매개 변수는 일반적으로 Post 및 Put 작업에 사용됩니다. 선택적 데이터는 서버에 게시되는 리소스 또는 정보 일 수 있습니다. 옵션 데이터가 없으면이 매개 변수는 null 일 수 있습니다.

두 번째 매개 변수 InternetOpen 해야한다 서버 이름입니다; 프로토콜을 포함해서는 안됩니다. 여섯 번째 매개 변수로 지정하는 프로토콜.

요청을 보낸 후에는 응답을 읽을 수 있습니다. InternetReadFile 그리고 InternetQueryDataAvailable.

API 기능이 0을 반환 한 다음 다음 줄에서 진행하는지 확인하지 마십시오. 그들이 실패하면 전화하십시오 GetLastError 이유를 찾기 위해. 게시 한 코드는 예외를 제외하지 않으므로 어울리는 것은 쓸모가 없습니다. (그리고 어쨌든 당신이하는 방식으로 그들을 다루는 것은 어리석은 일입니다. 아직 고치는 방법을 모르는 예외를 포착하지 마십시오. 다른 모든 것이 발신자 나 발신자의 발신자 등을 올리게하십시오. .))

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top