FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin for Harbour/xHarbour Use cUrl to upload data to online server
Posts: 1487
Joined: Tue Jun 14, 2016 07:51 AM
Use cUrl to upload data to online server
Posted: Sat May 22, 2021 02:41 PM
I was able to retrieve data from my webshop hosted by a 3the company. Normaly we can retrieve and upload data by API

Download = working (I retrieve some productdata)

Upload (Change a name from a product seems to be more difficult)

For upload, the server samples show this :

curl -X PATCH "http://swagger.shoptrader.com/api/v2/products/1994?token=abc" -H "accept: application/json" -H "token: abc" -H "Content-Type: application/json" -d "{\"model\":\"string\",\"sku\":\"string\",\"ean\":\"string\",\"name\":\"Test 1994\",\"description\":\"string\",\"introDescription\":\"string\",\"extraDescription\":\"string\",\"metaTitle\":\"string\",\"metaKeyword\":\"string\",\"metaDescription\":\"string\",\"quantity\":0,\"categoryId\":0,\"price\":0,\"purchasePrice\":0,\"status\":true,\"taxRate\":0,\"manufacturerId\":0,\"width\":0,\"height\":0,\"weight\":0,\"images\":[\"ImageOne\"],\"imagesAlt\":[\"ImageOneAlt\"],\"resources\":[{\"resourceKey\":\"key\",\"resourceValue\":\"value\",\"resourceType\":\"type\"}]}"

and there is

Request Url :

http://swagger.shoptrader.com/api/v2/pr ... ?token=abc

For retrieve we put : "https://swagger.shoptrader.com/api/v2/products?limit=100&token=abc" and this gives resulting data to retrieve

Now for upload/edit online, how does the program need to get the command ? The request Url = not having all the data i thing

Online sample with Swagger: http://apidocs.shoptrader.com/#/Products/productsPatch
Marc Venken

Using: FWH 23.08 with Harbour
Posts: 1487
Joined: Tue Jun 14, 2016 07:51 AM
Re: Use cUrl to upload data to online server
Posted: Sat May 22, 2021 08:02 PM

I found a testing server from swagger, and there the folowing is working :

curl -X 'PUT' \
'https://petstore.swagger.io/v2/pet' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"id": 666,
"name": "Noyca",
"status": "available"
}'

the request url :

https://petstore.swagger.io/v2/pet

I get a Response on the demo server :

200 so it is done ok and
{
"id": 666,
"name": "Noyca",
"photoUrls": [],
"tags": [],
"status": "available"
}

The demo server : https://editor.swagger.io/?_ga=2.123072 ... 1621675979

This is changing the content of the online database. It is 1 field to update, so if I can get this to work from FW i think I can get it to work for my shop as well.

I've seen several postings on cUrl, but non I get working for this code.

In fact,

Marc Venken

Using: FWH 23.08 with Harbour
Posts: 1487
Joined: Tue Jun 14, 2016 07:51 AM
Re: Use cUrl to upload data to online server
Posted: Sat May 22, 2021 08:25 PM
I'm getting close.

I found a program that converts cUrl code to programming code.

Can any of these help finding a FW solution ?

So

curl -X 'PUT' \
'https://petstore.swagger.io/v2/pet' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"id": 666,
"name": "Troy",
"status": "available"
}'

becomes :

PHP

Code (fw): Select all Collapse
$headers = array(
   "accept: application/json",
   "Content-Type: application/json",
);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);

$data = <<<DATA
{
  "id": 666,
  "name": "Troy",
  "status": "available"
}
DATA;

curl_setopt($curl, CURLOPT_POSTFIELDS, $data);

//for debug only!
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);

$resp = curl_exec($curl);
curl_close($curl);
var_dump($resp);

?>


JAVASCRIPT

Code (fw): Select all Collapse
var url = "https://petstore.swagger.io/v2/pet";

var xhr = new XMLHttpRequest();
xhr.open("PUT", url);

