Skip to main content
Participant
January 18, 2023
Question

Need To Replicate a cURL call With CFHTTP

  • January 18, 2023
  • 3 replies
  • 834 views

Hello:

I need to replicate the following cURL call, which uses a multipart/form-data header and form fields:

 

curl -L -R POST "https://api.XXXXXXXX.com/api/v1/academic_success/sync/enrollment" \
-H "Authorization: Bearer <access_token>" \ # Generated OAuth2 token request
-H "Content-Type: multipart/form-data" \
-F "input_type=CSV" \
-F "input_data=@enrollment_upload.csv" \ # Path to CSV file. Include '@' before path.
-F "dry_run=false" \ # Set to true when testing
-F 'drop_not_passed_enrollments=true' \ # only enabled when dry_run = false

 

CFHTTP does not allow specifying form fields for multi-part data. I assume I'd have to code a header that included the form fields as part of the body along with the data, but am unclear on how to do this. We are currently production with CF 2018.

Thanks.

Gerry, Pace University

 

    This topic has been closed for replies.

    3 replies

    Participant
    January 25, 2023

    BKBK:  let me first apologize for not responding sooner. I just got a chance a little while ago to run your code, it failed though it mentioned the request was well formed (see message below). The field that the says was missing, you did have in code. It appears that the site couldn't parse the payload correctly.  I get the feeling that I will need do boundary headers for the form fields manually and add them to body to get it to be consumed properly. Again, apologies for the very late response, I am very appreciative of your assisting us  in this matter.  Gerry, Pace University

     

    Return Code Is 422 UNPROCESSABLE ENTITY

    Returned Variables - struct

    messageThe request was well-formed but was unable to be followed due to semantic errors.
    messagesReturned Variables - struct
    input_typeReturned Variables - array
    1Missing data for required field.
    status422
    BKBK
    Community Expert
    Community Expert
    January 26, 2023

    The error message suggests that the API understands the request, but perhaps requires a slightly different representation. So what happens when you send a JSON rather than a JSON string. That is, test with the following line

    CFHttpParam( Type="Body" , Value=#serializeJson(REQUEST.LoadBody)# ) ;
    Participant
    January 26, 2023

    BKBK: I did, I used the exact code you sent, with the one exception of course of it going to the actual vendor site. Below is the code that was run.  Gerry

     

    <CFSCRIPT>

    // Code From BKBK

    //REQUEST.ApiEnrollment = "http://httpbin.org/post"

    //REQUEST.DataBlob=fileread("full_path_to_CSV_file");
    //REQUEST.ApiEnrollment="API_URL";

    REQUEST.LoadBody=structNew();
    REQUEST.LoadBody.input_type="CSV";
    REQUEST.LoadBody.dry_run="true";
    REQUEST.LoadBody.input_data=REQUEST.DataBlob;

    CFHttp( Url="#REQUEST.ApiEnrollment#" , Method="POST" , ThrowOnError="YES", TimeOut="450" )
    {
    CFHttpParam( Type="Header" , Name="Authorization" , Value="#REQUEST.Token#" );
    CFHttpParam( Type="Header" , Name="X-TW-PersonId" , Value="#REQUEST.XTWPersonId#" );
    Cfhttpparam( Type="Header" , Name="Content-Type" , value="application/json");
    CFHttpParam( Type="Body" , Value="#serializeJson(REQUEST.LoadBody)#" ) ;
    }

    WriteOutput( '<br/>***** PROGRAM: Send Student Data</br></br>' ) ;
    WriteOutput( 'Return Code Is ' & CFHTTP.StatusCode ) ;
    WriteOutput('<br/><br/>') ;

    Returned = deserializeJSON( CFHttp.FileContent ) ;
    WriteDump( Var="#Returned#" , Label="Returned Variables" ) ;

    </CFSCRIPT>

    Participant
    January 18, 2023

    BKBK:

    Thank you for getting back to me. The code is below, I assume it needs to have request headers for the form variables added, along with multi part header commented out in the CFHTTPPARAM. Just not sure of the exact specification for the headers and their order, I assume the form variables would come before the data (CSV) being sent.

    Gerry, Pace University

    <CFSCRIPT>

    REQUEST.ApiEnrollment = "http://httpbin.org/post"

     

    // The contents for the BODY, but need to include headers for the form variable
    REQUEST.LoadBody = "" ;
    REQUEST.LoadBody = REQUEST.LoadBody & "input_type=CSV&" ;
    REQUEST.LoadBody = REQUEST.LoadBody & "dry_run=true&" ;
    REQUEST.LoadBody = REQUEST.LoadBody & "input_data=" & REQUEST.DataBlob ;
    REQUEST.LoadBody = UrlEncodedFormat( REQUEST.LoadBody ) ;

    CFHttp( Url="#REQUEST.ApiEnrollment#" , Method="POST" , ThrowOnError="YES" , MultiPart="YES" , MultiPartType="RELATED" , TimeOut="450" )
    {
    CFHttpParam( Type="Header" , Name="Authorization" , Value="#REQUEST.Token#" ) ;
    CFHttpParam( Type="Header" , Name="X-TW-PersonId" , Value="#REQUEST.XTWPersonId#" ) ;
    // CFHttpParam( Type="Header" , Name="Content-Type:" , Value="multipart/form-data" ) ;
    // CFHttpParam( Type="FormField" , Name="input_type" , Value="CSV" ) ;
    // CFHttpParam( Type="FormField" , Name="input_data" , Value="#REQUEST.CsvName#" ) ;
    // CFHttpParam( Type="FormField" , Name="dry_run" , Value="true" ) ;
    CFHttpParam( Type="Body" , Value="#REQUEST.LoadBody#" ) ;
    }

    WriteOutput( '<br/>***** PROGRAM: Send Student Data</br></br>' ) ;
    WriteOutput( 'Return Code Is ' & CFHTTP.StatusCode ) ;
    WriteOutput('<br/><br/>') ;

    Returned = deserializeJSON( CFHttp.FileContent ) ;
    WriteDump( Var="#Returned#" , Label="Returned Variables" ) ;

    </CFSCRIPT>

    BKBK
    Community Expert
    Community Expert
    January 18, 2023

    The instructions at http://httpbin.org suggest you might be able to send JSON data. If so, then you could do it simply, without any need for multipart/form-data.

     

    Try something like:

    REQUEST.DataBlob=fileread("full_path_to_CSV_file");
    REQUEST.ApiEnrollment="API_URL";
    	
    REQUEST.LoadBody=structNew();
    REQUEST.LoadBody.input_type="CSV";
    REQUEST.LoadBody.dry_run="true";
    REQUEST.LoadBody.input_data=REQUEST.DataBlob;
    
    
    CFHttp( Url="#REQUEST.ApiEnrollment#" , Method="POST" , ThrowOnError="YES", TimeOut="450" )
    {
    	CFHttpParam( Type="Header" , Name="Authorization" , Value="#REQUEST.Token#" );
    	CFHttpParam( Type="Header" , Name="X-TW-PersonId" , Value="#REQUEST.XTWPersonId#" );
    	Cfhttpparam( Type="Header" , Name="Content-Type" , value="application/json");
    	CFHttpParam( Type="Body" , Value="#serializeJson(REQUEST.LoadBody)#" ) ;
    	 
    }

     

    Participant
    January 19, 2023

    BKBK:

    First, apologies on the delayed response, I'm severely slammed on time with another project. I hope that httpbin.org are correct ! I will given it a try as soon as I can, probably this evening.

    Thank you again for the assistance -- it is much appreciated.  Have a great day !

    Gerry, Pace University

     

    BKBK
    Community Expert
    Community Expert
    January 18, 2023

    Could you please share the cfhttp code that you used.