2

I want to create a HTML page which offers a button (link, some other clickable element, etc.) which, when pressed, sends a specific constant POST request to a specific constant server. The value I need to post is a specific constant JSON-encoded value ({"key":"value"}), so for HTTP it is just a very short constant string.

The value and the URL I have to use are constant. In order to make something happen, I have to send exactly this constant POST request. There is no need to parameterize this request or to "set a value" or similar. Also, I have no parameter name or similar. I must not send a parameter list with a parameter whose value is the JSON-encoded value, but I must send the JSON-encoded value by itself. The complete POST request can look like this:

POST /post/path/to/action HTTP/1.1
Host: the.specific.server
Content-Type: application/x-www-form-urlencoded
Content-Length: 15

{"key":"value"}

(NOT parameter={"key":"value"} or similar as body!)

The server is not under my authority but a service I want to use.

With pure shell means I can do this very simply using curl:

curl http://the.specific.server/post/path/to/action -d '{"key":"value"}'

I imagined something like

<button url="http://the.specific.server/post/path/to/action"
        value="{%22key%22:%22value%22}">visible text</button>

but I found nothing appropriate.

Based on questions like this or this or this I tried various approaches like this one:

<form method="POST" action="http://the.specific.server/post/path/to/action">
  <input type="text" id="key" key="value">value</input>
  <button type="submit" value="{%22key%22:%22value%22}">visible text</button>
</form>

With or without the input field, the button, with other arguments, other values, etc. but nothing finally sent anything useful to the server when pressed. At best I got something which was also transmitting a parameter name (thus the payload was not just the Json-encoded value).

I guess I'm just missing something basic in this :-}

Community
  • 1
  • 1
Alfe
  • 56,346
  • 20
  • 107
  • 159
  • There is no `url` property on the HTMLButtonElement and your question is a bit unclear : how do you set the value ? How do you want to pass your values ? What do you use to retrieve those on server? In order to send `` as POST to your server, you have to give them name, so here nothing is sent. Also there is no `key` attribute on the `HTMLInputElement`. What about a few readings on [how to POST from a webpage to a server](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Forms/Sending_and_retrieving_form_data)? – Kaiido Oct 05 '15 at 01:05
  • The server is not under my authority. In order to make something happen, I have to send exactly this constant POST request, that's it. It is not further parameterized, so there is no need to "set a value". I repeated these aspects in my question to make this further clear. – Alfe Oct 05 '15 at 06:11
  • But here you are not sending anything to the server ... – Kaiido Oct 05 '15 at 06:23
  • Yah, maybe so. I'm no so skilled in web programming. But I *want* to send a POST request to the server. How can I do this? My trials did not succeed, as I wrote. Btw, *I* am talking about `the.specific.server` when I mention the server. I do not want to communicate with the server the HTML page was coming from. Actually, in my case that is a local file accessed via `file://`. – Alfe Oct 05 '15 at 12:09
  • Guessing that you get the JSON value through js, you could set an hidden input with JSON content : `var jsonString = "{%22key%22:%22value%22}"; var obj = JSON.parse(decodeURIComponent(jsonString)); var hid = document.querySelector('input[type="hidden"]'); hid.name = Object.keys(obj)[0]; hid.value = obj[hid.name];` and in HTML
    – Kaiido Oct 06 '15 at 04:43
  • The Json content is constant. I repeat that as often as you like ;-) That means I get it not at runtime through a software, not through JS, but at coding time from reading my spec which states that I have to send exactly *this* constant Json value. And I have to send it as Json, so I don't see the point in parsing it. I think it's best to forget that it is Json. Let's just call it an arbitrary *constant* string (which just happens to be a Json-encoded value). – Alfe Oct 06 '15 at 13:03
  • then just add a `
    ` But still, a simple google search or some readings of the links I gave you first would answer this as well.
    – Kaiido Oct 08 '15 at 01:27
  • That would not POST the pure Json-encoded value but a parameter list with one parameter whose value is the Json-encoded value. – Alfe Oct 08 '15 at 09:20
  • Thank you for your comments, @Kaiido, I think it showed me how to improve my question with clarifications. I set up a bounty because I think this question drew to little attention. – Alfe Oct 08 '15 at 09:22