xhr.setRequestHeader("accept", "application/json");
xhr.setRequestHeader("Content-Type", "application/json");

xhr.onreadystatechange = function () {
   if (xhr.readyState === 4) {
      console.log(xhr.status);
      console.log(xhr.responseText);
   }};

var data = `{
  "id": 666,
  "name": "Troy",
  "status": "available"
}`;

xhr.send(data);


Python

Code (fw): Select all Collapse
import requests
from requests.structures import CaseInsensitiveDict

url = "https://petstore.swagger.io/v2/pet"

headers = CaseInsensitiveDict()
headers["accept"] = "application/json"
headers["Content-Type"] = "application/json"

data = """
{
  "id": 666,
  "name": "Troy",
  "status": "available"
}
"""


resp = requests.put(url, headers=headers, data=data)

print(resp.status_code)


JAVA

Code (fw): Select all Collapse
URL url = new URL("https://petstore.swagger.io/v2/pet");
HttpURLConnection http = (HttpURLConnection)url.openConnection();
http.setRequestMethod("PUT");
http.setDoOutput(true);
http.setRequestProperty("accept", "application/json");
http.setRequestProperty("Content-Type", "application/json");

String data = "{\n  \"id\": 666,\n  \"name\": \"Troy\",\n  \"status\": \"available\"\n}";

byte[] out = data.getBytes(StandardCharsets.UTF_8);

OutputStream stream = http.getOutputStream();
stream.write(out);

System.out.println(http.getResponseCode() + " " + http.getResponseMessage());
http.disconnect();


c#/NET

Code (fw): Select all Collapse
var url = "https://petstore.swagger.io/v2/pet";

var httpRequest = (HttpWebRequest)WebRequest.Create(url);
httpRequest.Method = "PUT";

httpRequest.Headers["accept"] = "application/json";
httpRequest.ContentType = "application/json";

var data = @"{
  ""id"": 666,
  ""name"": ""Troy"",
  ""status"": ""available""
}";

using (var streamWriter = new StreamWriter(httpRequest.GetRequestStream()))
{
   streamWriter.Write(data);
}

var httpResponse = (HttpWebResponse)httpRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
   var result = streamReader.ReadToEnd();
}

Console.WriteLine(httpResponse.StatusCode);


cUrl/BASH

Code (fw): Select all Collapse
#!/bin/bash

curl -X PUT https://petstore.swagger.io/v2/pet -H "accept: application/json" -H "Content-Type: application/json" --data-binary @- <<DATA
{
  "id": 666,
  "name": "Troy",
  "status": "available"
}
DATA
Marc Venken

Using: FWH 23.08 with Harbour
Posts: 10733
Joined: Sun Nov 19, 2006 05:22 AM
Re: Use cUrl to upload data to online server
Posted: Sun May 23, 2021 05:13 AM
Please try this:
Code (fw): Select all Collapse
function TestHttp()

   local oHttp
   local cUrl  := "https://petstore.swagger.io/v2/pet"
   local cData

   cData    := '{ "id" : 666, "name": "Troy", "status" : "available" }'

   oHttp := FWGetOleObject( "WINHTTP.WinHttpRequest.5.1" )

   WITH OBJECT oHttp
      :SetTimeouts(0, 60000, 30000, 120000)
      :Open( "POST", cUrl, .f. )
      :SetRequestHeader( "Accept",        "application/json" )
      :SetRequestHeader( "Content-Type",  "application/json" )
      :Send( cData )
      :WaitForResponse()
      ? :Status, :StatusText // 200 OK
   END

return nil
Regards



G. N. Rao.

Hyderabad, India
Posts: 6755
Joined: Wed Feb 15, 2012 08:25 PM
Re: Use cUrl to upload data to online server
Posted: Sun May 23, 2021 07:13 AM
Try with this: ( sorry, I have not been able to prove it )

