Author Topic: How to use NetworkTransfer POST() function?  (Read 272 times)

Offline rarahaha2

  • Newcomer
  • Posts: 3
    • View Profile
How to use NetworkTransfer POST() function?
« on: 2019 November 29 08:34:42 »
I studied PCL document these days and focus on the NetworkTransfer POST() function. In my opinion, it is not similar to traditional HTTP POST operation. I don't know how to set onDownloadDataAvailable() function and not very sure with the parameter of POST() function.
Here is a screenshot showed how I use postman to test my interface. It is just an interface that can upload my astro image to a remote server. there are 3 parameters of this interface: observatory_id(int),name(string),image(file)
Can anyone tell me how to do it in PixInsight JavaScript? Thanks a lot!

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7028
    • View Profile
    • http://pixinsight.com/
Re: How to use NetworkTransfer POST() function?
« Reply #1 on: 2019 December 01 13:32:40 »
The following function should work to simplify HTTP POST operations:

function POST( url, fields )
{
   let T = new NetworkTransfer;
   T.setURL( url );
   T.response = new ByteArray;
   T.onDownloadDataAvailable = function( data )
   {
      this.response.add( data );
   };
   
   if ( T.post( fields ) )
      console.writeln( "<end><cbr>POST executed. Server response = '", T.response.toString(), "'" );
   else
      console.criticalln( "<end><cbr>*** Error: POST operation failed." );
}


Using this function is straightforward; for example:

POST( "https://foobar.com/", "foo=bar&bar=foo" );


You must provide the list of key/value pairs in URL-encoded format. If necessary, you can use the following helper function to encode individual items:

function toPercentEncoding( s )
{
   function nibbleToHex( n )
   {
      const hexDigits = "0123456789ABCDEF";
      return hexDigits[n & 0xf];
   }

   let e = new String;
   for ( let i = 0, n = s.length; i < n; ++i )
   {
      let c = s.charCodeAt( i );
      if (   c >= 0x61 && c <= 0x7A  // a ... z
          || c >= 0x41 && c <= 0x5A  // A ... Z
          || c >= 0x30 && c <= 0x39  // 0 ... 9
          || c == 0x2D               // -
          || c == 0x2E               // .
          || c == 0x5F               // _
          || c == 0x7E )             // ~
      {
         e += s;
      }
      else
      {
         e += '%';
         e += nibbleToHex( (c & 0xf0) >> 4 );
         e += nibbleToHex( c & 0x0f );
      }
   }

   return e;
}



Let me know if this helps.
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline rarahaha2

  • Newcomer
  • Posts: 3
    • View Profile
Re: How to use NetworkTransfer POST() function?
« Reply #2 on: 2019 December 04 00:39:43 »
Thanks a lot for your help! But sorry... I'm still confused about the function...
Here are some of my questions:
1.How to set the "fields" parameter? It seems like to be a string, but my api need more than one parameter. Could you please tell me how to deal with that?
For example, I can use my api in Python like this:
Code: [Select]
import requests

url="http://astronomy.ezgolife.com/api/o1.business/getFiles"
param={"observatory_id":21,"name":"123"}
response=requests.post(url,data=param)
json=response.json()
console.writeln(json)

and then I get response like this:
Code: [Select]
{
    "code": 1,
    "data": {
        "files": []
    },
    "msg": ""
}
But when I use your function:
Code: [Select]
function POST( url, fields )
{
   let T = new NetworkTransfer;
   T.setURL( url );
   T.response = new ByteArray;
   T.onDownloadDataAvailable = function( data )
   {
      this.response.add( data );
   };
   
   if ( T.post( fields ) )
      console.writeln( "<end><cbr>POST executed. Server response = '", T.response.toString(), "'" );
   else
      console.criticalln( "<end><cbr>*** Error: POST operation failed." );
}
POST("http://astronomy.ezgolife.com/api/o1.business/getFiles", "observatory_id=21&name=123");
It just raised the error. Could you please tell me what is the problem?
2. I guess that my error is because encoding, but I don't know how to use your second part of code to encode it...
I use it like this:
Code: [Select]
function toPercentEncoding( s )
{
   function nibbleToHex( n )
   {
      const hexDigits = "0123456789ABCDEF";
      return hexDigits[n & 0xf];
   }

   let e = new String;
   for ( let i = 0, n = s.length; i < n; ++i )
   {
      let c = s.charCodeAt( i );
      if (   c >= 0x61 && c <= 0x7A  // a ... z
          || c >= 0x41 && c <= 0x5A  // A ... Z
          || c >= 0x30 && c <= 0x39  // 0 ... 9
          || c == 0x2D               // -
          || c == 0x2E               // .
          || c == 0x5F               // _
          || c == 0x7E )             // ~
      {
         e += s;
      }
      else
      {
         e += '%';
         e += nibbleToHex( (c & 0xf0) >> 4 );
         e += nibbleToHex( c & 0x0f );
      }
   }

   return e;
}
console.writeln(toPercentEncoding("name"));

It returned:
Code: [Select]
name=123name=123name=123name=123%3Dname=123name=123name=123Is that right? Should I use this result as parameter "fields"? In my opinion, it should be "e+=c" instead of "e+=s". Also, it seems like you forgot to encode '/'. But I'm not sure about that. Please tell me about that, thanks!!!
« Last Edit: 2019 December 04 06:24:45 by rarahaha2 »

Offline rarahaha2

  • Newcomer
  • Posts: 3
    • View Profile
Re: How to use NetworkTransfer POST() function?
« Reply #3 on: 2019 December 04 07:00:38 »
The following function should work to simplify HTTP POST operations:

function POST( url, fields )
{
   let T = new NetworkTransfer;
   T.setURL( url );
   T.response = new ByteArray;
   T.onDownloadDataAvailable = function( data )
   {
      this.response.add( data );
   };
   
   if ( T.post( fields ) )
      console.writeln( "<end><cbr>POST executed. Server response = '", T.response.toString(), "'" );
   else
      console.criticalln( "<end><cbr>*** Error: POST operation failed." );
}


Using this function is straightforward; for example:

POST( "https://foobar.com/", "foo=bar&bar=foo" );


You must provide the list of key/value pairs in URL-encoded format. If necessary, you can use the following helper function to encode individual items:

function toPercentEncoding( s )
{
   function nibbleToHex( n )
   {
      const hexDigits = "0123456789ABCDEF";
      return hexDigits[n & 0xf];
   }

   let e = new String;
   for ( let i = 0, n = s.length; i < n; ++i )
   {
      let c = s.charCodeAt( i );
      if (   c >= 0x61 && c <= 0x7A  // a ... z
          || c >= 0x41 && c <= 0x5A  // A ... Z
          || c >= 0x30 && c <= 0x39  // 0 ... 9
          || c == 0x2D               // -
          || c == 0x2E               // .
          || c == 0x5F               // _
          || c == 0x7E )             // ~
      {
         e += s;
      }
      else
      {
         e += '%';
         e += nibbleToHex( (c & 0xf0) >> 4 );
         e += nibbleToHex( c & 0x0f );
      }
   }

   return e;
}



Let me know if this helps.
OK I have addressed the problem I posted hours ago. I discovered that the function T.post() returned false but in fact I succeed in sending the post request and got the right response.
But now I have a new question: how to use this function to upload image files? I succeed with 2 api which just need two string parameter but failed with an api whose function is upload image files to a remote server and need an image file. Could you please tell me how to deal with that? Thank you!!