Post 'multipart/form-data' out of Salesforce.com APEX - http

I have an APEX Method that attempts to Post a form to a remote endpoint out of SFDC's APEX Code.
Everything seems to encode correctly, and the server sends back a 200 response, but the attachment isn't arriving with the request... is SFDC removing the content of my post body before it's sent?
HttpRequest req = new HttpRequest();
req.setHeader('Authorization','Basic '+EncodingUtil.base64Encode(Blob.valueOf('removed:removed')));
req.setHeader('Content-Type','multipart/form-data; boundary=-----------------------------153501500631101');
req.setHeader('X-Atlassian-Token','nocheck');
req.setMethod('POST');
req.setEndpoint(endPoint+'issue/'+c.Internal_Bug_Number__c+'/attachments');
String body = '-----------------------------153501500631101\r\n';
body = body + 'Content-Disposition: form-data; name="Filedata"; filename="'+attachments[0].Name+'"\r\n';
body = body + 'Content-Type: '+attachments[0].ContentType+'\r\n';
body = body + 'Content-transfer-encoding: base64\r\n\r\n';
body = body + attachments[0].Body+ '\r\n';
body = body + '-----------------------------153501500631101--\r\n';
req.setBody(body);

Try this solution. It's a messing solution with Blob+HttpResponse I've proposed. http://enreeco.blogspot.it/2013/01/salesforce-apex-post-mutipartform-data.html

You should be able to use EncodingUtil.urlEncode to ensure the form params. See https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_restful_encodingUtil.htm

Related

How would one send an HTTP POST request?

