• Purchasing a license grants permission to use the software and to get Tech Support. A license purchase doesn't grant customization support.

API issue

knightsguard

Founder license
License owner
Good evening!

I'm working closely with a few fellow mobile app developers and we've came across an issue with the POST function. The GET function works properly and will fetch a URL and upload it... but when attempting to upload a local base 64 image source, the error log keeps receiving "Can't create the image" from my server. Also, we attempted to send a base64 image as a variable with no luck. We have the most up to date GD Library that our hosting provider "Host Gator" has to offer, according to their support.

Any suggestions on what to do?

Our website is https://www.piccastle.com
 

Rodolfo

Chevereto Developer
Chevereto Staff
_FILES must be sent in the context of a form payload. In other words, you have to forge a multipart/form-data if you want to send the image as a form file.

In the other hand, the base64 works best when you use POST. Keep in mind that when you use GET the data gets url encoded and it limits the size of the image to the number of chars available in the URL.
 

DravenLewis

New Member
Im not quite sure what that means, (hello im one of his developers). We have decided to use Cordova in order to provide a mobile app to our users, currently GET based requests are fine but im having some issues with POST, i have tried several different approaches to send the data. Since its a cordova app we are limited to XMLHttpRequest (and AJAX which is an improvement) the api DOES NOT like to respond UNLESS the API Key is in the URI of the request, but at that point the server has decided it is receiving a GET. I can send the request with only the "Key" and the "Source" fields and then a base 64 encoded image and i get pretty far, but then the server says it cannot decode the image. He and i have been scratching our heads for weeks and i know you, as the developer would be the best help. If you could, take a look at my source code and see if something is not configured correctly for your service, or i have just goofed let me know šŸ˜‚

NOTE: Currently Working to use the FormData class available in JavaScript with a XMLHttpRequest that has a "content-type" of "multipart/form-data" to spoof a HTML form, real forms are not used as to have control over a certain UX element of the app, if that is halting us, can be changed later.
 

Attachments

Rodolfo

Chevereto Developer
Chevereto Staff
TL;DR: Use POST for everything and you should be fine.

The API uses $_REQUEST so it doesn't matter if you GET or POST, but there are differences in these request methods. Keep in mind that there's a limitation on the URL length so chances are that the base64 string is already chopped when gets handled by the API (this limitation is from the HTTP spec, not this API).

Your script is using x-www-form-urlencoded and when you use that, the base64 that you are putting there gets altered to fit in the whole payload. This means that the base64 string change as some chars may get replaced making the string useless.

If you want to stop worrying about this then simply use multipart and send the file as a binary with something like new File([blob], "filename.jpeg") or assign the raw base64 without any alterations.

For more, read this: application/x-www-form-urlencoded or multipart/form-data?
 

DravenLewis

New Member
Awesome so I can send the blob, I didn't see that mentioned in the API but if it works it will take a lot off of my shoulders haha, thanks for your help! Will follow up if it works or if I hit another roadblock, just for clarification, I send the Blob as the source argument with "multipart/form-data"

Edit: I'm probably going to use the FormData object from the JavaScript Standard API
 

DravenLewis

New Member
Okay so your advice worked somewhat, turns out the issues was my XMLHttpRequest was not fully forging a correct POST request.
I decided to stay with a Base64 image and just send it to the server as such, the request is sent through a proxy server so i could sniff the global headers.

Here is the output:

(i know that 'pretty' is not an API field but it has significance for the usage of the pretty printer that i used to filter the text so that i dont flood your comments with a massive block of Base64 code)

Request Outout:
-------------------------------------------------
--- BEGIN REPORT --------------------------------
-------------------------------------------------

GET ---------------------------------------------
Results From _GET array

-------------------------------------------------
POST --------------------------------------------
Results From _POST array
  *  key --> [Redacted Per NDA with employer]
  *  source --> iVBORw0KGgoAAAANSUhEUgAAAPAAAADwCAYAAAA+VemSAAAQx0lEQVR4nO2dzY4kRxWFu7q6q6vGVcMI[Truncated For Pretty Print]
  *  pretty --> true
  *  format --> json

-------------------------------------------------
REQUEST -----------------------------------------
Results From _REQUEST array
  *  key --> [Redacted Per NDA with employer]
  *  source --> iVBORw0KGgoAAAANSUhEUgAAAPAAAADwCAYAAAA+VemSAAAQx0lEQVR4nO2dzY4kRxWFu7q6q6vGVcMI[Truncated For Pretty Print]
  *  pretty --> true
  *  format --> json

