Android Question Curl Call

MarcoRome

Expert
Licensed User
Hi all, i have this code:

B4X:
curl -s --user 'api:key-c292cc778030d88b68e08b71a49fef6f' \
    https://api.mailgun.net/v3/sandbox7506614de5d448eaaeb72b7a58f4ad3c.mailgun.org/messages \
    -F from='Excited User <mailgun@sandbox7506614de5d448eaaev72b7a58f4ad0c.mailgun.org>' \
    -F to=info@devil-app.com \
    -F to=bar@example.com \
    -F subject='Hello' \
    -F text='Testing some Mailgun awesomness!

i translate in B4 so:

B4X:
Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("Layout1")

    Dim job1 As HttpJob
    job1.Initialize("MyToken", Me)
    job1.Username = "api"
    job1.Password = "key-c292cc778030d88b68e08b71a49fef6f"
    job1.PostString("https://api.mailgun.net/v3/sandbox7506614de5d448eaaeb72b7a58f4ad0c.mailgun.org/messages",$"{"from":"Excited User <mailgun@sandbox7506614de5d448eaaeb72b7a58f4ad0c.mailgun.org>","to": ["bar@example.com", "info@devil-app.com"],"subject": "Hello","text": "Testing some Mailgun awesomness!"}"$)
    job1.GetRequest.SetHeader("Content-Type", "application/json")
    job1.GetRequest.SetContentType("application/json")
    job1.GetRequest.SetContentEncoding("text/plain")
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub JobDone(Job As HttpJob)
   If Job.Success Then
           ToastMessageShow("Success", True)
        Dim res As String
        res = Job.GetString
        ToastMessageShow(res, True)
        'Log("Response from server: " & res)
        Select Job.JobName
        Case "MyToken"
            Dim parser As JSONParser
            parser.Initialize(res)
        
        End Select
        Else
        Log(Job.ErrorMessage)
         ToastMessageShow("errore: "  & Job.ErrorMessage, True)
        ProgressDialogHide
    End If

End Sub

And return: "BAD REQUEST"
I dont understand where i wrong
Any idea ???
 
Last edited:

DonManfred

Expert
Licensed User
Make a multipart post

-F, --form <name=content>
(HTTP) This lets curl emulate a filled-in form in which a user has pressed the submit button. This causes curl to POST data using the Content-Type multipart/form-data according to RFC 2388. This enables uploading of binary files etc. To force the 'content' part to be a file, prefix the file name with an @ sign. To just get the content part from a file, prefix the file name with the symbol <. The difference between @ and < is then that @ makes a file get attached in the post as a file upload, while the < makes a text field and just get the contents for that text field from a file.
So you need to add different key value pairs to the multipartpost to transmit all fields marked with -F
 
Upvote 0

MarcoRome

Expert
Licensed User
Hi Don, thank you for you quick response.
can you make a little example pls. I dont understand.
Thank you very much.
marco
 
Upvote 0

DonManfred

Expert
Licensed User
Thank you very much for your availability.
Try this. I have not worked with httpclient in the past but to transport username and password you need to use ExecuteCredentials on the httpclient.

Try the attached Example. UNTESTED!

PS: Please note that you need to use okHTTP
 

Attachments

  • multipartpost_marco.zip
    8.5 KB · Views: 167
Upvote 0

MarcoRome

Expert
Licensed User
Try this. I have not worked with httpclient in the past but to transport username and password you need to use ExecuteCredentials on the httpclient.

Try the attached Example. UNTESTED!

PS: Please note that you need to use okHTTP
Thank you very much for this :) but anyway i have same error "BAD REQUEST" ( 400 - Bad Request - Often missing a required parameter )

B4X:
Sub Activity_Create(FirstTime As Boolean)
    If FirstTime Then
        hc.Initialize("hc")
    End If
        Activity.LoadLayout("main")
    'Add name / values pairs (parameters)
    Dim NV As Map
    NV.Initialize
    NV.Put("from", "Excited User <mailgun@sandbox7506614de5d448eaaeb72b7a58f4ad0c.mailgun.org>")
    NV.Put("to", "info@devil-app.com")
    NV.Put("subject", "MySubject")
    NV.Put("text", "Body")
    Dim req As OkHttpRequest
    req = MultipartPost.CreatePostRequest("https://api.mailgun.net/v3/sandbox7506614de5d448eaaeb72b7a58f4ad0c.mailgun.org/messages", NV, Null)
    req.SetHeader("Content-Type", "application/json")
    req.SetContentType("application/json")
    req.SetContentEncoding("text/plain")   
    hc.ExecuteCredentials(req,1,"api","key-c292cc777030d88b68e08b71a49fef6f")
    'hc.Execute(req, 1)
End Sub

'curl -s --user 'api:key-c292cc777030d88b68e08b71a49fef6f' \
'    https://api.mailgun.net/v3/sandbox7506614de5d448eaaeb72b7a58f4ad0c.mailgun.org/messages \
'    -F from='Excited User <mailgun@sandbox7506614de5d448eaaeb72b7a58f4ad0c.mailgun.org>' \
'    -F To=info@devil-app.com \
'    -F To=bar@example.com \
'    -F subject='Hello' \
'    -F text='Testing some Mailgun awesomness!'


