Feature Request: Allow Functions to be Called with GET

We teach kids how to use the Spark to make Internet controlled robots. It’s a lot of fun, and they make great things!

I have a feature request that would make it a lot easier for kids (and adults) to learn to use the Spark: allow functions to be called with GET as well as POST.

A major principle of our teaching is to “get to the awesome” as soon as possible. Allowing functions to be called with GET would allow us to do this much quicker.

The “Hello World” first example could be triggered with a URL entered into their browser. We wouldn’t have to install and explain curl.

The next step after is easier, too. Making a basic web interface would be as simple as adding a link with a URL, with a target of an iFrame that doubles as a status window. No forms, no jquery, no javascript required.

I hope you can work this into a future release!

Thanks,
Andy

I could be mistaken, but I don't believe this is going to happen. The main reason is the fact that it goes completely against the whole idea behind the REST API/HTML conventions. It's there to separate the most basic functionalities into easy to understand, logical commands. Doing it the way you suggest is completely counter-intuitive.
Let's say you'd like to send someone a letter (those old school paper things). I have a feeling you'd POST the letter, rather than GET the letter. POST is there to send info, GET there to, well, get info.

That said, I completely understand your arguments, and agree with you that it would be easier. It would however not be better. And if you're starting off by teaching kids to use hacks, rather than proper coding, you'll eventually run into problems (or rather, they will).
I still consider myself a "kid" at 19 without a lot of programming experience, and have to say I never got the whole CURL thing working. I've tried, it gave me some errors, and I rage-quit. That's not to say I quit working with the Spark. I found it to be a good lesson to get the stuff working with JavaScript, since that's what half of the web is running on, as well as all things Node.js. Since this is an IoT device, I'd like to read out my stuff over the web, meaning a web page. Personally I'd rather struggle for 5 days straight to get it working with "good" code, than to hack it together just to have something working. "Bad habits die hard" is a real pain when it comes to programming.

Back to the

That can still be true, while using the proper techniques. I personally wouldn't bother with explaining all the URL calling stuff either, depending on how much time you have. Why not make a universal interface in which the account owner could log in, which exposes all functions/variables? This will allow you to do pretty much anything, without having to mess with the web code (yet). Some people already made something like this, and were kind enough to share it. I've personally used this one a lot, and still do:

I gave it a shot as well, mainly for trying the SparkJS library.
When you progress through the course, you could slowly start to introduce the principles behind this, and start working towards web code. This way, the kids will still be able to program their code, without having to worry about the web side of things, while making sure that they're not starting some bad habits.


This is not, in any way, meant as criticism. I'm merely trying to explain why I wouldn't do it that way, and provide alternatives.

I hope some of this was useful, but feel free to ask for help/clarification if you require any.

Thanks for the reply, you certainly made me think about this in more detail!

I totally agree that it is important to teach good coding habits. However, the decision to use GET vs POST is not as clear cut as whether you are sending or retrieving data.

Using GET to send the server some parameters and generate is response is not a hack, modern web sites do this all the time. For example, the URL of the page that you are looking at right now does exactly what I am proposing! It's a GET request with parameters embedded into the URL to tell the server what forum post to dynamically generate and display. I simply want to be able to do this with the Spark API - specify some parameters in the URL and have the API do its work and return some information.

There are certainly reasons you would want to choose POST over GET and vice versa. As a web developer, I am used to making that choice myself rather than having it imposed on me by the architecture. In this case, I would like to choose GET for ease of use. I don't think the differences of POST make it the right option to use in this case.

According to the "undoubtedly always true, no questions asked" wikipedia, it sort of is:

Requests using GET should only retrieve data and should have no other effect.

Considering the naming of the HTML verbs, this seems to make perfect sense. GET requests can pass parameters to let the server know what to look for. POST requests tell the server to do stuff with their content. If using either, you should be able to safely assume they do what they're meant to do. If we're mingling verbs anyhow, why not just use DELETE to request variables, and PUT to call functions. It's all a server side implementation, and can be easily changed indeed. The reason that hasn't happened yet, and likely wont, is probably because they like to stick to the standard.

I personally feel like it just doesn't make sense to use GET for anything other than getting stuff. The name implies the function, and if your trying to make it POST data, you're no longer GETting stuff. That would be the main reason for not using GET for functions in my opinion; it feels wrong. It rather spend the extra effort to do it right the first time, than have it bite me in the back later on.

In case of teaching the kids, I feel its even more important to get it right the first time. They're going to be like:"wow, if I open this URL, this and this happens, which is freakin' awesome". Then they'll move on, and some time passes, and they try to use a different API which is strict with their verbs. And then they're going to be disappointed since the stuff they always assumed to work, now suddenly doesn't any more.

