I'm wondering if there's any simple way to create a link to submit a POST request to the server by using some Express.js technique or plugin.
It is also a way to secure more critical actions such as deletion of users. Adding also CSRF protection.
This is quite simple to do in some PHP frameworks such as CakePHP (with its postLink helper).
The way I'm doing it right now is by creating a hidden form by myself and adding in the html link an event to submit the form:
<form action="/users/delete/{{user.id}}" method="post" name="deleteUser{{ user.id }}" style="display:none;">
<input type="hidden" name="_csrf" value="{{ csrfToken }}" />
</form>
<a href="#" onclick="if (confirm('Are you sure you want to delete this user?')) { document.deleteUser{{ user.id }}.submit(); } event.returnValue = false; return false;">
Delete
</a>
This is exactly the way it works in CakePHP framework as well.
Inorder to create link to a POST request you can make use of client side techniques like capturing the click using javascript and generate a ajax post request to the server, Inoder to avoid CSRF attacks express middlewares are available(https://github.com/expressjs/csurf)
I ended up creating my own way to deal with them by using jQuery (but could also be done with javascript as well).
In my case, any link I want to send by POST will have to:
Contain the class postLink.
Contain the destination URL in the href attribute.
Contain the CSRF token in the data-csrf attribute.
Optionally contain the data-confirm attribute to specify a message to show as a confirmation before sending the POST request.
A link in the view would look like so:
<a href="/reject/23" class="postLink" data-confirm="Are you sure you want to reject this item?" data-csrf="NdiuZynW-thVmMqYPZqFFGxGcInQZn35mDf8">
Reject
</a>
Or without the confirm attribute:
<a href="/reject/23" class="postLink" data-csrf="NdiuZynW-thVmMqYPZqFFGxGcInQZn35mDf8">
Reject
</a>
The needed jQuery code is the following:
$(document).on('click', '.postLink', function(e){
e.preventDefault();
var url = $(this).attr('href');
var csrf = $(this).data('csrf');
var confirmed = false;
if(typeof $(this).data('confirm') !== 'undefined'){
if(confirm($(this).data('confirm'))){
confirmed = true;
};
}else{
confirmed = true;
}
if(confirmed){
$('body').append('\
<form action="'+ url +'" method="post" name="postLink" style="display:none;">\
<input type="hidden" name="_csrf" value="'+ csrf +'" />\
</form>\
');
$('form[name="postLink"').submit();
}
});
Basically what it does is applying the same technique of creating a form for each POST link that I mentioned in my question. The only difference is that I don't have to be bothered to create a form every time I want to create POST link.
This way the form will be created dynamically and appended to the body. Then submitted.
To make it secure I made use of the CSRF module for express.js.
If you don't need a secure POST link, then you probably could use the postLink plugin for jQuery.
Related
I have a form In their it has a cancel button. when that button is clicked a confirm box will appear and ask whether user needs to leave the page then i need to redirect the page .I'm using codeigniter and I did this but it is redirects to same page.I don't know why? can anyone help me?
View(busineeRateView.php)
<?php $Vehicleid=$details['id']; ?>
<input type="submit" name="cancelreview" class="btn btn-primary btn-lg" value="CANCEL" onClick="return cancelConfirm();">
<script>
function cancelConfirm() {
job = confirm("Are you sure you want to cancel and leave this page?");
if (job == true) {
window.location.href = "http://localhost/ci/adpreview_ctrl/getad_preview/".$Vehicleid;
return true;
}
}
</script>
controller
public function loadReviewPage($vehicleid){
$data=array();
$data['details']['id']=$vehicleid;
$this->load->view('pages/templates/header');
$this->load->view('pages/businessRateView',$data);
$this->load->view('pages/templates/footer');
}
Since you return true from the event handler, the submit button submits the form.
Since that comes after the location assignment, it overwrites it.
Submitting a form will reload the current page (assuming form doesn't have an action attribute and the submitted data doesn't cause the server to return a different page).
Don't use a submit button. Your JavaScript is doing little more than simulating a link, so use a real link.
<a class="btn btn-primary btn-lg"
href="http://localhost/ci/adpreview_ctrl/getad_preview/$Vehicleid"
onclick="return cancelConfirm();">
Cancel
</a>
and
function cancelConfirm(){
return confirm("Are you sure you want to cancel and leave this page?");
}
NB: You seem to have left some PHP in your example. Make sure you express your URL in valid HTML/JS.
this line is confusing:
window.location.href = "http://localhost/ci/adpreview_ctrl/getad_preview/".$Vehicleid;
Seems you mix javascript and php. Concatenating strings in JS is done with +, not . which is php syntax. and php variables like $Vehicleid are not accessible directly in JS. Try to use a php block for that. like:
window.location.href = "http://localhost/ci/adpreview_ctrl/getad_preview/" + "<?= $Vehicleid; ?>";
I think maybe you use the wrong operation. You should use '+' instead of '.' in javascript string operation. '.' is used in php:)
window.location.href = "http://localhost/ci/adpreview_ctrl/getad_preview/" + $Vehicleid;
Here's a challenge:
I don't care about which language to use, Javascript, PHP, .. whatever.
I need the most simple way to let my user upload an image.
I will later offer the user a way to place it on a canvas (displayed inside a div, with jquery draggable)
I can not have the page refreshed since there are useful variables in other fields etc..
(I don't have any security preferences as this will be a local website for intranet)
I tried:
<form action="upload_file.php" method="post" enctype="multipart/form-data">
<label for="file">Filename:</label>
</br>
<input type="file" name="file" id="file" size="70%"><br>
</br>
<input type="submit" name="submit" value="Submit">
</form>
But then came to realise there are soo many options out there, such as uploadify, and i easily got lost online..
You have two choices to make a file upload w/o refreshing the page:
Use HTML5 form upload
Post the form to an hidden iframe
The latter one gives best browser compatibility, and is what I'd suggest you to use. To post to an hidden iframe, simply set the target of the form to the iframe:
<script>
// Global callback function from the file
function uploadCallback(){
console.log("File is uploaded!");
}
</script>
<iframe name="hiddentarget" style="display:none;"></iframe>
<form action="upload_file.php" method="post" enctype="multipart/form-data" target="hiddentarget">
...
To respond back to the site from the iframe, you will have to go through the window.top frame as such:
upload_file.php:
<?php
// Uploading stuff
// ...
// "Talk" back to the site
// Of course you can (should) pass some parameter to this JS-function, like the filename of the recently uploaded image.
echo "<script>window.top.uploadCallback();</script>";
?>
EDIT:
As suggested by other users; the optimal solution would be to use the File API where supported, and fall back to the hidden iframe on browser that doesn't support it. This gives you nice features such as file uploda progress for example.
The way that I would suggest is using AJAX and and make your upload box a div which can be replaced when the upload is successful. Instead of traditional post you then create a Javascript function for onSubmit. Your action can then be changed to #.
If you lookup AJAX there are some great tutorials about and you will be able to do many more amazing things.
Alternatively look into jQuery which will definitely have something to help you
I'm gonna show you an example on how to use the jQuery Form Plugin to upload files to your server really easy without needing to refresh the page.
First off, download and install the jQuery Form Plugin. After you do that, include it in your files where you want to make use of it. Add an ID attribute to your form tag like this:
id="unique_id"
After you have identified the upload form, put this code in your jQuery:
$(function() {
$('#unique_id').ajaxForm({
target: '.myTarget' // Display here whatever the server side script returns
success: function(response) {
// An usual success callback
}
})
})
Assuming that your server side language is PHP, this is how a simple upload script would look like (upload_file.php):
<?php
$uploaddir = 'your_upload_dir/something';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']); // Filename
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
echo $uploadfile;
} else {
echo "Error";
}
?>
Where userfile is the name attribute of your file input (<input type="file" />).
The above code combined returns the relative path to your image which you can use to display the image inside an img tag. You must use Javascript (or jQuery) for that.
I have a form on a website that is not directly selectable (as it is embedded in a javascript). So selecting it via mechanize browser object is not possible. What i want to do is to create a form just like that one and submit it using the browser object.
The form is
<form method="POST" action="Action.php?action=338&n=66&t=mine">
<input id="Mine66" type="hidden" value="22" name="duree">
<button class="boutonsGeneral" value="submit" type="submit" name="travail">
<span class="infoBoutonsGeneral" title="">
Work
<span id="dureeMine66" class="boutonsGeneral_duree boutonsGeneral_dureePlus">22 hours</span>
</button>
</form>
I used firebug and here is the info. The URL posted to is http://www.renaissancekingdoms.com/Action.php?action=338&n=66&t=mine
Parameters
duree 22
travail submit
Request Headers From Upload Stream
Content-Length: 23
Content-Type: application/x-www-form-urlencoded
What i have done so far is that i managed to log into the site and did the following
form = mechanize.HTMLForm('http://www.renaissancekingdoms.com/Action.php?action=338&n=66&t=mine', method='POST')
form.new_control('duree', 'hidden', {
'id' : 'Mine66',
'value' : '22'})
form.fixup()
br.form = form
br.submit()
But this doesn't seem to work. Any ideas where i am going wrong?
have you tried going directly to the link passing the post data as a parameter? like this :
r = opener.open('http://example.com/', data)
where data is the post data as a dictionnary
So a follow up to this question: getting bad request from ruby on rails ssl post.
I fixed that problem and I make the next step in the transaction no problem. The problem I am facing is that their response is sent to an iFrame as a hidden form on an html document. The form then posts to a url that I provide them.
I have tried giving them localhost:3000/policies/complete making a controller action and a route resource for the post but it doesn't ever show anything.
- It just says javascript error unable to load resource: localhost:3000/policies/complete
So then I tried just /policies/complete (with the coresponding method in my policies controller complete) but for some reason instead of posting to that action - it posted to theirwebserver.com/policies/complete which obviously doesn't exist.
So since it looks like I have to pass in a whole url for it to work correctly the form is going to look like: <form method='Post' action='whatever whole url I give them'>
The form looks like this:
<form name="frmReturn" method="Post" action="localhost:3000/policies/hosted_checkout_complete">
<input name="PaymentID" type="hidden" value="the value you need really badly!">
<input name="ReturnCode" type="hidden" value="0">
<input name="ReturnMessage" type="hidden" value="Your transaction has been approved.">
</form>
Tl:DC How do I set up my app to handle that?
I can request that they use get to send the information back to me. If that would be easier to set up and accept please let me know!
You need to add the protocol (either http:// or https://) to the front of the action=
<form name="frmReturn" method="Post" action="http://localhost:3000/policies/hosted_checkout_complete">
However, I would NOT recommend doing this... You have completely missed the point of Rails routing. You should be doing something like this:
<form name="frmReturn" method="Post" action="<%= resource_url %>">
Ideally, you'd use the Rails form builders:
<%= form_for :resource, :action => 'hosted_checkout_complete' do %>
In our application, we need to refresh the page. Now I am using the onclick() event to call the below javascript method.
function refresh() {
document.getElementById('Question-Preview-ComboBox').style.display='none';
document.getElementById('Question-Preview-RelatedSRTicketDetails').style.display='none';
document.getElementById('Question-Preview-SignoffdetailControl').style.display='none';
document.getElementById('Question-Preview-RelatedTicketDetails').style.display='none';
document.getElementById('Question-Preview-PerformedBy').style.display='none';
document.getElementById('Question-Preview-TextBox').style.display='none';
document.getElementById('Question-Preview-CheckBoxMatrix').style.display='none';
document.getElementById('Question-Preview-Radio').style.display='none';
document.getElementById('Question-Preview-CheckBoxMatrixWOT').style.display='none';
document.getElementById('Question-Preview-MultiLineText').style.display='none';
if (windowDirty == true) {
showModal('doyouwanttosave');
}
else {
self.location = 'CreateQuestionnaireForm.html';
}
}
The above script will ask users before they refresh the page "Do you want to save" and will make a GET request to call the controller method to reload the page. But our requirement is to change the GET request to POST for the above same functionality. Please suggest how can I change a GET request to POST?
You will need to create a hidden form, add it to the document and then submit it by calling the .submit() on the form's DOM object.
Include the form tag and specify the action method as post
<form action="destination_url" METHOD=Post>
....
<input type=submit value="Submit" />
</form>
you need to create a form and submit it - than you'll have post request.