5 Answers5

4

There is no way in HTML to generate JSON from forms. You need here to implement this using an AJAX request.

Using jQuery it could be something like that:

$.ajax({
  type: 'POST',
  url: 'http://the.specific.server/post/path/to/action',
  data: '{"key":"value"}',
  success: function() {
    // Successful response received here
  },
  dataType: 'json',
  contentType : 'application/json'
});

This will be trigger when clicking on a button or a link, as described below:

$('#myButtonId').click(function() {
  $.ajax({
    (...)
  });
});

This can be put for example in a script in your page after including jQuery library, as described below:

<html>
  <head>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
    <script type="text/javascript">
      // Waiting for the DOM to be loaded
      $(document).ready(function() {
        $('#myButtonId').click(function() {
          // When button is clicked
          $.ajax({
            (...)
          });
        });
      });
    </script>
    <body>
      <button id="myButtonId">CLICK ME</button>
    </body>
  </head>

Edited

Here is the way to send an HTTP request using raw JavaScript API: http://www.quirksmode.org/js/xmlhttp.html.

I adapted this code to work for your use case:

function sendRequest(url, callback, postData, contentType) {
    var req = createXMLHTTPObject();
    if (!req) return;
    var method = (postData) ? "POST" : "GET";
    req.open(method,url,true);
    req.setRequestHeader('User-Agent','XMLHTTP/1.0');
    if (postData) {
        if (contentType) {
            req.setRequestHeader('Content-type', contentType);
        } else {
            req.setRequestHeader('Content-type',
                  'application/x-www-form-urlencoded');
        }
    }
    req.onreadystatechange = function () {
        if (req.readyState != 4) return;
        if (req.status != 200 && req.status != 304) {
            return;
        }
        callback(req);
    }
    if (req.readyState == 4) return;
    req.send(postData);
}

var XMLHttpFactories = [
    function () {return new XMLHttpRequest()},
    function () {return new ActiveXObject("Msxml2.XMLHTTP")},
    function () {return new ActiveXObject("Msxml3.XMLHTTP")},
    function () {return new ActiveXObject("Microsoft.XMLHTTP")}
];

function createXMLHTTPObject() {
    var xmlhttp = false;
    for (var i=0;i<XMLHttpFactories.length;i++) {
        try {
            xmlhttp = XMLHttpFactories[i]();
        } catch (e) {
            continue;
        }
        break;
    }
    return xmlhttp;
}

To execute your request, simply use the function sendRequest:

sendRequest(
  'http://the.specific.server/post/path/to/action',
  function() {
    // called when the response is received from server
  },
  '{"key":"value"}',
  'application/json');