I'm not saying you can't use GET instead of POST, I'm saying I probably wouldn't since I'd regret it later on. The relative easy of use doesn't weigh up to the "this isn't right" feeling. It's not that hard to make an Ajax, Javascript, JQuery, forms request which complies with the standard. The architecture is there for a reason, why not use it? There are too many better alternatives available to simply neglect the standard.

If it's just for an introductory course, then the students probably won't mind using one of the previously mentioned pages to use the functionalities. If it goes deeper than that, then it's perhaps best to explain to them why you'd rather use a POST over a GET.

You could still do that, but then do an onClick="callFunction()", to request the relevant function. This is pretty much all it takes to POST, so it shouldn't be that hard:

$.ajax({
    type: "POST",
    url: url,
    data: {
    	access_token: accessToken,
	args: data
    },
    dataType: "json"
})

Is avoiding the above worth messing with the standards used globally?
If you're set on doing so anyway, there is always the Local Cloud, with which you can do whatever you deem necessary. I just have a feeling that your proposed functionality won't be added. Although I've contemplated it as well, I think that's a good thing, since I wouldn't want them promoting potentially dysfunctional habits.

I do agree with @Moors7 here.
The thing that should guide the decision if to POST or GET should be the focus of your action - what are you actually interested in

While this is true

That's usually not what you care for. As a user who doesn't know or care that the server will be running some functions in the background I'd only want to GET the info I asked for.
On the other hand, if my main focus is to trigger some specific action on the server I'll only POST it some info to instruct the server to do something. Sure I'll get some return code of a Spark.function but that is usually not my main concern - it's the remote action I care for.

1 Like

Compare it with an old school file cabinet (those with paper in them).
When someone asks you for a file, they’re likely to say:“Could you GET me this/that file from this/that cabinet?”. They’re asking you to retrieve data, and pass you the information necessary to be able to find that data. They’re not expecting you to clean up the cabinet, relocate it, light a bonfire, summon twelve demons, and celebrate Christmas. They’re merely asking you to retrieve some data, and will expect nothing more.
When someone asks you to create a new document, and add it to the cabinet, you’re going to take the document, and POST it in there. You’re inputting data. They don’t expect you to come back with 20 extra documents, since that’s not what they asked for. They expected you to post the document in the cabinet, and move on with your life, no questions asked. To do this, they’ll also have to provide you with some location parameters, so you’ll know which cabinet to post in.
Now, when someone asks you, “hey I’ve got this document, but I’m not sure if there is already a version in there, would you mind PUTting it in there for me?”. They’ll assume this is what’s going to happen: they expect you to take their document, go to the cabinet they told you, and PUT the document in there. If there already exists a version of the document, they’ll expect you to remove the old one, and replace it with the new version. If no version already exists, they’ll expect you to create a new folder and PUT it in there.
When someone asks you:“I’m done with this project, would you mind clearing out the relevant documents?”, they’ll expect the following: you go to the assigned cabinet, open the drawer, find the relevant documents, and stuff them through a shredder, effectively DELETEing them. Again, this doesn’t include doing a rain dance, worshipping satan, solving world hunger, of practicing black magic. Rather, they’ll expect the assigned documents to be deleted, nothing more, nothing less.

Anyone who has ever worked with computers will know one thing for certain: those things are dumb as hell. They’re also very loyal, and will trust you on your word. They won’t do anything unless you tell them to do so. The problem lies in the fact that we told to computer the story above. So when you tell them to go and GET something, they will get you something. And that’s where it ends. They won’t go investigate black matter, or cure malaria at the same time. They get you your data, and they’re done. Just like I wouldn’t expect you to do the crazy things above, it isn’t fair to request that from a computer who doesn’t know any better.
We humans have intelligence, we can figure stuff out. If we get to a cabinet with a lock on it, we could figure out to break the lock by shooting it. A computer will act like a sad panda, abandon all hope, and give up, since nobody told him what to do with a lock. Heck, it doesn’t even know what a lock is. We could of course tell him what it is, and how to handle it, but that doesn’t always make sense. That’s exactly the case with the issues above. Why would you reasonably expect a computer to DELETE data, when you asked him to GET data. That’s starting to sound a bit like skynet if you ask me. It’s just not what they’re supposed to do. Although it may be convenient at times, it will become highly unpractical once they start doing stuff on their own, and it turns out we hadn’t configured them properly.
Imagine you were a kid, and your mother asked you to get the cookie jar. Now, instead of merely retrieving it, you also ate half of the cookies, then you can bet on it you’ll be in trouble. Because that’s not what you were asked to do. That’s not what you were supposed to do. Rather, you did something you thought was convenient at the time, but ending up hurting you more than it should have in the end, making you regret your decisions.

