Somehow in the confusion of organizing ourselves for this assignment my group became responsible for building two servers. Turns out that I LOVE developing them, and complimenting the work I did last spring in DWD Online Server, I gained better understanding of how to design a RESTful API framework. Though I’d still argue that the demands of both projects would be better served using sockets, I’m glad for the opportunity to dig in and complete the builds for GET and POST requests. Here’s how our projects rounded out.
This week I finished building out the frontends for both devices (the device clients) which informed some minor server-side changes for both projects. Fortunately, problem solving for both in tandem informed possible solutions for programming logic and libraries to include.
Visual Mode (formerly Super Cool VJ Machine)
It’s here! Finally, you take your party visuals wherever you go.
Visual Mode offers three modes: waiting for super cool input, GIF mode, and an abstract visual mode. Abstract visual mode includes options to activate five different animations: squares, circles, triangles, arcs, and squiggles. Users many change both the background and foreground colors. In GIF mode, users send a word that triggers the server to make a GET request to the GIPHY API and returns a GIF sticker. Stickers have transparent backgrounds, which means users can still set the background color to their liking.
I ran into two problems to solve when building out the GIF mode features:
How to handle repeat requests with the same word? Part of the fun of submitting a word is that the request uses GIPHY’s random endpoint, so sending the same word again and again returns very different results. I added a counter to the server’s state object as a way to track requests to the /gifword route and poll for changes in that counter on the frontend. An increase in the counter triggered a flow of events to remove any existing GIFs and create a new one from the GIF image url stored server-side.
How to make GIPHY requests without exposing my API key? In the beginning stages of development, the frontend handled the GIPHY request. But when I investigated how to hide my API key, I realized that I would have to move the process to server to prevent exposing it during requests. I remembered how to store sensitive information in a separate file from DWD, but then I had to figure out how to structure the request from the server. I ended up using the Request library to do so.
In addition to these, I considered how the VJ output would appear to users on first start. Without their input it would be blank and very confusing. So gave the server state some initial values to prompt interaction: an initial GIF for that mode and rotating turquoise squares on a red background for the other.
Alden and Beverly created the controller client for their VJ machine (pictured above), and when we sat down to test we also ran into a few issues:
CORS! Right away we ran into these error messages. Actually, they’re not errors; it’s expected behavior for browsers when requests are made from different domains (which is how we developed the client controller and server). Here is a helpful article that explains CORS in a friendly way. Because I built out the server using Express.js, I installed their cors module and required it on my server file. Again, useful documentation on how to do this here and here. (Had we bundled everything together into one project under the same domain, we’d likely avoid this issue.)
The server’s state object expects POST values as strings. Not only did we have to make sure we were using the correct word assignment for variables (those included in the body of the request), but we also made sure that any values arriving in requests from the controller were formatted as strings. Otherwise, they would blow out that part of the server object and the screen would go blank. All requests were packaged by using the deceptively simple Axios library in the controller’s frontend.
For future improvements I’d consider:
I can’t remember why I built out the server state object using all strings (maybe I preferred the consistency?) but since the frontend converts the numerical values to integers anyway perhaps I should revisit this.
Handling multi-word submissions for GIF requests. Right now it’s only set up to take single words. My initial guess is that this would require parsing the words server-side on any spaces and reformatting appropriately for the GIPHY call.
Include error handlers in my route callbacks. During my research to build about various sections of the server, I saw many examples of how to do this.
Related to the above, include methods for handling GIF requests that return no data.
Incorporate proper response status codes to reinforce my understanding of them.
Now to the playing! We finished the Super Cool VJ Machine in time to play test with others on the floor for valuable feedback and a chance to consider the dynamics of play beyond all the technical considerations of getting it to work. We set up the output on a screen in the hallway and gave people the URL to the controller.
Again, the GIFs are random, so the element of surprise and whacky returns made this feature endlessly surprising and fun. Playing with others, there’s element of competition to see who can change the output first, and because it’s anonymous, there are the unanswered questions of who submitted and what word they submitted that to prompt the return of the ridiculous GIF.
Finally, I continued to play with it at home, co-curating the content and dialoguing with some unknown person (Alden?!). The above clip is a sped-up recording of that interaction. Off the floor, there’s the added fun in remembering that your decisions play out in a shared, semi-public space.
Of note: we discovered early on that the GIPHY API limits requests to 42 an hour. Unlimited calls require a production key.
Both the controller and the server are living on Alden’s Digital Ocean droplet (for now) here:
Input - Client Controller (code)
Output - Device Client (code)
At the time of this writing, we’ve yet to test our karaoke machine with Roxanne and Jason, but the server and frontend respond to curl requests to select songs for the singer, to pause/play the playback, change its speed, and also submit compliments that display for two seconds at a time.
I added actual karaoke videos from karafun’s Youtube channel of five popular hits. My instinct was to preload these in the P5 sketch, but it turn out that you can only use this for load calls (makes sense), and I couldn’t find any of those for videos. My browser also threw errors when I attempted to push them into an array in for loop. In the end, I landed on a less elegant way that works.
Server-side the list of compliments are also pushed into an array on start. Each time that route is requested, one is randomly chosen to display and is also removed from the array to prevent a repeat appearance. When the array is emptied, it’s replenished with all of them for the next cycle.
The counter worked so well for the Super Cool VJ Machine that I incorporated it into the karaoke server state for to keep track of new song selections. Every time the counter increases, it removes the current video and plays the new one.
Because the other group is also building out an online controller separately, I also added the Express CORS package to this project anticipating similar issues.
Code for Device Client (Output)