ruby/erb/cgi -- get method works, but post doesn't - ruby

I am trying to write a simple eruby (erb) cgi form. Everything works fine, if I use method="get". For example, the following code just dumps the cgi parameters.
<html><body>
<% require 'cgi' %>
<% cgi = CGI.new %>
<%= cgi.keys %>
<form action="/sscms/temp.rhtml" method="get">
<input type="text" name="title" value="Grover">
<input type="submit" value="save">
</form>
</body></html>
However, if I change "get" to "post", the cgi parameters are always empty. This seems to work with plain-old ruby cgi. So it appears to be an eruby/cgi problem. Everything I've seen online seems to say that get and post are treated the same by ruby. Is there something I am missing?
Thank you.

"a CGI program is called with the parameters of the request passed in either in the environment (GET) or via $stdin (POST)", you can only consume $stdin once but you can read the environment as many times as you want.

Related

How to PATCH or DELETE from a form without javascript

I am writing a simple crud app on Phoenix. How does one submit PATCH and DELETE requests from a form without using javascript?
Ah I figured it out, same as rails:
<form method="POST">
<input name="_method" type="hidden" value="patch" />
...
Handled in Plug.MethodOverride: https://github.com/elixir-lang/plug/blob/master/lib/plug/method_override.ex
<form> elements only support sending GET and POST requests. The workaround that Rails uses is to read the request method from the _method request parameter, overriding the actual request method (the GET or POST method).
Phoenix does exactly the same through Plug, the Rack-like framework that Phoenix is built on. Long story short, Plug provides middlewares and one of the middlewares it provides is Plug.MethodOverride, which does exactly what we discussed. Doing so in a middleware, the Phoenix app barely knows that the original request was not a GET/POST.
You can see Plug.MethodOverride used in Phoenix's source code.
As the others have mentioned, Phoenix handles this in the routing via the MethodOverride plug.
In order to change this in the template with the form_for helper, use the :method parameter:
<%= form_for #changeset, path(#conn, :update), [multipart: true, method: "patch"], fn f -> %>
This will add the hidden input to the HTML, as noted by #greggreg:
<input name="_method" type="hidden" value="patch" />

use javascript value in html erb

I am trying to use a JavaScript variable in an HTML erb, using <% %> tags. query[i] is something I have in loop I am trying to call:
<%= Table.update('query[i]')%>;
How can I use query[i] from JavaScript for the actual value?
You can't do this. erb runs on the server to generate the HTML, which is then sent to the client, where the Javascript runs. By the time the Javascript variable is available, erb has already executed, and we're not even on the same machine anymore!
It looks as though you want Javascript code to supply a value which is then used as an argument to a database call. You'll have to do this via a post-back; i.e., the Javascript can make an AJAX call, a new erb could generate the new HTML fragment, and then the Javascript can receive it and plug it into the page.
Here's the first link I got when I googled "erb AJAX".

Mathematica 8.0 interaction with a web server JSP using HTTP POST and XML

I have been tasked with using Mathematica to interact with a third party's web server via JSP using HTTP POST and XML. Example of what I need to send:
<html>
<head></head>
<body>
<form method="post" action="http://www. ... .com/login.jsp">
<textarea name="xml" wrap="off" cols="80" rows="30" spellcheck="false">
<loginInfo>
<param name="username" type="string">USERNAME</param>
<param name="pwd" type="string">PASSWORD</param>
</loginInfo>
</textarea>
<input type="hidden" name="Login" value="1"/>
<input type="submit" name="go" value="go" />
</form>
</body>
</html>
Example of what I will receive (XML):
<UserPluginInfo>
<PluginInfo>
<param name="pluginUid" type="string">1</param>
</PluginInfo>
<UserInfo>
<param name="username" type="string">USERNAME</param>
</UserInfo>
</UserPluginInfo>
I found a blog by Robert Raguet-Schofield written in 2009 about interacting with Twitter that uses J/Link to access Java to perform the HTTP POST and handle the response.
My question is, is this the best method to accomplish my task or has Mathematica evolved since 2009 and there is a better way (more straight forward) to accomplish my task?
Whilst this may not be a better way, an alternative approach to circumvent the need of J/Link would be to set up an intermediate CGI script to translate the request from GET to POST for you.
This script file would sit on an accessible server, it would take the specified GET query, make a POST request on the target page, then output/return the result XML in the normal way.
For example, using curl in PHP that would work well - although obviously it would be possible to achieve the same functionality in pretty much any CGI language.
<?php
$c = curl_init();
// set the various options, Url, POST,etc
curl_setopt($c, CURLOPT_URL, "http://www. ... .com/login.jsp"); // Target page
curl_setopt($c, CURLOPT_HEADER, false);
curl_setopt($c, CURLOPT_POST, true);
curl_setopt($c, CURLOPT_RETURNTRANSFER, false);
// POST the incomming query to the Target Page
curl_setopt($c, CURLOPT_POSTFIELDS, $_SERVER['QUERY_STRING']);
curl_exec($c);
curl_close($c);
// Output the XML response using header/echo/etc...
// You might need to also send some of the POST request response headers
// use CURLOPT_HEADER to access these...
?>
From the Mathmatica stand point this is much simpler as you simply use the built in import method to make a standard GET request on the proxy page but get the result XML from a POST request on the login page.