Code (fw): Select all Collapse
local aHeaders  := {}
local cError
local cRet
local cData       := := '{ "id" : 666, "name": "Troy", "status" : "available" }'
curl_global_init()

   if ! empty( hCurl := curl_easy_init() )
      curl_easy_setopt( hCurl, HB_CURLOPT_URL, cUrl )
      curl_easy_setopt( hCurl, HB_CURLOPT_DL_BUFF_SETUP )
      curl_easy_setopt( hCurl, HB_CURLOPT_CONNECTTIMEOUT, 30 )
      //for debug only!
      curl_easy_setopt( hCurl, HB_CURLOPT_SSL_VERIFYHOST, .F. )
      curl_easy_setopt( hCurl, HB_CURLOPT_SSL_VERIFYPEER, .F. )
      curl_easy_setopt( hCurl, HB_CURLOPT_VERBOSE, .F. )
      AAdd( aHeaders, "accept: application/json" )
      AAdd( aHeaders, "Content-Type: application/json" )
      curl_easy_setopt( hCurl, HB_CURLOPT_HTTPHEADER, aHeaders )
      curl_easy_setopt( hCurl, HB_CURLOPT_POST, 1 )
      curl_easy_setopt( hCurl, HB_CURLOPT_POSTFIELDS, cData )
      cError  := curl_easy_perform( hCurl )
      if !Empty( cError )
         //MsgInfo( curl_easy_strerror( cError ), "Error" )
         cRet := curl_easy_strerror( cError )
      else
         cRet := curl_easy_dl_buff_get( hCurl )
      endif

   endif

   curl_global_cleanup()

Return cRet
Cristobal Navarro

Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo

El secreto de la felicidad no está en hacer lo que te gusta, sino en que te guste lo que haces
Posts: 1487
Joined: Tue Jun 14, 2016 07:51 AM
Re: Use cUrl to upload data to online server
Posted: Sun May 23, 2021 08:28 PM
nageswaragunupudi wrote:Please try this:
Code (fw): Select all Collapse
function TestHttp()

   local oHttp
   local cUrl  := "https://petstore.swagger.io/v2/pet"
   local cData

   cData    := '{ "id" : 666, "name": "Troy", "status" : "available" }'

   oHttp := FWGetOleObject( "WINHTTP.WinHttpRequest.5.1" )

   WITH OBJECT oHttp
      :SetTimeouts(0, 60000, 30000, 120000)
      :Open( "POST", cUrl, .f. )
      :SetRequestHeader( "Accept",        "application/json" )
      :SetRequestHeader( "Content-Type",  "application/json" )
      :Send( cData )
      :WaitForResponse()
      ? :Status, :StatusText // 200 OK
   END

return nil


Yes, This will update the data on the test server.

On my server it also changes the data, but always there is a new record created ?

I put some code I was testing. Data is written, but also every time a new record.

The ID of the product = 2062 and is put in the url.

I have tried also 'PUT' and 'PATCH' have been reading about it, but the I get return code 404 = not found error

