HTML & REST (dynamic "id" in a link) - html

I am using an HTML as a REST client. I need to send form data to a server.
On a server side (implemented with java), a path to my POST(i`m using POST to update my table) method is something like : #Path("http://www.something.com/{id}")
The path works fine, I have tested it with Postman and browser, but for my HTML client, I need the {id} part of
my link to be dynamic.
For example, I click on some product (lets assume, I have web page with some kind of products), the browser opens a new window, so I can update a information
about that product. To make an update, I need that product "id" to be in my link as follows : http://www.something.com/{id}
<form action="http://www.something.com/2" method="post">
<input name="id" type="hidden">
<input name="product_name">
<input name="product_size">
<input name="product_number">
<input type="submit" value="Add">
</form>
In the example, I just 'hardcoded' {id} to be equal to 2, and it works!
But how can I make http://www.something.com/{id} <-- this {id} part to be dynamic(in my index.html file)?

You will need to do two things
Give your form an id and name, for example
<form action="" method="post" name="my-form" id="my-form">
Write some JavaScript which sets the form's action dynamically on some action being performed, such as
document.getElementById("my-form").action = "http://www.something.com/"+myvar;
But in my opinion I think you would be better off using JavaScript to do the post directly, rather than try changing form actions.

Thank You for Your answers and special thanks to #Toby whose proposed solution worked! I`ll share my final solution in case some one runs in the same issue:
...
<body onload="getId('id')">
<div>
<form action="http://www.something.com/{id}" method="post" id="productForm">
<input name="id" type="hidden" id="id">
<input name="product_name">
<input name="product_size">
<input name="product_number">
<input type="submit" value="Add">
</form>
</div>
<script>
var query = window.location.search.substring(1);
var id = null;
function getId (variable){
var idArr = query.split("=");
id = idArr[1];
document.getElementById("productForm").action="http://www.something.com/"+id;
document.getElementById("id").value=id;
}
</script>
</body>
...
my java class with REST paths looks similar to this:
/**
* to access:
* http://www.something.com/{id}
* #param id
* #param product_name
* #param product_size
* #param product_number
*/
#Path("/{id}")
#POST
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void tableUpdate(#FormParam("id") int id,#FormParam ("product_name") String name, #FormParam ("product_size") String size, #FormParam ("product_number") String number){
...
}

Related

how to get path variable in URL instead of query param in form submit get request without JavaScript?

I have the form:
<form class="form" action="/bars" method="get" >
<input type="text" class="form-control" name="pid" id="pid" />
<button type="submit">Find By PID</button>
</form>
When submitted, I want to get URL as /bars/123 (assuming 123 was entered in input field). Instead I get /bars/?pid=123. How can I solve this without using JavaScript? I am using thymeleaf 3 with Spring Boot 2 where my controller code looks like:
#GetMapping("/bars/{pid}")
public List<Bar> findBypid(#PathVariable Integer pid, ... ) {
Bar bar barService.findBypid(pid);
// code omitted
// ......
}
I am not sure how ThymeLeaf can help here without using JavaScript.
You can't. Html (and ThymeLeaf) just wasn't built to work this way. You can either use JavaScript, or add special controller methods that forwards to the correct url. Something like this for example:
#GetMapping("/bars")
public String forwarder(#RequestParam String pid) {
return "redirect:/bars/" + pid;
}
#GetMapping("/bars/{pid}")
public List<Bar> findBypid(#PathVariable Integer pid, ... ) {
Bar bar barService.findBypid(pid);
// code omitted
// .
// .
// .
}

html code doesn't work in wordpress

this following code belongs to a wordpress custom plugin "upload". It basically creates a button to open a file browser to select one file.
<form class="file_input_uploadform" id="uploadform_2" name="uploadform_2" method="post" enctype="multipart/form-data">
<input align="center" type="button" id="input_2" value="Select File" class="file_input_button_hover">
<input type="file" accept=".$params[" pid"]="" "="" class="file_input_hidden" name="uploadedfile_2" id="upfile_2" tabindex="1" onchange="javascript: document.getElementById('fileName_2').value = this.value.replace(/c:\\fakepath\\/i, '');" onmouseout="javascript: document.getElementById('input_2').className = 'file_input_button'" onmouseover="javascript: document.getElementById('input_2').className = 'file_input_button_hover'" onclick="javascript: document.getElementById('messagelabel_2').innerHTML = ''; document.getElementById('inline_upload_message_2').style.display='none'; this.value = ''; document.getElementById('fileName_2').value = '';">
<input type="hidden" id="hiddeninput_2" name="hiddeninput_2" value="">
</form>
if we put it in a html editor, it works fine --- click on the button will pop up the file browser.
However if we put it in wordpress with
....
[upload uploadId="0"]
[upload uploadId="1"]
....
The first one doesn't work (didn't open the file browser) while the second one works(opens the file browser).
Is it any way to debug, or is it any reason why this would happen?
Search inside plugin's code for upload and you should find something like this:
add_shortcode( 'upload', 'upload_function' );
Then search for upload_function (or whatever the name of the function is). Then check what parameters the function accepts and how it works.
That way you shall find why this function doesn't accept 0 for uploadId.
More on Shortcodes: Wordpress Shortcode API