Enough with the analogies, I think I’ve made my point :stuck_out_tongue: I hope it makes sense, somehow.
Like I’ve said, the local cloud will allow you to do pretty much anything you want, so you can (mis)use it any which way you see fit. Looking forward to hear what your course of action will be!

Wow, lots of passion about the original intention of the low level methods of the HTTP protocol! Thanks for your responses, this is worth discussion.

I understand your argument that GET was originally intended to retrieve data from the server, and POST was originally intended to send data to the server for processing and storage. It is certainly a good practice in the web development world to use POST when you are sending data to the server for processing and storage. The browser behaves differently, and helps protect against things like pressing the reload button and resubmitting data.

I think you are taking a logical leap from there that is incorrect. You are saying that the decision to use GET vs POST should be solely based on whether you are sending data to the server or not.

First of all, you are always sending data to the server with every request! The URL, header information about your browser, the previous page you came from, cookies, etc.

The decision to use POST or GET should instead be based on what the server is going to do with that data being submitted. That is a decision that the programmer should make, not have imposed on them by the server architecture.

To allow this decision to be made by the programmer, the HTML specification for FORM, an element designed to collect information from the user and send it to the server specifically allows both GET and POST methods.

So I am simply asking to be able to make that decision by allowing functions to be processed from GET requests.

I do not think it is a good practice for the server architecture to impose POST for processing of functions. Restrictive environments trying to enforce good coding practices are all well and good, but not when they block legitimate use cases. This very page you are looking at now was generated from a GET request, and undoubtedly had multiple function calls processed on the server.

If you still disagree with me, I challenge you to find a single widely used application server architecture that only allows functions to be processed from HTTP POST requests.

How about setting up a PHP script that converts the kids Get request into a Post using curl?

kids point their Get request to your server and your server takes the request and sends it as a post to the spark server…

Really good suggestion Hootie!

That's what I'll do if Spark has no plans to implement this. Just adds another step that's different than the Spark documentation, so introduces potential confusion. I really hope they make this change!

Actually no. It shouldn't be based on what the server should do but what you expect of it. Do you first of all expect to get something back of it or do you just expect it to read your posted letter and act accordingly. Sure there is always a server who has to do something, but I believe the GET/POST decission should be based on the viewpoint of the initiator of the action.

I'd rather see the server as a servant/slave without say - only the initiators perspective is important :wink:

And as for this

Yes this might be true, but when we asked for this page, we (the initiator of the request) expected to GET it back and no one would actually care through what hoops and loops the server had to jump, to give us back what we wanted.

As an application programmer I also had to learn, that the programmers point of view is not always what the customer needs or even wants to understand. They pay so they say - we can only suggest.

1 Like

Regardless of what’s going to happen, or what may or may not be correct, it’ll come down to one crucial thing: are you, or are you not going to explain to the kids what happens when they press the button? I can say you should use POST, and you’ll make a point for GET, but does it really matter when they don’t know what’s going on. There are two options I can see:
You explain what happens:
You’re going to tell them that for in order to make something happen, some data will have to be sent to a server. To do that, you’ll make use of HTML conventions, which you’ll hopefully also explain. Now if you’ve got some know-it-alls, they’re going to ask you:“well, since you tell us everything can be done with GET, why even bother with POST and the others?” (which I’d like to see an answer to as well). If you’re explaining that in-depth enough that they understand the functionality, you might as well go for POST, since it won’t be that illogical any more.
You don’t explain what happens:
You’re going to tell them that for in order to make something happen, they’ll need this magically formatted HTML thingy which will tell the server what to do. If you’re telling them:“use this and this URL and edit these parameters”, you might as well tell them:“use this and this code and edit these parameters” Since you’re not explaining what’s happening anyhow, they won’t care whether you’re using POST or GET, as long as it gets the job done.

Result: either you explain the inner workings, and they’ll understand the reasoning behind POST, or they don’t understand, and it won’t matter whether or not you use POST or GET, in which case you might as well let 'em use POST.

Assuming you’re letting them build a web interface, in which a lot of interactivity is based on JavaScript, why not that for making the requests? Using a PHP to convert the requests will still require you to explain what’s going on.

Here’s some recommended reading, particularly the sections on idempotent versus nullpotent methods.

The notion of “calling a function” is not super useful here since nullpotent methods like GET can return derived results that may have to be computed. The useful distinction here is the nullpotent methods cannot have side effects and calling them multiple times does not change any state.

1 Like

Thanks bko, that is indeed very good reading. (Your tutorials have also been very good reading, by the way! Used them a lot when I was getting started.) A key constraint of a RESTful API is that a GET request should not change a resource on the server.