Code (fw): Select all Collapse
function TestMarc()

   local oHttp

   local cUrl  := "https://maveco-webshop.be/api/v2/products/2062?token=47b en rest ...."
   local cData

   /*  This is the Curl that has the data insite needed to send


   curl -X PATCH "http://swagger.shoptrader.com/api/v2/products/1994?token=abc" -H "accept: application/json"
   -H "token: abc" -H "Content-Type: application/json"
   -d "{\"model\":\"string\",\"sku\":\"string\",\"ean\":\"string\",\"name\":\"Test 1994\",
   \"description\":\"string\",\"introDescription\":\"string\",\"extraDescription\":\"string\",
   \"metaTitle\":\"string\",\"metaKeyword\":\"string\",\"metaDescription\":\"string\",\"quantity\":0,
   \"categoryId\":0,\"price\":0,\"purchasePrice\":0,\"status\":true,\"taxRate\":0,\"manufacturerId\":0,
   \"width\":0,\"height\":0,\"weight\":0,\"images\":[\"ImageOne\"],\"imagesAlt\":[\"ImageOneAlt\"],
   \"resources\":[{\"resourceKey\":\"key\",\"resourceValue\":\"value\",\"resourceType\":\"type\"}]}"
   */


   //cData    := '{ "id" : 333, "name": "Noyca", "status" : "available" }'  //  PETSTORE

   cData := '{"model":"510.10.00","sku":"skuData","ean":"123456","name":"Noyca 1994","description":"MemoData"}'

   oHttp := FWGetOleObject( "WINHTTP.WinHttpRequest.5.1" )

   WITH OBJECT oHttp
      :SetTimeouts(0, 60000, 30000, 120000)

      //:Open( "PUT", cUrl )      // By Marc seen on Google
      //:Open( "PATCH", cUrl )      // By Marc seen on Google

      :Open( "POST", cUrl, .f. )  //By Rao

      :SetRequestHeader( "Accept",        "application/json" )
      //:SetRequestHeader( "Token",        "47b en rest ...." )   //  By Marc from Google
      :SetRequestHeader( "Content-Type",  "application/json" )
      :Send( cData )
      :WaitForResponse()
      ? :Status, :StatusText // 200 OK
   END

return nil
Marc Venken

Using: FWH 23.08 with Harbour
Posts: 1487
Joined: Tue Jun 14, 2016 07:51 AM
Re: Use cUrl to upload data to online server
Posted: Sun May 23, 2021 09:15 PM
cnavarro wrote:Try with this: ( sorry, I have not been able to prove it )

Code (fw): Select all Collapse
local aHeaders  := {}
local cError
local cRet
local cData       := := '{ "id" : 666, "name": "Troy", "status" : "available" }'
curl_global_init()

   if ! empty( hCurl := curl_easy_init() )
      curl_easy_setopt( hCurl, HB_CURLOPT_URL, cUrl )
      curl_easy_setopt( hCurl, HB_CURLOPT_DL_BUFF_SETUP )
      curl_easy_setopt( hCurl, HB_CURLOPT_CONNECTTIMEOUT, 30 )
      //for debug only!
      curl_easy_setopt( hCurl, HB_CURLOPT_SSL_VERIFYHOST, .F. )
      curl_easy_setopt( hCurl, HB_CURLOPT_SSL_VERIFYPEER, .F. )
      curl_easy_setopt( hCurl, HB_CURLOPT_VERBOSE, .F. )
      AAdd( aHeaders, "accept: application/json" )
      AAdd( aHeaders, "Content-Type: application/json" )
      curl_easy_setopt( hCurl, HB_CURLOPT_HTTPHEADER, aHeaders )
      curl_easy_setopt( hCurl, HB_CURLOPT_POST, 1 )
      curl_easy_setopt( hCurl, HB_CURLOPT_POSTFIELDS, cData )
      cError  := curl_easy_perform( hCurl )
      if !Empty( cError )
         //MsgInfo( curl_easy_strerror( cError ), "Error" )
         cRet := curl_easy_strerror( cError )
      else
         cRet := curl_easy_dl_buff_get( hCurl )
      endif

   endif

   curl_global_cleanup()

Return cRet


Sorry, But this was not working.

It also needs a extra ch file (found) and i think 2 libs to link.
Marc Venken

Using: FWH 23.08 with Harbour
Posts: 10733
Joined: Sun Nov 19, 2006 05:22 AM
Re: Use cUrl to upload data to online server
Posted: Sun May 23, 2021 09:25 PM
Try
Code (fw): Select all Collapse
      :Open( "PUT", cUrl, .f. )


not
Code (fw): Select all Collapse
      :Open( "PUT", cUrl )


POST is for adding a new pet and PUT is for modifying an existing one.
Error 404 means the id you are trying to modify is not found on the server.
Regards



G. N. Rao.

