Help with hbcurl

Issues and Discussions related to Harbour

Moderator: Rathinagiri

Post Reply
User avatar
Rathinagiri
Posts: 5408
Joined: Tue Jul 29, 2008 6:30 pm
DBs Used: MariaDB, SQLite, SQLCipher and MySQL
Location: Sivakasi, India
Has thanked: 249 times
Been thanked: 301 times
Contact:

Help with hbcurl

Post by Rathinagiri »

I want to use hbcurl to POST/GET to/from web especially https.

Can you please tell me what are the libraries required to be statically linked and working in HMG?
East or West HMG is the Best.
South or North HMG is worth.
...the possibilities are endless.

User avatar
Rathinagiri
Posts: 5408
Joined: Tue Jul 29, 2008 6:30 pm
DBs Used: MariaDB, SQLite, SQLCipher and MySQL
Location: Sivakasi, India
Has thanked: 249 times
Been thanked: 301 times
Contact:

Post by Rathinagiri »

As of now, I am using hbtip successfully to send and receive data from https secured websites.

But in the Harbour distribution there is a warning which states like the one below. So, I want to switch over to others like hbcurl or MSXML2.ServerXMLHTTP

I have tried both. Both of them I am getting so many errors.

WARNING for HBTIP users
=======================

Due to the excessive amount of problem reports and long known (and unfixed)
problems and due to the non-trivial nature of internet protocols, this document
_strongly recommends to avoid_ using this library in anything production or
in fact anything more serious than simple test code for educational purposes.
Please notice that even if something happens to work in some specific
scenario, it's highly likely it's not a stable solution, nor is it a secure
solution.

The only reason hbtip hasn't been deleted altogether is compatibility
with 3.0, xHarbour and existing projects, plus the fact there are still some
low-level functions that do work fine (tip_MimeType()) or have no better
replacement yet (tip_MailAssemble()).

For internet protocol related tasks, the recommended and supported library
is _hbcurl_, which is a thin wrapper over libcurl's 'easy' API. libcurl is
a highly ubiquitious, very stable, actively and professionally developed,
secure communications library
East or West HMG is the Best.
South or North HMG is worth.
...the possibilities are endless.

edk
Posts: 706
Joined: Thu Oct 16, 2014 11:35 am
Location: Poland
Has thanked: 193 times
Been thanked: 647 times

Post by edk »

I have done communication with RESTAPI on the server with TLS 1.2 and I use both: cURL and "MSXML2.ServerXMLHTTP".

With "MSXML2.ServerXMLHTTP" I use json data exchange between my application and RESTAPI, while cURL for uploading image files ("MSXML2.ServerXMLHTTP" doesn't send form-data boundary correctly, at least I couldn't make him do it ;) )

Necessary are libraries that support TLS1.2 (those that were previously published on the forum did not work with TLS 1.2, I am attaching new ones - I do not know if they will work with TLS 1.3 also :roll: )
lib.zip
(1.19 MiB) Downloaded 26 times
My configuration:
HBP:

Code: Select all

Myapi.prg
hbziparc.hbc
hbcurl.hbc
HBC:

Code: Select all

inc=yes
head=native
libs=hbmxml mxml libeay32 ssleay32 libwinpthread-1 libcurl zlib1 libidn-11
HMG 3.4.4

Code snippets:

Code: Select all

//Init
BEGIN SEQUENCE WITH {|o| break(o)}
	oApi := Win_OleCreateObject( "MSXML2.ServerXMLHTTP" )
	oApi:setTimeouts(nTimeout * 1000 /* nResolve */ , nTimeout * 1000 /* nConnect*/ , nTimeout * 1000 /* nSend */, nTimeout * 1000 /* nReceive */ )

RECOVER
     MsgStop( "Microsoft XML Core Services (MSXML) 6.0 is not installed."+CRLF+;
          "Download and install MSXML 6.0 from http://msdn.microsoft.com/xml"+CRLF+;
          "before continuing.")
     oApi:=""
END SEQUENCE

IF EMPTY(oApi)
	MsgStop('Error while initialization')
	RETURN Nil
ENDIF

cResp := SendApi( cUrl, hb_jsonEncode( hData , .F. ), oApi )

Msgdebug ( cResp )

cResp := GetApi( cUrl, oApi )

