How to avoid multipart/form-data with XMLHTTPRequest and FormData - aws-lambda

I'm trying to setup an html form, the form action is an aws lambda function.
When I submit the form via plain html, all is well. However, when I'm sending the form via XMLHTTPRequest + FormData the lambda function breaks.
Looking at the lambda logs it seems that when using the plain html form send, the form is encoded in the request body as straight forward query string ('name=Johnny&email=john%40bon.com' etc) which my lambda function can parse.
However, when using XMLHTTPRequest+FormData to send the form, the form is encoded in using a different format which I believe (not sure) is called multipart/form-data (has these WebKitFormBoundaryXXX additions).
Is there a way to make XMLHTTPRequest+FormData send the form in the same format as is used when sending the form via plain html. Alternatively, how to do parse this multipart/form-data format in aws lambda python.
const form = document.querySelector('#my-form-id')
form.addEventListener('submit', event => {
// disable default action
event.preventDefault()
// configure a request
const xhr = new XMLHttpRequest()
xhr.open('POST', 'www.myurl.com/submit')
// prepare form data
let data = new FormData(form)
// set headers
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
// send request
xhr.send(data)
// listen for `load` event
xhr.onload = () => {
console.log(xhr.responseText)
}
})```

Is there a way to make XMLHTTPRequest+FormData send the form in the same format as is used when sending the form via plain html.
Well. It does… for a value of plain HTML with enctype='multipart/form-data'.
If you want to send application/x-www-form-urlencoded data then FormData is the wrong tool for the job.
Use URLSearchParams instead.
You can initialise it with a FormData object.
const data = new URLSearchParams(new FormData(document.querySelector('form')));
console.log(`${data}`);
<form>
<input name=foo value=bar>
<input name=x value=y>
</form>
Note that XMLHttpRequest can infer the Content-Type header when you pass a URLSearchParams or FormData object to send() so don't set it manually. That is just a waste of time and an opportunity to introduce errors.

Quentin's solution works. Here's the corrected code:
form.addEventListener('submit', event => {
// disable default action
event.preventDefault()
// configure a request
const xhr = new XMLHttpRequest()
xhr.open('POST', 'www.myurl.com/submit')
// send request
xhr.send(new URLSearchParams(new FormData(form)))
// listen for `load` event
xhr.onload = () => {
console.log(xhr.responseText)
}
})```

Related

Set Session value from JavaScript and Get Session value in C#

Is it available to set the value from javascript(Session / ViewState) and get the value in C# without using hidden field??
Its work to store the value from javascript , and available to get the value in C# (page.request["Token"]) , but its not working for me because there have a postback action " form.submit();"
function setToken(Token) {
try {
var form = document.createElement("form");
var field = document.createElement("input");
field.setAttribute("type", "hidden");
field.setAttribute("name", 'Token');
field.setAttribute("value", accessToken);
form.appendChild(field);
document.body.appendChild(form);
form.submit();
} catch (err) {
}
}
If you want to submit a value from your clientside code to your serverside code, you'll need to submit it in some kind of request. A form post would be one way, but if you don't want the page to reload it could equally well be an AJAX request:
function setToken(accessToken) {
$.post('/SetToken', { Token: accessToken });
}
Using jQuery there as it'll save you a lot of the trouble involved in getting AJAX to work the same way across browsers.
In the example I'm posting a request to a page called /SetToken, which could be any url in your website where you have code that can update the token. Your own example submits a form without an action, which means it'll submit to the current page. You could easily do that as well
$.post(location.href, { Token: accessToken });

Send Multiple data with ajax