Sub hc_ResponseError (Response As OkHttpResponse, Reason As String, StatusCode As Int, TaskId As Int)
    Log("error: " & Response & " " & StatusCode)
   
    ToastMessageShow("Error" & Reason, True)
    If Response <> Null Then
    End If
End Sub

Sub hc_ResponseSuccess (Response As OkHttpResponse, TaskId As Int)
        out.InitializeToBytesArray(0) ' I expect less than 2000 bytes here
       Response.GetAsynchronously("Response", out, True, TaskId)
    ToastMessageShow("OK " & Response , True)
    Log("response: " & Response )
    'Msgbox(Response, "")
    'Response.Release
End Sub

Screenshot 2015-10-20 18.47.08.png



Screenshot 2015-10-20 19.29.21.png


Screenshot 2015-10-20 19.30.21.png
 
Upvote 0

MarcoRome

Expert
Licensed User
And this is version HttpUtils2 ( 2.10 )

Module request is:


In HttpJob Class add this:

B4X:
'Sends a multipart POST request.
'NameValues - A map with the keys and values. Pass Null if not needed.
'Files - List of MultipartFileData items. Pass Null if not needed.
public Sub PostMultipart(Link As String, NameValues As Map, Files As List)
    Dim boundary As String = "---------------------------1461124740692"
    Dim stream As OutputStream
    stream.InitializeToBytesArray(0)
    Dim b() As Byte
    Dim eol As String = Chr(13) & Chr(10)
    If NameValues <> Null And NameValues.IsInitialized Then
        For Each key As String In NameValues.Keys
            Dim value As String = NameValues.Get(key)
            Dim s As String = _
$"--${boundary}
Content-Disposition: form-data; name="${key}"
 
${value}
"$
            b = s.Replace(CRLF, eol).GetBytes("UTF8")
            stream.WriteBytes(b, 0, b.Length)
        Next
    End If
    If Files <> Null And Files.IsInitialized Then
        For Each fd As MultipartFileData In Files
            Dim s As String = _
$"--${boundary}
Content-Disposition: form-data; name="${fd.KeyName}"; filename="${fd.FileName}"
Content-Type: ${fd.ContentType}
 
"$
            b = s.Replace(CRLF, eol).GetBytes("UTF8")
            stream.WriteBytes(b, 0, b.Length)
            Dim in As InputStream = File.OpenInput(fd.Dir, fd.FileName)
            File.Copy2(in, stream)
            stream.WriteBytes(eol.GetBytes("utf8"), 0, 2)
        Next
    End If
    s = _
$"
--${boundary}--
"$
    b = s.Replace(CRLF, eol).GetBytes("UTF8")
    stream.WriteBytes(b, 0, b.Length)
    PostBytes(Link, stream.ToBytesArray)
    req.SetContentType("multipart/form-data; boundary=" & boundary)
    req.SetContentEncoding("UTF8")
End Sub

in you Main the code is:

B4X:
  'Activity.LoadLayout("main")
    'Add name / values pairs (parameters)
    Dim NV As Map
    NV.Initialize
    NV.Put("from", "Excited User <mailgun@sandbox7506614de5d448eaaeb72b7a58f4ad0c.mailgun.org>")
    NV.Put("to", "info@devil-app.com")
    NV.Put("to", "marco.amici@devil-app.com")
    NV.Put("subject", "MySubject")
    NV.Put("text", "Vediamo con una frase più lunga")
   
    Dim job2 As HttpJob
 
    'Send a POST request
    job2.Initialize("Job2", Me)
    job2.Username = "api"
    job2.Password = "key-c292cc777030d88b68e08b71a49fef6f"
    job2.PostMultipart("https://api.mailgun.net/v3/sandbox7506614de5d448eaaeb72b7a58f4ad0c.mailgun.org/messages", NV, Null)
    job2.GetRequest.SetHeader("Content-Type", "application/json")
    job2.GetRequest.SetContentEncoding("text/plain")
 
 
End Sub
 
 
Sub JobDone(Job As HttpJob)
   If Job.Success Then
        Dim res As String
        res = Job.GetString
        ToastMessageShow(res, True)
        'Log("Response from server: " & res)
        Select Job.JobName
        Case "MyToken"
            Dim parser As JSONParser
            parser.Initialize(res)
            ToastMessageShow("**Ok: " & res, Activity_Resume)
          
        End Select
        Else 
        Log(Job.ErrorMessage)
         ToastMessageShow("errore: "  & Job.ErrorMessage, True)
        ProgressDialogHide
    End If
    Job.Release
End Sub

That all.
 
Upvote 0

MarcoRome

Expert
Licensed User
I still dont understand. Does it work now? Or does it still NOT work? In post #10 you told about a BAD request

My suggestion was to try to remove the line
B4X:
job2.GetRequest.SetHeader("Content-Type", "application/json")
Don YES WORK without problem. I add also method for HttpUtilis2 (#14) and work also so ( Both Tested )
 
Upvote 0
Top