Msgdebug ( cResp )

*********************************************************
Function SendApi( cUrl, cBody, oApi, cMethod )
Local cReturn, cAPIKey :="blablabla"

Default cMethod := "POST"

BEGIN SEQUENCE WITH {|o| break(o)}

	oApi:Open( cMethod, cUrl, .F. )
	oApi:setRequestHeader("Content-Type", "application/json;charset=utf-8")
	oApi:setRequestHeader("client-secret", cAPIKey)
	oApi:Send( cBody )

	IF oApi:Status <> 200
		BREAK "HTTPS status: " + hb_NToS(oApi:status) + " "  +oApi:statusText 
	ENDIF

	cReturn := oApi:ResponseBody()

RECOVER USING oErr
	cReturn := "!ERROR!" + CRLF + IF (ValType(oErr) = 'O', oErr:Description, oErr )
 
END SEQUENCE
 	
RETURN cReturn


**************************************
Function GetApi( cUrl, oApi)
Local cReturn, cAPIKey := "blablabla"

BEGIN SEQUENCE WITH {|o| break(o)}

	oApi:Open( "GET", cUrl, .F. )
	oApi:setRequestHeader("client-secret", cAPIKey)
	
	oApi:Send()
	oApi:WaitForResponse()

	IF oApi:Status <> 200
		BREAK "HTTPS status: " + hb_NToS(oApi:status) + " "  +oApi:statusText 
	ENDIF

	cReturn := oApi:ResponseBody()

RECOVER USING oErr

	cReturn := "!ERORR!" + CRLF + IF (ValType(oErr) = 'O', oErr:Description, oErr )
 
END SEQUENCE
 	
RETURN cReturn

Code: Select all

***********************************************************
* cURL
***********************************************************

//Init
curlHandle := curl_easy_init()
IF EMPTY(curlHandle)
	MsgStop('Error while initialization')
	RETURN Nil
ENDIF

//upload pictures
cResp := SendCurlPictApi( curlHandle, cUrl, cImageFile, hb_HGetDef( hPrd [i0], "id", 0) /* ProductId */ , Str(nIdZdjecia) /* id */, hb_HGetDef( hPrd [i0], "name", "") + " [" + Left( hb_HGetDef( hPrd [i0], "code", ""), 5 ) + "]" /* desc */ )

Msgdebug ( cResp )

curl_global_cleanup( curlHandle )

*********************************************************
Function SendCurlPictApi( curlHandle, cUrl, cImage, idProd, idZdjecia, cOpis )
Local cReturn, cAPIKey := "blablabla"
Local cPlikPict:=hb_FNameNameExt ( cImage )
Local boundary:='------' + hb_StrToHex ( hb_TtoC( hb_DateTime(), 'YYYYMMDDhhmmssfff' ) ) 
Local cFormBody:='--' + boundary + CRLF
Local aHeaders, curlErr
Default cOpis:=""

Do Events

cFormBody+='Content-Disposition: form-data; name="id"' + CRLF + CRLF
cFormBody+=Alltrim(idZdjecia) + CRLF

cFormBody+='--' + boundary + CRLF
cFormBody+='Content-Disposition: form-data; name="productId"' + CRLF + CRLF
cFormBody+=Alltrim(Str(idProd)) + CRLF

cFormBody+='--' + boundary + CRLF
cFormBody+='Content-Disposition: form-data; name="version"' + CRLF + CRLF
cFormBody+='1' + CRLF

cFormBody+='--' + boundary + CRLF
cFormBody+='Content-Disposition: form-data; name="description"' + CRLF + CRLF
cFormBody+=Alltrim (cOpis) + CRLF

cFormBody+='--' + boundary + CRLF

cFormBody+='Content-Disposition: form-data; name="file"; filename="' + cPlikPict + '"' + CRLF
SWITCH Upper(hb_FNameExt ( cImage ))
	CASE "JPG"
		cContentType:='image/jpeg'
		EXIT
	CASE "JPEG"
		cContentType:='image/jpeg'
		EXIT
	CASE "BMP"
		cContentType:='image/bmp'
		EXIT
	CASE "PNG"
		cContentType:='image/png'
		EXIT
	OTHERWISE
		cContentType:='image/jpeg'
END SWITCH
	