-------------------------------------------------
SERVER ------------------------------------------
Results From _SERVER array
  *  HTTP_HOST --> 192.168.1.101
  *  HTTP_CONNECTION --> keep-alive
  *  CONTENT_LENGTH --> 6206
  *  HTTP_ACCEPT --> */*
  *  HTTP_ORIGIN --> file://
  *  HTTP_USER_AGENT --> Mozilla/5.0 (Linux; Android 8.0.0; SM-S757BL Build/R16NW; wv) AppleWebKit/537.36[Concantated For Pretty Print]
  *  CONTENT_TYPE --> application/x-www-form-urlencoded; charset=UTF-8[Truncated For Pretty Print]
  *  HTTP_ACCEPT_ENCODING --> gzip, deflate
  *  HTTP_ACCEPT_LANGUAGE --> en-US,en;q=0.9
  *  HTTP_X_REQUESTED_WITH --> com.piccastle.mobile
  *  PATH --> Z:\.sys\miniperl\bin;Z:\.sys\php;C:\ProgramData\Oracle\Java\javapath;C:\WINDOWS\[Concantated For Pretty Print]
  *  SystemRoot --> C:\WINDOWS
  *  COMSPEC --> C:\WINDOWS\system32\cmd.exe
  *  PATHEXT --> .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC[Truncated For Pretty Print]
  *  WINDIR --> C:\WINDOWS
  *  SERVER_SIGNATURE -->
  *  SERVER_SOFTWARE --> Apache/2.4.3 (Win64)
  *  SERVER_NAME --> 192.168.1.101
  *  SERVER_ADDR --> 192.168.1.101
  *  SERVER_PORT --> 80
  *  REMOTE_ADDR --> 192.168.1.145
  *  DOCUMENT_ROOT --> Z:/web
  *  REQUEST_SCHEME --> http
  *  CONTEXT_PREFIX -->
  *  CONTEXT_DOCUMENT_ROOT --> Z:/web
  *  SERVER_ADMIN --> admin@localhost
  *  SCRIPT_FILENAME --> Z:/web/test/test.php
  *  REMOTE_PORT --> 37177
  *  GATEWAY_INTERFACE --> CGI/1.1
  *  SERVER_PROTOCOL --> HTTP/1.1
  *  REQUEST_METHOD --> POST
  *  QUERY_STRING -->
  *  REQUEST_URI --> /test/test.php
  *  SCRIPT_NAME --> /test/test.php
  *  PHP_SELF --> /test/test.php
  *  REQUEST_TIME_FLOAT --> 1560324049.248
  *  REQUEST_TIME --> 1560324049

-------------------------------------------------
- EOF -------------------------------------------
-------------------------------------------------
Note that the Content Type is
Code:
application/x-www-form-urlencoded
, that is because when the
Code:
multipart/form-data
is set, i got no entries in the header.

Im wondering if the data is not being correctly sent to the server in a meaningful way, namely the API key seems to be invalid, but when i cURL it with my terminal, the key works just fine. So the key is correct.

Here is my upload code:
JavaScript:
function upload(){
    if(currentBase64Image != " " && currentBase64Image != ""){
        //============================================================================================================
        var CUSTOMER_ENDPOINT = "https://piccastle.com/api/1/upload/";
        //var LOCAL_ENDPOINT = "http://192.168.1.101/test/test.php";

        $.ajaxSetup({
            // DOES NOT WORK. PHP server returns all vars as unset.
            //contentType: "multipart/form-data; boundary=!XIS"
        });

        var jqueryXHR = $.post(LOCAL_ENDPOINT,{
            key: getApiKey(),
            source: currentBase64Image.split(",")[1], // Removing the header info from the image, as to send the RAW image with no META
            //pretty: "true", // TEST SERVER VAR
            format: "json"
        },function(data,status){
            // Success
            if(isJSONValid(data['responseText'])){
                // Response is JSON
                var json = JSON.parse(data['responseText']);
                if(window.ismodules["ISNotification"] && window.ismodules["Color"]){
                    new ISNotification(GREEN,"Image Upload Successful",SECOND * 5,BOTTOM).show();
                }
            }else{
                // Response is probably text.
                if(window.ismodules["ISNotification"] && window.ismodules["Color"]){
                    new ISNotification(YELLOW,data,SECOND * 5,BOTTOM).show();
                }
            }
            console.log(data);
        });

        jqueryXHR.fail(function(data){
            if(isJSONValid(data['responseText'])){
                // Response is JSON
                var json = JSON.parse(data['responseText']);
                if(window.ismodules["ISNotification"] && window.ismodules["Color"]){
                    var msg = json["error"]["message"];
                    var rest = json["status_txt"];
                    new ISNotification(RED,rest + ", " + msg,SECOND * 5,BOTTOM).show();
                }
            }else{
                // Response is probably text.
                if(window.ismodules["ISNotification"] && window.ismodules["Color"]){
                    new ISNotification(RED,"Error: " + data,SECOND * 5,BOTTOM).show();
                }
            }
            console.log(data);
        });
    }
}
EDIT:
Hope you can help :) and as far as i can see there is not any url corruption as a result of the content type, i think that only occurs when sent via the URI, but this data is sent in the request body, and seems to match, in other words, it matches and is binary equivalent to the source, so it has to be how i make requests.
 

DravenLewis

New Member
There is also an error in the code that is an artifact from me switching to my dev server, the POST request should be open on "CUSTOMER_ENDPOINT" and i forgot to change it from "LOCAL_ENDPOINT" prior to upload, but with the test i did, the request was open to "CUSTOMER_ENDPOINT"
 

Rodolfo

Chevereto Developer
Chevereto Staff
The only thing that I can think of is to use xhr directly and not use $.post or any of those. Either that or make sure that the thing you use fit the purpuse of sending files as multipart or unaltered base64. If you touch the base64 just make absolute sure to send something that php will understand.

Also, you should test the request using postman or something like that. It is made to test http requests.

If you want to know how php is getting the request, do G\debug($_REQUEST); inside app/routes/route.api.php
 
Top