Sending a DELETE request from Sinatra

I am trying to develop a RESTful Sinatra application. Now, I know how to respond to a delete request with something like
delete '/user/:id' do |id|
#do something in the model
end
What I am interested in is how do I get to execute that method. I can't have link that does a DELETE instead of a GET, can I?
The only solution I found so far is sending a DELETE request via jQuery: How to send a PUT/DELETE request in jQuery?
I tried looking into different RESTful Sinatra projects on github but my Ruby knowledge is probably to limited to get how they are doing it.
Put following line in your code.
use Rack::MethodOverride
It will help you interpret post methods with parameter "_method" with value "delete" as put.
Then you can write
delete '/user/:id' do |id|
I thinks it's like the Rails way. You need define a params '_method' with 'delete' value and add it on your form.
When you POST you form with this particular params, you do a DELETE request in sinatra.
Like :
<form action="/search" method="post">
<div style="margin:0;padding:0">
<input name="_method" type="hidden" value="delete" />
</div>
</form>
It's the same with PUT method
Another way is to use Curl:
curl -X DELETE http://host/user/1
%form{:action => "/note/delete/#{#note.id}", :method => "post"}
%input{:type => 'submit', :name=> "_method", :value => 'delete', :class => 'button'}
You can also trigger the delete route with a button like so
see also Call Sinatra delete route with jQuery for how to do this with jQuery and JSON at the front end and Sinatra on the back end.

Codeigniter: Pass form variable into URI

Not sure if this can be done but it seems my main issue is because i have a default route to a method called "index." I want to be able to list all users tagged with a specific keyword. In addition, users can search for other users based on these keywords.
i.e.
www.domain.com/tags/apples
www.domain.com/tags/oranges
www.domain.com/tags/blueberry
It works fine if I go to the URL manually. I'm having issues getting it to work with a form field.
Snippet of the form_open:
<?=form_open('tags/');?>
<p>Search for Tag: <input type="text" name="tag" /></p>
<p><input type="submit" value="Search" /></p>
Here's a snippet of my controller:
function index() {
$data['result'] = $this->tags_model->searchByTag($this->uri->segment(2));
$this->load->view('tags_view', $data);
}
Here's a snippet of my router:
$route['tags'] = "tags/index";
$route['tags/(:any)'] = "tags/index/$1";
Now, I can easily fix all this if I have a method called search, but I don't want the URL to show up as www.domain.com/tags/search/orange.
When you create your form you set it to use POST variables instead of GET, that way they don't go through the url, that's codeigniter's default method for forms.
So your form_open code will generate the following code:
<form method="post" action="tags/" />
If you want them to got through url though, call the form opener this way instead:
form_open('tags/', array('method' => 'get'));
The same applies to any other attributes you want to specify for the form, just follow the same pattern attribute_name => attribute_value inside the array.
More info on the user guide
The problem here is that your form will be submitting all it's data to "/tags", with nothing trailing it, as POST data doesn't come in as part of the URL. Even if it was a GET request however, I don't think that CodeIgniter will take anything out of the querystring and use it as part of the routing segments.
I think what you should do is have a small Javascript function that automatically updates the form action parameter to be tags/<select option value> whenever the select value is changed. This way it will submit to the right place. In order to handle non-javascript enabled browsers, you could have a default action called tags/search that would simply analyze your form data and put out a 301 redirect to the proper tags/<location> once you'd figured it out.
It seems like a bit of overkill here however, as you could really point the form at tags/index and not worry about it. I'm not sure search engines index form submission locations, and even if they did, they certainly wouldn't index a form that submits to dynamic URIs in the way that you want it to. You could still link to the search result pages using tags/apples, etc, but the form could work quite normally just by going to tags/index.
I ended up redirecting the URL and passed the keyword into the URI.
i.e. domain.com/tags/view/

Resources