I'm using lua-http for HTTP requests in my Lua script. I'm trying to find a way to send data as a POST request, similar to the -d option of curl.
I've tried new_from_uri:set_body() but I don't think I'm doing it correctly.
request = require "http.request"
headers, stream = assert(request.new_from_uri("https://example.org"):set_body("body text"))
headers, stream = assert(request.new_from_uri("https://example.org"):go())
body = assert(stream:get_body_as_string())
if headers:get ":status" ~= "200" then
error(body)
end
Could someone show me how to do this properly?
I've decided to use luasocket for this instead. Here is the code I'm using:
http = require "socket.http"
body = "body text"
respbody = {
result, respcode, respheaders, respstatus = http.request {
method = "POST",
url = "https://example.org",
source = ltn12.source.string(body),
headers = {
["content-type"] = "application/json", -- change if you're not sending JSON
["content-length"] = tostring(#body)
},
sink = ltn12.sink.table(respbody)
}
respbody = table.concat(respbody)

How to send HTTP SOAP request to local Sonos device with NodeMCU?

How do I send a simple HTTP POST/GET SOAP request to my Sonos loudspeaker in Lua?
I have tried simple HTTP POST and GET requests with success, but I do not know where to start with SOAP requests.
Note: I am a newbie at this. I have never worked with a NodeMCU before nor have I programmed in Lua. I have experience in other languages though.
I know how to do it in C#, Java and PHP.
This works in Postman:
HTTP Headers:
SOAPAction:urn:schemas-upnp-org:service:AVTransport:1#Pause
Content-Type:text/xml; charset="utf-8"
Host:192.168.0.10:1400
BODY:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:Pause xmlns:u="urn:schemas-upnp-org:service:AVTransport:1"><InstanceID>0</InstanceID></u:Pause></s:Body></s:Envelope>
What I did is this and it does not work:
sendRequest("192.168.0.10")
function sendRequest(url)
print("Sending request to Sonos Playbar...")
sk = net.createConnection(net.TCP, 0)
sk:on("receive", function(sck, c) print(c) end )
sk:on("connection", function(sck, c)
print("\r\n\r\n\r\n")
-- HTTP 405: Method not allowed
-- sck:send("POST / HTTP/1.1\r\nHost: "..url..":1400\r\nConnection: keep-alive\r\nAccept: */*\r\n\r\n")
-- HTTP 500, UPnP 402: Invalid arguments
-- sck:send("POST /MediaRenderer/AVTransport/Control HTTP/1.1\r\nHost: "..url..":1400\r\nSOAPAction:urn:schemas-upnp-org:service:AVTransport:1#Pause\r\nConnection: keep-alive\r\n\r\nAccept: */*\r\n\r\n")
local content = nil;
content = "POST /MediaRenderer/AVTransport/Control\r\n"
content = content.."Host:192.168.0.10:1400\r\n"
content = content.."Content-Type:text/xml; charset=utf-8\r\n"
content = content.."SOAPAction:urn:schemas-upnp-org:service:AVTransport:1#Pause\r\n"
content = content.."\r\n"
-- SOAP Body
content = content.."<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\""
content = content.." s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
content = content.."<s:Body>"
content = content.."<u:Pause xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\">"
content = content.."<InstanceID>0</InstanceID>"
content = content.."</u:Pause>"
content = content.."</s:Body>"
content = content.."</s:Envelope>"
-- SOAP Body End
print(content.."\r\n\r\n\r\n")
sck:send(content);
end)
sk:connect(1400, url)
end
I am getting this response of my Sonos player:
HTTP/1.1 500 Internal Server Error
CONTENT-LENGTH: 347
CONTENT-TYPE: text/xml; charset="utf-8"
EXT:
Server: Linux UPnP/1.0 Sonos/34.16-37101 (ZPS9)
Connection: close
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<s:Fault>
<faultcode>s:Client</faultcode>
<faultstring>UPnPError</faultstring>
<detail>
<UPnPError xmlns="urn:schemas-upnp-org:control-1-0">
<errorCode>401</errorCode>
</UPnPError>
</detail>
</s:Fault>
</s:Body>
</s:Envelope>
What am I doing wrong? I copied and paste the text, basically. Maybe it is the order of headers? Maybe I am declaring the headers wrong or something?
I don't have a Sonos device to play with. Thus, this ain't a confirmed answer.
The string in your content variable is not a valid HTTP request. Sonos doesn't understand it as the error code 401 means "invalid action".
You need the separate HTTP headers with \r\n. An extra \r\n needs to be placed right before the HTTP body. Therefore, I'd expect that your content should be:
"POST http://192.168.0.10:1400/MediaRenderer/AVTransport/Control\r\n
SOAPAction:urn:schemas-upnp-org:service:AVTransport:1#Pause\r\n
Content-Type:text/xml; charset=\"utf-8\"\r\n
Host:192.168.0.10:1400\r\n\r\n
<s:Envelope xmlns:s=\"http://schemas.xml......"
Finally! I have it working! Below is the code to get it working:
sendRequest("192.168.0.10")
function sendRequest(url)
print("Sending request to Sonos Playbar...")
local content = nil;
content = "";
-- SOAP Body
content = content.."<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\""
content = content.." s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
content = content.."<s:Body>"
content = content.."<u:Pause xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\">"
content = content.."<InstanceID>0</InstanceID>"
content = content.."</u:Pause>"
content = content.."</s:Body>"
content = content.."</s:Envelope>"
-- SOAP Body End
http.post("http://"..url..":1400/MediaRenderer/AVTransport/Control",
'Content-Type: text/xml; charset="utf-8"\r\n'..
'Host:'..url..':1400\r\n'..
'SOAPAction:urn:schemas-upnp-org:service:AVTransport:1#Pause\r\n',
content, function(code, data)
if(code < 0) then
print("HTTP request failed with code "..code)
else
print(code, data)
end
end)
end

How does HTTP POST work in Polymer?

I want to know how POST calls work in Polymer. I know that I have to use POST calls for sending sensitive information such as user passwords and access tokens. I tried doing this :
<iron-ajax
id="AjaxPost"
url="/api/login"
method="POST"
content-type="application/x-www-form-urlencoded"
handle-as="json"
on-response="_handleAjaxPostResponse"
on-error="_handleAjaxPostError"
></iron-ajax>
this.$.AjaxPost.params = { email: "abc#gmail.com", password: "password" };
this.$.AjaxPost.generateRequest();
But, this will set the parameters in the URL, which can be viewed in the browser console like :
POST http://localhost:8080/api/login?email=abc%40mgail.com&password=password 400 (Bad Request)
The PUT method allows you to set the data in body, which I think is more secure. Now I have 2 questions :
Can we set the body of POST method too? Or setting params is same as setting body?
If that is possible, how should I extract the data in the server side?
PS: We are not using SSL HTTPS connection. Having said that, which method can be incorporated for better security?
The api document for iron-ajax defines body attribute as below:
body
Object default:
Body content to send with the request, typically used with "POST" requests.
If body is a string it will be sent unmodified.
If Content-Type is set to a value listed below, then the body will be encoded accordingly.
content-type="application/json"
body is encoded like {"foo":"bar baz","x":1}
content-type="application/x-www-form-urlencoded"
body is encoded like foo=bar+baz&x=1
Otherwise the body will be passed to the browser unmodified, and it will handle any encoding (e.g. for FormData, Blob, ArrayBuffer).
To send the data as body, you should modify your request as below
<iron-ajax
id="AjaxPost"
url="/api/login"
method="POST"
content-type="application/json"
handle-as="json"
on-response="_handleAjaxPostResponse"
on-error="_handleAjaxPostError"
></iron-ajax>
this.$.AjaxPost.body = { "email": "abc#gmail.com", "password": "password" };
this.$.AjaxPost.generateRequest();

Does get request need content type and accept header?

I am making web request and method is get.Does I need to mention content-Type and accept for get method?or it just require for post method
string strURL = "web address";
Uri uri = new Uri(strURL);
HttpWebRequest webRequest = System.Net.WebRequest.Create(uri) as HttpWebRequest;
webRequest.Method = WebRequestMethods.Http.Get
webRequest.ContentType = "application/json";
webRequest.Accept = "application/json";
content-type : It is not required in the GET request as you are not sending any content in the request body.
content-type indicates the media type of the entity-body sent to the recipient.
Accept : It depends on your requirement. If you want to restrict the media type in your response then you can use it otherwise leave it.
The Accept request-header field can be used to specify certain media types which are acceptable for the response.

use of "application/x-www-form-urlencoded" in HTTP Post method

What is the meaning of
ContentType = "application/x-www-form-urlencoded"
in HTTP Post method..??
my code is
Uri url = new Uri(" http://blah/blah/blah...json");
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Method = "POST";
webRequest.ContentType = "application/x-www-form-urlencoded";
I have been using ContentType = "application/x-www-form-urlencoded" in particular project. What I know is, it is the scheme that is used, so the POST parameters you are sending to the server are in the form-urlencoded. For example, if you send the parameter key-value like below:
name=Agung
id=121
then, when you send the request, the POST body will be like encoded to be like this:
name=Agung&id=121
When you are setting ContentType = "application/x-www-form-urlencoded", then the server will know how to parse the Body parameter you are sending.
Hope it will help
This is used for Security purpose.
you can get more help here.

Resources