Last week I was asked to make some tools that talked to a Rails app. Let say you have a Rails app that has a scaffold name Product and resides on
www.your_app.com . If you want to create a new Product, you go to
www.your_app.com/products/new, fill in the form in there, including typing in some information product name, choosing a photo to upload and finally hit Create. A new Product will be created. Now how do automate it? I mean, to accomplish the above task without going to the web, fill out the form, select a file to upload and hit Create. Instead, you run some script and voila`, a new Product is created. It sounds confusing at first.
Interestingly, all the user just does is to make some HTTP request, specifically, GET and POST here. So you want you want to do is to write a script that make HTTP request, taking all the information that need to be filled up in the form as parameters, including the photo to be uploaded.
First Try: Use Java. I tried to write some script using Java. A quick research gives me some options: Either use Java.net or Apache HTTPClient. The second one is better. This is a very easy-to-use library to deal with HTTP. So;I have an html form that looks something like this:
<input id="product_name" name="product[name]" size="30" type="text"/>
<input id="product_picture" name="product[picture]" size="30" type="file"/>
<div class="actions"></code><input name="submit" value="Create" size="30" type="submit"/></div>
String fileName = "example.img"
HttpHost host = new HttpHost("your_app.com", 80, "http");
HttpPost httpPost = new HttpPost("/products");
<span class="typ">MultipartEntity</span><span class="pln"> entity </span><span class="pun">=</span><span class="kwd">new </span><span class="typ">MultipartEntity</span><span class="pun">();
<span class="typ">FileBody</span><span class="pln"> bin </span>=<span class="kwd">new </span><span class="typ">FileBody</span>(<span class="kwd">new</span><span class="typ">File</span>(<span class="pln">fileName</span>));
</span>entity.addPart("product[name]", "Product1");entity.addPart("product[picture]", bin);
HttpResponse postResponse = httpClient.execute(host, httpPost);
The piece of code above is pretty much self-explanatory. It first creates a host and an HttpPost object. Then it makes a; MultipartEntity which is what stores all the information that user supposes to fill in the form, including choosing an image file to upload along with the creation of a new Product. Next it assigns the entity to the HttpPost and execute the HTTP Post request;
Now the question is: Is there any other way easier to do this. Digging into stackoverflow, I see that this can be done using CURL – An unix tool that is mainly used to download stuffs on command line interface, like wget.
Second Try: Use CURL. Actually the above code can be done by just one curl command:
curl --data </code>product[name]="Product1" <code>--form </code>product[picture]=@/path/to/file.img --form submit=Create [URL]
The above line feeds in the product name, which is “Product1”, chooses a file to upload and make a HTTP Post request to upload the selected file and create a new Product. Run the the command, refresh the web interface and I see a new product get created :-). Note the path/to/file.img needs a “@” that comes right before it, otherwise the /path/to/file.imge will be interpreted as a string. More tutorials with curl can be found on its official page http://curl.haxx.se/docs/httpscripting.html
Lesson learned: Before doing anything, check if something similar is already out there, ready to be used o_O.