Hope it helps you, Thierry

Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • Coming from a pure HTML point of view, where do I put that code? Inside a ` – Alfe Oct 08 '15 at 09:36
  • Btw, as it is *constant*, I have no need to *generate* the JSON (I think I wrote that a hundred times by now). I just want to POST a constant string (which happens to be a JSON-encoded value), and not as part of a parameter list. – Alfe Oct 08 '15 at 09:40
  • Thank you, that comes closer to what I want. I feel that importing an external library like that jQuery stuff might be overkill for my simple task (then I would prefer the CGI solution which I also dislike). My main objection here is that I might not have Internet access and so probably would not be able to use this solution, am I right? – Alfe Oct 08 '15 at 09:46
  • The problem is that you can't generate JSON only from an HTML form even for constant fields. When submitting a form with HTML-only support, the content will be encoded using `application/x-www-form-urlencoded ` or `multipart/form-data ` but not `application/json`. See the specification for more details: http://www.w3.org/TR/html401/interact/forms.html#form-content-type. – Thierry Templier Oct 08 '15 at 09:49
  • You can download the library and put it next to your HTML file. Sure you could use the raw XHR API of your browser but it can be browser-dependent ;-) and using the jQuery support is much easier to use. CGI is a server-side approach. We tackle here the client side within the browser... – Thierry Templier Oct 08 '15 at 09:51
  • I updated my answer with a solution without jQuery and using raw API from browsers (and cross browsers). – Thierry Templier Oct 09 '15 at 16:07
3

A simple, customisable an no dependencies solution based on : https://gist.github.com/Xeoncross/7663273
May works on IE 5.5+, Firefox, Opera, Chrome, Safari.

<html>
    <body>
          <button id="myButtonId" onclick='post("http://the.specific.server/post/path/to/action", "{\"key\":\"value\"}");'>CLICK ME</button>
    </body>

    <script>
        function post(url, data, callback) {
            try {
                var req = new(this.XMLHttpRequest || ActiveXObject)('MSXML2.XMLHTTP.3.0');
                req.open('POST', url, 1);
                req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
                req.send(data)
            } catch (e) {
                window.console && console.log(e);
            }       
        }
    </script>
</html>
aprovent
  • 941
  • 6
  • 20
  • I will try that soon and hope it works! (For me, in my environment etc.) Btw, working on an Android browser would be perfect as this is meant to send simulated remote control key presses to my tv set, and that would make most sense from a mobile device. – Alfe Oct 09 '15 at 15:54
  • You should replace `application/x-www-form-urlencoded` by `application/json` in the code above since you actually send JSON content ;-) – Thierry Templier Oct 09 '15 at 16:08
  • You are right. But i heard that "application/json" give sometime random behaviors and that some other people used "text/plain". So I do not know what to think :-) – aprovent Oct 09 '15 at 16:22
  • 1
    wow... that sounds a little bit crazy. we can't build a viable world wide web with such rules. – Thierry Boileau Oct 09 '15 at 16:48
  • Really strange, indeed ;-) That's why I prefer not to use directly low-level API for AJAX request and leave more high-level API / libraries handle such weird browser-specific behaviors! What I would say is, if you send JSON content, you should use content type `application/json`... – Thierry Templier Oct 09 '15 at 18:48
2

You are looking for FORM encoding algorithm which enables form data to be transmitted as json.

Have a look at W3C HTML JSON form submission. It is not active and not likely to be maintained.

So, you are better off using the above JS or Jquery solution or use a server side forwarding. My suggestion is to use jquery as most websites point to google cdn these days and jquery is mostly browser cached. With below code, you neatly fire a POST request without worrying about underlying browser variants.

$.ajax({
  type: 'POST',
  url: 'http://the.specific.server/post/path/to/action',
  data: '{"key":"value"}',
  success: function() {
    // Successful response received here
  },
  dataType: 'json',
  contentType : 'application/json'
});
Faiz Mohamed Haneef
  • 3,418
  • 4
  • 31
  • 41
0

Try this suggestion using JQuery methods and Ajax:

$(document).ready(function(){
    $("#myForm").submit(function(){
        $.ajax({type:"POST", 
                data: $(this).serializeObject(),
                url:"http://the.specific.server/post/path/to/action",
                contentType: "application/json; charset=UTF-8",
            success: function(data){
                // ... OK
            },
            error: function(){
                // ... An error occured
            }
        });
        return false;
    });
});

Note : serializeObject method converts form elements to a JSON string.

André Blaszczyk
  • 750
  • 4
  • 17
0

I now went for a simplistic solution (because that's what I wanted) I found myself by searching for more answers. It seems there is no way around using JS for this task.

<button onClick="postCommand('mypath', 'mykey', 'myvalue')">Click</button>
<script>
  function postCommand(path, key, value) {
    var client = new XMLHttpRequest();
    var url = "http://the.specific.server/" + path;
    client.open("POST", url, true);
    client.send("{\"" + key + "\":\"" + value + "\"}");
  }
</script>

This is in general @aprovent's answer, so I accepted his and granted him the bounty.

Alfe
  • 56,346
  • 20
  • 107
  • 159