Hyderabad, India
Posts: 6755
Joined: Wed Feb 15, 2012 08:25 PM
Re: Use cUrl to upload data to online server
Posted: Sun May 23, 2021 09:42 PM
Marc Venken wrote:

Sorry, But this was not working.

It also needs a extra ch file (found) and i think 2 libs to link.


Yes, sure, if you want to use curl you need the appropriate harbour and compiler libraries
What C compiler do you use in your development?
Cristobal Navarro

Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo

El secreto de la felicidad no está en hacer lo que te gusta, sino en que te guste lo que haces
Posts: 1487
Joined: Tue Jun 14, 2016 07:51 AM
Re: Use cUrl to upload data to online server
Posted: Sun May 23, 2021 09:50 PM
nageswaragunupudi wrote:Try
Code (fw): Select all Collapse
      :Open( "PUT", cUrl, .f. )


not
Code (fw): Select all Collapse
      :Open( "PUT", cUrl )


POST is for adding a new pet and PUT is for modifying an existing one.
Error 404 means the id you are trying to modify is not found on the server.


Using PATCH did work ! (PUT was not changing data) don't know way, because it should i think
Marc Venken

Using: FWH 23.08 with Harbour
Posts: 1487
Joined: Tue Jun 14, 2016 07:51 AM
Re: Use cUrl to upload data to online server
Posted: Sun May 23, 2021 10:00 PM
Where do I put the dbf loop to update the data ?
The object http = already created once.

Maybe it is the intension that the loop will fill the cData var and that we patch it only once ?
The cData will become a large file or mem variable then. Do we ever can have memory problems when we do large updates ?

Code (fw): Select all Collapse
function TestMarc()

   local oHttp

   local cUrl  := "https://maveco-webshop.be/api/v2/products/2062?token=47b en rest ...."
   local cData

   //cData    := '{ "id" : 333, "name": "Noyca", "status" : "available" }'  //  PETSTORE

   cData := '{"model":"510.10.00","sku":"skuData","ean":"123456","name":"Noyca 1994","description":"MemoData"}'

   oHttp := FWGetOleObject( "WINHTTP.WinHttpRequest.5.1" )

   WITH OBJECT oHttp
      :SetTimeouts(0, 60000, 30000, 120000)
      :Open( "PATCH", cUrl, .f.)     
      :SetRequestHeader( "Accept",        "application/json" )
      :SetRequestHeader( "Content-Type",  "application/json" )
      :Send( cData )
      :WaitForResponse()
      ? :Status, :StatusText // 200 OK
   END

return nil
Marc Venken

Using: FWH 23.08 with Harbour
Posts: 10733
Joined: Sun Nov 19, 2006 05:22 AM
Re: Use cUrl to upload data to online server
Posted: Sun May 23, 2021 10:26 PM
The cData will become a large file or mem variable then. Do we ever can have memory problems when we do large updates ?

No problem at all.
cData is getting replaced. It is not growing.
Regards



G. N. Rao.

Hyderabad, India
Posts: 1487
Joined: Tue Jun 14, 2016 07:51 AM
Re: Use cUrl to upload data to online server
Posted: Sun May 23, 2021 10:32 PM
nageswaragunupudi wrote:
The cData will become a large file or mem variable then. Do we ever can have memory problems when we do large updates ?

No problem at all.
cData is getting replaced. It is not growing.


Size will be no problem, but cData is in the loop until full processed not ? And then the call to the Function to update by http
Marc Venken

Using: FWH 23.08 with Harbour
Posts: 1487
Joined: Tue Jun 14, 2016 07:51 AM
Re: Use cUrl to upload data to online server
Posted: Sun May 23, 2021 10:37 PM

API programming... A whole new world is opening ))))

I spend lot's of time creating functions so I could use the import function of the hosting company. With the API I can go direct. Very Nice.

Marc Venken

Using: FWH 23.08 with Harbour

Continue the discussion