I want to use ajax for add data in database and i found following code in net and it is working fine.
<script language='javascript'>
reqObj=null;
function saveCust(){
document.getElementById('res').innerHTML='processing';
if(window.XMLHttpRequest){
reqObj=new XMLHttpRequest();
}else {
reqObj=new ActiveXObject('Microsoft.XMLHTTP');
}
reqObj.onreadystatechange=processSave;
reqObj.open('POST','./custSave?reqObj.open('POST','./cName?id='+document.getElementById('CustCode').value,true);,true);
reqObj.send(null);
}
function processSave(){
if(reqObj.readyState==4){
document.getElementById('res').innerHTML=reqObj.responseText;
}
}
</script>
Above code sends only one String but, i have 5 Strings in my form.
Please anybody alter the code for sending multiple data.
The problem is that you're sending a single parameter in the reqObj.open function:
reqObj.open('POST','./custSave?reqObj.open('POST','./cName?id='+document.getElementById('CustCode').value,true);,true);
Note that the only parameter you send is id.
You can add more parameters in the flavor of QueryString:
id=something&otherParameter=else //and more parameters
IMO the easiest way to handle an ajax request would be using jQuery, as shown and heavily explained by BalusC in How to use Servlets and Ajax?.
Based on the samples there and jQuery Ajax POST example with PHP, you can come with the following code:
Assuming the 5 Strings are in the form
function saveCust(){
$('#res').html('processing');
var $form = $(this);
var serializedData = $form.serialize();
$.post('./custSave', serializedData, function(responseText) {
$('#res').html(responseText);
});
}
Assuming there's data outside the form
function saveCust(){
$('#res').html('processing');
var $form = $(this);
var serializedData = $form.serialize() + "&id=" + $('#CustCode').val();
$.post('./custSave', serializedData, function(responseText) {
$('#res').html(responseText);
});
}
And you can even enhance this using more jQuery functions, but that's outside the scope of this answer.

How do I send arbitrary JSON to node.js without a page reload?

My ultimate goal is to send an arbitrary JSON to node.js when a button is clicked. I currently only know how to send input from a form. Here's some code I put together to send form information:
function postForm() {
$('form').submit(function(e) {
e.preventDefault(); // no page reload
$.post(
$(this).attr('action'),
$(this).serialize(),
function(data) { console.log('Code for handling response here.') },
'json'
);
});
}
Where the HTML looks like:
<form action='/send' method='post'>
<input name= "foo" type="radio" value=1>
<input type="submit" value="Submit">
</form>
And the relevant express/node.js code looks like:
app.post('/send', function(request, response) {
fs.appendFile('test.txt', JSON.stringify(request.body) + '\n', function(e) {
if(e) throw e;
console.log(request.body);
});
});
However, I don't know how to adapt this example to use data that is not from form input. To give context, I'm building a web-based user study, and I want to send various information collected about the user to node.js. I've tried variants of what was working for the form submission, but none of my attempts have been successful. My impression was that I could just swap out $(this).serialize() to any other data that the client can access, but I couldn't get this line of thought to work. I also tried altering some of the many .ajax() examples, but those always redirected the page which is undesirable, since my study will lose user-state information if the page refreshes.
I've done decent amount of client and server side programming, but I have next to no knowledge about how ajax works, which is proving rather problematic for solving this! And also rather silly since, often times, that's what glues the two together :)
Since you're using jQuery, sending data is simple – call $.post(url, data) from the button's click handler:
$('#somebutton').click(function() {
var data = { key: 'value', ... };
$.post('/send', data, function(res) {
// success callback
});
});
The browser will POST to url with a URL-encoded serialization of the data argument.
POST /send HTTP/1.1
Content-Type: application/x-www-form-urlencoded
...
key=value&...
Which Express' bodyParser will have no trouble with. Alternatively, you can tell jQuery to send a JSON serialization of data:
$.post('/send', data, function(res) {}, 'json');
In your case, it really doesn't matter how jQuery transmits the data (URL encoded or JSON), since bodyParser automatically deserializes both formats.

Information Bar appears in IE8 while downloading

I have an application in which there are options to Export the document in Word/PDF format. We do a form submit to post the HTML and send it to the server for conversion. In the back-end the servlet writes it back to client after setting a contentType. The Information Bar appears during the first download only.
I cannot recommend users to reduce their Browser Security levels. Hence i need a solution to by-pass this alert. I saw that Google Docs has handled this. Does anyone have an idea about what needs to be done ?
I'm using the following JQuery code:
$.download = function(url, data, method){
//url and data options required
if( url && data ){
//data can be string of parameters or array/object
data = typeof data == 'string' ? data : $.param(data);
//split params into form inputs
var inputs = '';
$.each(data.split('&'), function(){
var pair = this.split('=');
inputs+='<input type="hidden" name="'+ pair[0] +'" value="'+ pair[1] +'" />';
});
//send request
$('<form action="'+ url +'" method="'+ (method||'post') +'">'+inputs+'</form>')
.appendTo('body').submit().remove();
};
};
And each time download should be initiated, I'm firing
$.download(options);
Server response is with proper content-type headers (e.g. Word).
Maybe you have forgotten to remove submitted form from the DOM?

What do browsers want for the Content-Type header on json ajax responses?

I am returning some json which needs to be handled by javascript as the response to an XMLHTTPRequest.
If I set the response's content type to "text/plain", all browsers but Chrome will accept it and pass it to my JS with no problem. However, Chrome will wrap the response in
<pre style="word-wrap: break-word; white-space: pre-wrap;">
before passing it to my javascript.
If I set the response's content type to the "proper" "application/json" all browsers but Firefox will accept it and pass it to my JS with no problem. Firefox, however will ask to save or open the response as a file.
What's the correct, cross-browser Content-Type?
You may solve the issue by parsing the response into the JSON object by using jQuery funcion parseJSON - http://api.jquery.com/jQuery.parseJSON/
The parameter you pass into the function is the JSON object string, which you extract from the response data:
function AjaxResponse (data) { // AJAX post callback
var jsonResult = $.parseJSON(data.substring(data.indexOf("{"), data.lastIndexOf("}") + 1));
}
Tested (besides Chrome which problem this solves) in FF and IE8 for the following simple JSON result, for other browsers and more complex responses no guarantees...
NOTE: the content type in this case is text/plain or text/html I think - I've used the following ASP.Net MVC function to return the result
ContentResult System.Web.Mvc.Controller.Content(string content);
Where I returned the JSON object like
System.Web.Script.Serialization.JavaScriptSerializer jsonSerializer
= new System.Web.Script.Serialization.JavaScriptSerializer();
var jsonResponse = jsonSerializer.Serialize(
new { IArticleMediaId = 0
, ImageUrl = Url.Content(fullImgPath)
});
return Content(jsonResponse);
In ajaxFileUpload.js in uploadCallback() replace
io.contentWindow.document.body.innerHTML.innerHTML
with
$(io.contentWindow.document.body.innerHTML).html()

Resources