Spring REST for DELETE Request Method

I have the following method in my controller
#RequestMapping(value = "processPurchase/{poid}", method = RequestMethod.DELETE)
public String processOrder(#PathVariable int poid) {
// do some processing
return acceptPurchaseForm;
}
My HTML
<form id="purchase-list-form" class="form-horizontal" action="/MyNewApp/processPurchase/" method="post">
<input type="hidden" name="_method" value="delete">
<input type="hidden" name="poid" value="">
With the above I still get the following error
WARN : org.springframework.web.servlet.PageNotFound - Request method 'DELETE' not supported
Any help appreciated.
First of all, I assume you have the HiddenHttpMethodFilter configured in your web.xml. It is required to convert your _method with value delete to the DELETE RequestMethod
Secondly, the poid is being passed in the body of the request but in your controller, you are expecting it to be passed in the URL itself. This might explain why Spring is unable to map the request.
EDIT 1:
To pass poid in URL, you will have to include in your form action when your HTML is generated. It depends on your view technology (I use Freemarker) but you would be required to do something like this:
<form action="/MyNewApp/processPurchase/${poid}" method="post">
Assuming that the poid is written to the model that is binded to your view.

Mapping one item posted in json object to the list object in Spring MVC

I have in trouble with posting json object and mapping it with List object in Spring MVC controller. I have the form that has several checkboxes. When a user checks and submits, data in the form is deserialized, sent to Spring MVC controller and mapped to List type object. When a user checks two or more checkboxes, it works fine. but for just one box, it doesn't.
When a user checks two or more, the data is deserialized like below.
{"users":["137","138"]}
However, when a user checks just one checkbox, it is like
{"users":"138"}
and 400 bad request error is returned.
Is there any workaround or solution for this?
The jQuery codes are:
$(document).ready(function() {
$('#groupusers').submit(function() {
var users = $(this).serializeObject();
$.postJSON("${context}/admin/groups/${group.seq}/users", users, function(result) {
...
});
return false;
});
And the form is:
<form id="groupusers" method="post" accept-charset="UTF-8" action="/" class="edit_group">
...
<div id="users">
<c:forEach var="user" items="${users}">
<label><input id="users" name="users" type="checkbox" value="${user.seq}" /> ${user.firstName} ${user.lastName}</label><br>
</c:forEach>
</div>
</form>
List object mapped to the form data:
public class AssignedUsers {
private List<Long> users;
...
}
Thanks in advance.
What is the implementation of the serializeObject() function? You might need to modify that to always return an array, so even if you only checked one box, the object should be: {"users":["138"]}
The server returned a 400 probably because the Jackson at threw a parsing exception at the backend.
Fojas' jQuery Serialize
This is the solution I have found and since been using which does excatly what you are requesting.
Example
HTML
<form id="myForm">
<input name="data[]" value="some data"/>
<input name="data[]" value="more data"/>
<input name="users[]" value="137"/>
</form>
jQuery
$('#myForm').serializeObject();
Output
{
data: ["some data", "more data"]
users: [137]
}

When submitting a GET form, the query string is removed from the action URL

Consider this form:
<form action="http://www.blabla.com?a=1&b=2" method="GET">
<input type="hidden" name="c" value="3" />
</form>
When submitting this GET form, the parameters a and b are disappearing.
Is there a reason for that?
Is there a way of avoiding this behaviour?
Isn't that what hidden parameters are for to start with...?
<form action="http://www.example.com" method="GET">
<input type="hidden" name="a" value="1" />
<input type="hidden" name="b" value="2" />
<input type="hidden" name="c" value="3" />
<input type="submit" />
</form>
I wouldn't count on any browser retaining any existing query string in the action URL.
As the specifications (RFC1866, page 46; HTML 4.x section 17.13.3) state:
If the method is "get" and the action is an HTTP URI, the user agent takes the value of action, appends a `?' to it, then appends the form data set, encoded using the "application/x-www-form-urlencoded" content type.
Maybe one could percent-encode the action-URL to embed the question mark and the parameters, and then cross one's fingers to hope all browsers would leave that URL as it (and validate that the server understands it too). But I'd never rely on that.
By the way: it's not different for non-hidden form fields. For POST the action URL could hold a query string though.
In HTML5, this is per-spec behaviour.
See Association of controls and forms - Form submission algorithm.
Look at "4.10.22.3 Form submission algorithm", step 17. In the case of a GET form to an http/s URI with a query string:
Let destination be a new URL that is equal to the action except that
its <query> component is replaced by query (adding a U+003F QUESTION
MARK character (?) if appropriate).
So, your browser will trash the existing "?..." part of your URI and replace it with a new one based on your form.
In HTML 4.01, the spec produces invalid URIs - most browsers didn't actually do this though...
See Forms - Processing form data, step four - the URI will have a ? appended, even if it already contains one.
What you can do is using a simple foreach on the table containing the GET information. For example in PHP :
foreach ($_GET as $key => $value) {
$key = htmlspecialchars($key);
$value = htmlspecialchars($value);
echo "<input type='hidden' name='$key' value='$value'/>";
}
As the GET values are coming from the user, we should escape them before printing on screen.
You should include the two items (a and b) as hidden input elements as well as C.
I had a very similar problem where for the form action, I had something like:
<form action="http://www.example.com/?q=content/something" method="GET">
<input type="submit" value="Go away..." />
</form>
The button would get the user to the site, but the query info disappeared so the user landed on the home page rather than the desired content page. The solution in my case was to find out how to code the URL without the query that would get the user to the desired page. In this case my target was a Drupal site, so as it turned out /content/something also worked. I also could have used a node number (i.e. /node/123).
If you need workaround, as this form can be placed in 3rd party systems, you can use Apache mod_rewrite like this:
RewriteRule ^dummy.link$ index.php?a=1&b=2 [QSA,L]
then your new form will look like this:
<form ... action="http:/www.blabla.com/dummy.link" method="GET">
<input type="hidden" name="c" value="3" />
</form>
and Apache will append 3rd parameter to query
When the original query has array, for php:
foreach (explode("\n", http_build_query($query, '', "\n")) as $keyValue) {
[$key, $value] = explode('=', $keyValue, 2);
$key = htmlspecialchars(urldecode($key), ENT_COMPAT | ENT_HTML5);
$value = htmlspecialchars(urldecode($value), ENT_COMPAT | ENT_HTML5);
echo '<input type="hidden" name="' . $key . '" value="' . $value . '"' . "/>\n";
}
To answer your first question yes the browser does that and the reason is
that the browser does not care about existing parameters in the action URL
so it removes them completely
and to prevent this from happening use this JavaScript function that I wrote
using jQuery in:
function addQueryStringAsHidden(form){
if (form.attr("action") === undefined){
throw "form does not have action attribute"
}
let url = form.attr("action");
if (url.includes("?") === false) return false;
let index = url.indexOf("?");
let action = url.slice(0, index)
let params = url.slice(index);
url = new URLSearchParams(params);
for (param of url.keys()){
let paramValue = url.get(param);
let attrObject = {"type":"hidden", "name":param, "value":paramValue};
let hidden = $("<input>").attr(attrObject);
form.append(hidden);
}
form.attr("action", action)
}
My observation
when method is GET and form is submitted, hidden input element was sent as query parmater. Old params in action url were wiped out. So basically in this case, form data is replacing query string in action url
When method is POST, and form is submitted, Query parameters in action url were intact (req.query) and input element data was sent as form data (req.body)
So short story long, if you want to pass query params as well as form data, use method attribute as "POST"
This is in response to the above post by Efx:
If the URL already contains the var you want to change, then it is added yet again as a hidden field.
Here is a modification of that code as to prevent duplicating vars in the URL:
foreach ($_GET as $key => $value) {
if ($key != "my_key") {
echo("<input type='hidden' name='$key' value='$value'/>");
}
}
Your construction is illegal. You cannot include parameters in the action value of a form. What happens if you try this is going to depend on quirks of the browser. I wouldn't be surprised if it worked with one browser and not another. Even if it appeared to work, I would not rely on it, because the next version of the browser might change the behavior.
"But lets say I have parameters in query string and in hidden inputs, what can I do?" What you can do is fix the error. Not to be snide, but this is a little like asking, "But lets say my URL uses percent signs instead of slashes, what can I do?" The only possible answer is, you can fix the URL.
I usually write something like this:
foreach($_GET as $key=>$content){
echo "<input type='hidden' name='$key' value='$content'/>";
}
This is working, but don't forget to sanitize your inputs against XSS attacks!
<form ... action="http:/www.blabla.com?a=1&b=2" method ="POST">
<input type="hidden" name="c" value="3" />
</form>
change the request method to' POST' instead of 'GET'.