cFormBody+='Content-Type: ' + cContentType + CRLF + CRLF

cFormBody+=FILESTR( cImage ) + CRLF

cFormBody+='--' + boundary + '--' + CRLF

DO EVENTS

curl_easy_reset( curlHandle )

aHeaders := {"client-secret: " + cAPIKey, ;
		   "Content-Length: " + Str(Len(cFormBody)) , ;
		   "Content-Type: " + "multipart/form-data; boundary=" + Boundary }


/* Specify the Header  data */
curl_easy_setopt( curlHandle, HB_CURLOPT_HTTPHEADER, aHeaders)

curl_easy_setopt( curlHandle, HB_CURLOPT_URL, cUrl )
curl_easy_setopt( curlHandle, HB_CURLOPT_FOLLOWLOCATION, .T. )
curl_easy_setopt( curlHandle, HB_CURLOPT_SSL_VERIFYPEER, .F. )

curl_easy_setopt( curlHandle, HB_CURLOPT_DOWNLOAD )
curl_easy_setopt( curlHandle, HB_CURLOPT_DL_BUFF_SETUP )
	
curl_easy_setopt( curlHandle, HB_CURLOPT_POST, .T. )
curl_easy_setopt( curlHandle, HB_CURLOPT_POSTFIELDSIZE, LEN( cFormBody ) )
curl_easy_setopt( curlHandle, HB_CURLOPT_POSTFIELDS, cFormBody )

curlErr := curl_easy_perform( curlHandle )		/* Do everything */

IF !EMPTY( curlErr )	/* Report any errors */
	cReturn := "!ERROR!" + CRLF + curl_easy_strerror(curlErr)
ELSE
	cReturn := curl_easy_dl_buff_get( curlHandle )
ENDIF
 	
RETURN cReturn
************************************

User avatar
Rathinagiri
Posts: 5408
Joined: Tue Jul 29, 2008 6:30 pm
DBs Used: MariaDB, SQLite, SQLCipher and MySQL
Location: Sivakasi, India
Has thanked: 249 times
Been thanked: 301 times
Contact:

Post by Rathinagiri »

OMG! You are a true saviour man!

Let me revert back with my experience. Thanks a lot.
East or West HMG is the Best.
South or North HMG is worth.
...the possibilities are endless.

User avatar
Rathinagiri
Posts: 5408
Joined: Tue Jul 29, 2008 6:30 pm
DBs Used: MariaDB, SQLite, SQLCipher and MySQL
Location: Sivakasi, India
Has thanked: 249 times
Been thanked: 301 times
Contact:

Post by Rathinagiri »

I am getting the following errors.

Code: Select all

d:/hmg.3.5/mingw/bin/../lib/gcc/i686-w64-mingw32/9.3.0/../../../../i686-w64-mingw32/bin/ld.exe: cannot find -llibwinpthread-1
d:/hmg.3.5/mingw/bin/../lib/gcc/i686-w64-mingw32/9.3.0/../../../../i686-w64-mingw32/bin/ld.exe: cannot find -llibcurl
d:/hmg.3.5/mingw/bin/../lib/gcc/i686-w64-mingw32/9.3.0/../../../../i686-w64-mingw32/bin/ld.exe: cannot find -lzlib1
d:/hmg.3.5/mingw/bin/../lib/gcc/i686-w64-mingw32/9.3.0/../../../../i686-w64-mingw32/bin/ld.exe: cannot find -llibidn-11
Can you give me the .a library files also?
East or West HMG is the Best.
South or North HMG is worth.
...the possibilities are endless.

edk
Posts: 706
Joined: Thu Oct 16, 2014 11:35 am
Location: Poland
Has thanked: 193 times
Been thanked: 647 times

Post by edk »

Unfortunately, I don't have these files. They are not needed if you are compiling with build.bat. I don't compile with the IDE.

User avatar
Rathinagiri
Posts: 5408
Joined: Tue Jul 29, 2008 6:30 pm
DBs Used: MariaDB, SQLite, SQLCipher and MySQL
Location: Sivakasi, India
Has thanked: 249 times
Been thanked: 301 times
Contact:

Post by Rathinagiri »

Ok. Let me try with build.bat then.
East or West HMG is the Best.
South or North HMG is worth.
...the possibilities are endless.

Post Reply