So here's a question: Is Spark giving us developers a framework for designing a RESTful API, or is Spark a RESTful API itself?

Most people would say the latter, Spark is a RESTful API. I here's the case for the position that Spark is actually a framework for developers to create APIs: we have control over the URL, the parameters to be submitted, and the code to execute when the API calls are made.

So I think it is perfectly reasonable that Spark give us a system for designing a RESTful API with a bit more flexibility for us as developers. In this case, it would be fine for code to be executed on our Spark Cores from a GET request. It would be up to us, the developers, the API designers, to make sure that in this case resources are not being changed from GET requests. Let us, the developers, pick whether each API call is GET or POST based on whether resource state is being changed.

I know, I know, this will allow users making non fully REST compliant APIs where GET requests modify resources on the server (Spark Core). I admit that I would immediately make a non-compliant REST API and use GET requests to change server state.

Moors7 made some very good points about encouraging good practices for developers, and is right that we don't want to encourage bad behaviour. So, let's look at this closely: how bad is this behaviour?

To answer this, we need to look at what the harm is in allowing GET requests to change resource states. What's the advantage of POST in a case where you are changing the resource's state in some way?

From what I can see, there are two key cases where there is an advantage to POST over GET when changing server resource states:

  1. Resubmitting a POST request could be dangerous. Browsers know this, so they display a warning if you press refresh after a form POST. For example, if code on the other end did actually execute and changed a server resource, but failed to respond. There's no way of the client knowing what happened, but at least the browser can warn the user that they are about to resubmit the same data. No such warning is displayed when you press refresh on a GET requested page since technically they are not supposed to change each time you request them.

For case number 1, since the Spark API does not return an HTML resource, the browser does not give these types of warning anyways. For many applications, resubmitting the data is actually fine. Remote control is very popular, resubmitting the forward button is perfectly OK. For those cases that it is not OK to resubmit data, it is already up to us developers to implement this warning or other protection. Having the API enforce POST vs GET does not help protect against resubmitting data.

  1. POST cannot be cached, GET can. With GET requests, browsers can skip calling the server if they think they have a fresh copy of the resource already.

For case number 2, there is a HTTP header to specify that GET requests should not be cached. So this automatic behaviour of POST can be applied to easily make GET requests not cache as well. In fact, I had a look at the HTTP headers given to the GET requests for Spark variables, and sure enough, "Cache-Control:max-age=0" is in there, specifying no caching.

I think that when rigidly complying with a specification provides no advantages, and gets in the way of getting things done, you should bend the rules.

I suspect that similar reasoning led to the HTML FORM element allowing the GET method to submit data to the server for processing. There are very few cases where submitting a form full of data is not going to change some resource's state on the server, and yet there it is, right in the FORM specification. GET is actually even the default, it's just so much easier a lot of the time than POST.

Many companies have reached this conclusion with their APIs. I have used many APIs over the years that use GET to change server resource states. The Adobe Connect API for example does this:

Changing server resource states with API calls via GET requests is a standard industry practice.

If you want to get totally technical about REST compliance, any API that uses JSON is not RESTful:

One of the key constrains on REST is that a RESTful API must use hypermedia formats (the HATEOAS constraint). Unfortunately, JSON is not a hypermedia format. Source: http://restcookbook.com/Mediatypes/json/

Should we just throw JSON away and never use it? Of course not, we need to send data back and forth, and JSON is a great way to do it, RESTful or not.

So Spark devs, please give us an API framework allowing function calls with GET for an easier way to get work done! :smile:

A friend of mine wanted this feature so I wrote a little proxy to turn the GET into a POST.

https://api.simonpainter.com/core/neil/?device={device name}&function={function name}&access_token={access token}

https://api.simonpainter.com/core/neil/?device=dolly&function=up&access_token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Found a little bug in the way the strings were being passed across so have updated the API.

https://api.simonpainter.com/core/v2/?device={devicename or deviceid}&function={functionname}&access_token={access token}&command={string to pass to your function}

1 Like

This is amazing. Thank you!

It is in fact possible to send a HTTP Post directly from the address bar of many browsers, in order to call a particle.function by pasting this string after adding you own data:

data:text/html,<body onload="document.body.firstChild.submit()"><form method="post" action="https://api.particle.io/v1/devices/DEVICEID/FUNCTIONNAME"><input value="TOKEN" name="access_token"><input value="6" name="args">

Fill in DEVICEID, particle.function FUNCTIONNAME and your TOKEN. Also, in this example an argument is passed to the function (the number 6).

Source: https://stackoverflow.com/a/34385367

2 Likes