If that’s your wish, then help could be at hand in the form of [Victor Ribeiro]’s RPiAPI. As its name suggests, it’s an API for your Raspberry Pi, and in particular it provides a simple web-accessible endpoint wrapper for the Pi’s GPIO library from which its expansion port pins can be accessed. By crafting a simple path on the address of the Pi’s web server each pin can be read or written to, which while it’s neither the fastest or most accomplished hardware interface for the platform, could make it one of the easiest to access.
Security comes courtesy of Apache password protected directories via
.htaccess files, so users would be well-advised to consider the implications of connecting this to a public IP address very carefully. But for non experts in security it still has the potential to make a very useful tool in the armoury of ways to control hardware from the little single board computer. It’s not the first try at this idea as we’ve seen a PHP example early in the Pi’s lifetime as well as one relying upon MySQL, but it does seem to be a simpler option than the others.
29 thoughts on “A Web API For Your Pi”
You should avoid changing of the state of anything on GET requests… It’s an open door for CSRF exploits.
Plus it’s just confusing. If you’re URL has anything other than nouns in it you probably aren’t following REST principles.
https://restfulapi.net/rest-api-design-tutorial-with-example/ has some good information. If JSON is too big of a burden you could use query parameters (but still the proper verbs).
That’s how you access a POST on WSGI. I’m not lazy or stupid. I decided to use GET cause I had an ideia on my mind. I’m now considering PUT or POST, but GET was very simple to anyone.
Turn on the Light
Anyways, I’ll consider the things I read here on my next iteration.
This is an example of where sticking rigidly to REST principles is not necessarily helpful to the end user. Disregarding the arguments about GET vs POST, etc. The use of verbs in the URLs actually makes the API very transparent and the need for documentation a lot more minimal. (Just because it’s a standard doesn’t mean it’s easy to use/understand)
For a beginner user getting into this sort of thing, at first glance it seems like a really nice introduction to talking to GPIO. If I wanted to go much further, or scale a system beyond hobbyist stuff, I may look at other libraries and be concerned about best practices, etc. but for showing a kid how to make a light flash with some HTML, I’d probably choose this.
Good job Victor, I hope you can keep developing this, but I like the URLs :)
Thanks again for the comment. I’m thinking about making a video from zero to turning on a light with this api and a simple frontend app, passing by activating a rele module connected to the pi.
What kind of request/method would be resilient?
“Applications can be developed to only accept POST requests for the execution of business logic. The misconception is that since the attacker cannot construct a malicious link, a CSRF attack cannot be executed. Unfortunately, this logic is incorrect. There are numerous methods in which an attacker can trick a victim into submitting a forged POST request, such as a simple form hosted in an attacker’s Website with hidden values. “
It’s a bit of red herring. Generally, you don’t want your Pi open to the world without authentication, anyway. These kind of APIs generally aren’t done through web browsers, either. If you want to protect against CSRF, it needs to be through a CSRF token.
That said, best practices are not to modify state with GET requests. It tends to break client assumptions. For example, some old “dial up accelerators” worked by prefetching every link on the page. Web-based file managers would have a delete link, and those accelerators would dutifully follow it.
I’m considering POST or PUT on my next iteration.
Yes, after reading the comments I’m leaning towards POST or PUT to activate / deactivate the pins
The big issue is that if you present your web api as a do-it-all solution/framework for everyone to import into their projects, then you also *must* consider security, standards and general good practices.
Because basically it’s just not so hard to add any sort of web api to your raspberry pi or your ESP8266 or whatever. Anyone can do that with a few lines of code.
But not everybody is capable of doing it in a secure and standardised way, AND following good practices. Your web api should really have some significant added value over custom-made code, in those areas.
Otherwise it’s just better for people to write their own custom code. Because their api will then be custom, not open, and at least give some security-by-obscurity. You published your api, so the security-by-obscurity advantage is not there anymore.
I’m not saying that security-by-obscurity is a good thing. :) But it does have some security advantages over no security at all. ;)
It is an API but not following RESTful principles (as has been pointed out).
Normally you would identify the resource and use the HTTP Verbs to act upon the resource. For example:
GET->/api/v1/gpio would return the state of all pins
GET->/api/v1/gpio/1 would return the state of pin 1
PUT->/api/v1/gpio/1 with a value in the body (formatted as JSON, XML, etc) would set the state of pin 1 to that value
and so on…
An API structured this way can include other resources such as GET->/api/v1/cpu/temperature, GET->/api/v1/cpu/utilisation, etc. The /v1 part allows for future versions which can coexist with the previous versions.
Yes, I was thinking “what makes more sense?” when selecting the endpoints, so I end up using activate / deactivate. I have a chat bot project that I can just say “activate 5” and it would. That’s also one of the reasons all my endpoints are GET, sou can access them with a simple link
A long time ago (in a far galaxy) WebIOPi was the very first REST API for the Pi :-)
Finally I can turn on an led with a massively over powered computer over the internets.
Come on man, you can’t have that lack of imagination
Don’t feed the troll.
NodeRed does it for you, it exposes the GPIOs as a REST API.
Instead of the usual HaD celebration or roasting of mediocrity (which it is) let’s make this a learning experience:
-No way to set multiple GPIO at once.
-Everything is GET as others pointed out. Idempotent state modification should use PUT, as in changing the mode of a pin.
-ADC read should be initiated with POST
-Cache-Control usage is here…seems like he found that out the hard way using a web browser
-Responses lack timestamps or sequence numbers
-Client should be able to request Content Type
He’s an undergrad, so don’t pick on him too hard
I can fix all those things you mentioned, but I can’t fix that attitude. If you don’t like the project and don’t intend to use it or help build it, the next best thing you can do is be polite. I sacrificed my weekend to create this simple but working project.
I am not trolling you Victor. But you must realise that many people here sacrifice their health and/or personal life creating complex and working projects. :)
Just take it as a free lesson by someone who is very much more professional and experienced than any of your professors.
“I can’t fix that attitude. If you don’t like the project and don’t intend to use it or help build it,”
He said, with a demonstrable bad attitude towards constructive criticism.
Seriously, the post you replied to was helpful, full of good, well structured advice, and called for people not to give you a hard time, and this is your response. Wonderful.
“…celebration or roasting of mediocrity (which it is)…”
Victor, I have been in industry for decades. People will be kicking you down for years when you start your career. Dare to do something different and you will be called a heretic. When you find a demonstrable compiler bug in TI’s msp430 compiler, you will be called out for writing unusual code. When you reorganize data in a way that highlights the core patterns people will call it overengineered.
In this case the different thinking was putting a web API on something typically done on the lowest level. In this case the web API was really mediocre and need improvement. Keep working hard.
Shame you didn’t actually keep the context of the actual quote:
“Instead of the usual HaD celebration or roasting of mediocrity (which it is) let’s make this a learning experience:”
Seems like you’re unlearning things with each reply….
and there is also another consideration: apache as web server on raspi? it is far better nginx, for low resources consumption
Well, if you know how to set it up on a nginx server, do it. People who don’t can just run the script and have it working with no time or configuration.
This sort of thing is usually implemented in a language-specific application framework (like Express.js). If it’s exposed to the rest of the world, it’s probably through a frontend proxy that handles authentication and TLS. Nginx makes a good frontend proxy.
I discovered another reason not to change state on a GET when I did a garage door opener years ago. Whenever my wife opened up the web page used to control the garage door and lights, it refreshed the last used URL such as /garage/door/open and the door opened. A post is never automatically resubmitted.
Yes, yours are one of the few good critics I got from these comments. I’ll consider POST or PUT to activate / deactivate pins on the next iteration. Thanks
Please be kind and respectful to help make the comments section excellent. (Comment Policy)