2009-12-01 15 views
13

का उपयोग कर डेल्फी में HTTP POST अनुरोध कैसे भेजें I WinVnet फ़ंक्शंस का उपयोग करके डेल्फी से HTTP अनुरोध करने का प्रयास कर रहा हूं।WinInet api

अब तक मेरे पास है:

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 का उपयोग किया है, लेकिन मुझे POST अनुरोध भेजने की भी आवश्यकता है और वह फ़ंक्शन ऐसा नहीं करता है।

क्या कोई मुझे एक साधारण उदाहरण दिखा सकता है? परिणाम मैं चाहता हूं कि स्ट्रिंग के रूप में एक var में http प्रतिक्रिया पृष्ठ प्राप्त करें।

उत्तर

9

मुझे पिछले यूआरएल/फ़ाइल नाम भाग पिछले कोड के साथ गड़बड़ हो गया है। मैं अब इस from 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 एक समारोह में "होस्टनाम/फ़ाइल नाम" एक यूआरएल विभाजन है और TStringArray तार की एक सरणी है। मुझे अभी भी कल कोड की समीक्षा करनी है, लेकिन यह ठीक दिखता है और मेरे स्निफर में मैंने पोस्ट डेटा और हेडर भेजे हैं।

+3

मुझे आपके लिए आपके कोड का स्रोत मिला ताकि आप मूल लेखक को उद्धृत कर सकें। मैंने खराब-अनुमानित बूलियन केस स्टेटमेंट को हटाने के लिए कोड बदल दिया, और मैंने रेफरर बदल दिया, इसलिए यह झूठ नहीं बोलता और फ़ायरफ़ॉक्स 3.0.10 होने का दावा करता है। –

+1

मुझे नहीं पता कि किस इकाई में ParseURL है, या शायद यह एक कस्टम दिनचर्या है। कोड: http://delphi.pastebin.com/f1ea3a752 कुछ अलग है और ParseURL का उपयोग नहीं करते हैं। – lkessler

+0

पोस्ट अनुरोध में आप कस्टम हेडर वैल्यू कैसे जोड़ेंगे? – hikari

1

तीसरा पैरामीटर (lpszObjectName) HttpOpenRequestURL होना चाहिए जो आप अनुरोध करना चाहते हैं। यही कारण है कि दस्तावेज पांचवें पैरामीटर (lpszReferer) का वर्णन करता है "एक शून्य-समाप्ति वाली स्ट्रिंग के लिए एक सूचक जो दस्तावेज़ के यूआरएल को निर्दिष्ट करता है जिसमें से अनुरोध में यूआरएल (lpszObjectName) प्राप्त किया गया था।"

पोस्ट किया गया डेटा HttpSendRequest के साथ भेजा जाता है; lpOptional पैरामीटर इस तरह वर्णित है:

अनुरोधकर्ता शीर्षकों के तुरंत बाद भेजे जाने वाले किसी भी वैकल्पिक डेटा वाले बफर को पॉइंटर। यह पैरामीटर आमतौर पर पोस्ट और पुट ऑपरेशंस के लिए उपयोग किया जाता है। वैकल्पिक डेटा सर्वर पर पोस्ट किया जा रहा संसाधन या जानकारी हो सकता है। यदि भेजने के लिए कोई वैकल्पिक डेटा नहीं है तो यह पैरामीटर न्यूल हो सकता है।

InternetOpen को दूसरा पैरामीटर सिर्फ सर्वर नाम होना चाहिए; इसमें प्रोटोकॉल शामिल नहीं होना चाहिए। प्रोटोकॉल जो आप छठे पैरामीटर के साथ निर्दिष्ट करते हैं।

अनुरोध भेजने के बाद, आप InternetReadFile और InternetQueryDataAvailable के साथ प्रतिक्रिया पढ़ सकते हैं।

यह जांच न करें कि एपीआई फ़ंक्शन शून्य लौटाते हैं और फिर अगली पंक्ति पर आगे बढ़ते हैं। अगर वे असफल होते हैं, तो पता लगाने के लिए GetLastError पर कॉल करें। आपके द्वारा पोस्ट किया गया कोड अपवाद नहीं उठाएगा, इसलिए किसी को पकड़ना व्यर्थ है। (और यह वैसे भी है कि आप जिस तरह से कर रहे हैं उन्हें "संभाल" करना मूर्खतापूर्ण है। अपवाद न लें कि आपको पहले से ही पता नहीं है कि कैसे ठीक किया जाए। अन्यथा कॉलर, या कॉलर के कॉलर आदि पर जाएं। ।)

2

व्यक्तिगत रूप से मैं अपने सभी टीसीपी/आईपी काम के लिए synapse लाइब्रेरी का उपयोग करना पसंद करता हूं।

uses 
    httpsend; 

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

पुस्तकालय में अच्छी तरह से लिखा और अपने विशिष्ट आवश्यकताओं के अनुरूप संशोधित करने के लिए बहुत आसान है: उदाहरण के लिए, एक सरल HTTP पोस्ट के रूप में कोडित किया जा सकता है। नवीनतम सबवर्सन रिलीज डेल्फी 200 और डेल्फी 2010 दोनों के लिए किसी भी समस्या के बिना काम करता है। यह ढांचा घटक आधारित नहीं है, बल्कि कक्षाओं और प्रक्रियाओं की एक श्रृंखला है जो बहु-थ्रेडेड वातावरण में अच्छी तरह से है।