Professional WordPress enthusiast and developer with a recent interest in Laravel. When not doing WordPress, he enjoys Netflix and playing Nintendo. He is also available for freelance opportunities. Get in touch to hash out the details.
Now that Tailwind CSS is approaching version 1.0, I wanted to go ahead and start using it on some projects that will be launching in the next few months. It seems the API is stable, so now seems like as good a time as any to document how to get Tailwind up and running with a new Laravel project.
All you need to do is run a few simple commands.
Install Tailwind 1.0 Beta
yarn add -D tailwindcss@next
Install Laravel Mix Tailwind
yarn add -D laravel-mix-tailwind
Generate Tailwind config file
yarn tailwind init
This is where all of your modifications to Tailwind will live. Check the official documentation for specifics on which keys to add/override depending on your needs.
In your webpack.mix.js file, replace it with this snippet to mimic the default behavior in a new Laravel project.
const mix = require('laravel-mix');
| Mix Asset Management
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your Laravel application. By default, we are compiling the Sass
| file for the application as well as bundling up all the JS files.
The above snippet will compile Tailwind using the standard app.scss as the base. Be sure to add your Tailwind directives to the top of that file so the utility classes are injected. You can also still use SASS if that’s something you want to take advantage of inside of your custom CSS components.
Running Mix is the same as always.
yarn run watch
yarn run dev
If something changes when Tailwind 1.0 is officially released, I’ll try to update this article accordingly. Leave a comment or reach out on Twitter if something needs to be updated or modified.
Well, as usual it’s been a while since I’ve posted something here on the blog, but some recent life events have convinced me it’s time to share what’s been going on.
On February 25th, 2019, I went to the doctor for a checkup for the first time in almost a decade. I’d been secretly dreading the appointment because I knew that he was going to say some things I did not want to hear. Stepping on the scale it wasn’t really a surprise to hear him say I weighed 310 pounds. I was honestly expecting it to be a bit higher. Next, came my blood pressure readings, my resting heart rate, and a plethora of other measurements. By the end of the exam I felt worse than the week before when I had an upper respiratory infection.
We went back to his office from the exam room and discussed some more specifics. I was so unhealthy, I was/am practically a walking heart attack at 24 years old (the results of my blood work taken that day later confirmed that). I was devastated inside. I didn’t know what else to say other than, “Ok.”
Near the end of our time together that day, the doctor gave me some tips. He suggested looking into intermittent fasting; something my wife’s doctor had recommended to her to help her reach her goal of losing a few pounds. That sparked a small bit of hope inside of me. Even if I had to change my eating habits, at least I could share the schedule with my wife. While I was sort of correct in this assumption, I was also not expecting what happened next.
When I got home (after grabbing some Korean fried chicken from Bonchon), I started doing what any good millennial would do; research on the internet. I started on Reddit since I remembered seeing a /r/fasting sub, but that quickly led to /r/intermittentfasting where I was assaulted by pictures of people who looked a lot like me slimming down in record times. I was honestly skeptical but willing to try it.
I found my way to the Zero fasting app and jumped right in with an 18:6 fast (eighteen hours fasting, six hours eating). My normal schedule was already skipping breakfast most days and eating a late lunch. I figured a 2PM lunch would force me to eat my next meal with my wife after she got home for work around 6 or 7PM each night.
Over the next two days, I continued the routine. My diet was probably still sub-optimal. On my doctor’s advice, I was cutting out a lot of carbohydrates as well. Instead of fries with my chicken wings, I got coleslaw instead. By day 3 I noticed I was pretty much fasting for 20 hours a day from dinner the night before to the time my wife got home, so I decided to bump up my fasts to 20:4. Why not take advantage of the extra fat burning time?
This was where I began really diving into more information about intermittent fasting, especially around people who are seriously overweight. I soon discovered Dr. Fung, a kidney specialist who focuses on patients with complications from type 2 diabetes. I won’t go into too much detail here but I do recommend you browse through his YouTube channel if you’re interested in more.
Unlike other “celebrity” doctors, Fung has very few uploaded videos of his own, which indicated to me that he wasn’t creating content for the money. He does however, frequently appear on other YouTube channels and radio shows discussing his ideas and findings. I especially recommend his series titled “The Aetiology of Obesity”, a six part series that appears to be a collection of lectures he gave to other doctors. It’s a big commitment to watch, but the information really eased some of my fears and quashed some common misconceptions around fasting.
The crux of his research and testing has basically boiled down to that fact that type 2 diabetes and many of it’s complications can be solved simply by fasting. Simply restricting the intake of calories (liquid or solid) tells your body to enter into fat-burning mode once all the glycogen (sugar, basically) is used up from your previous “meal”. I use quotes because sugary juices and sodas aren’t viewed any differently by your cells when it comes to absorbing nutrients.
Learning all of this really got me thinking. After a couple of weeks, I got the nerve to try a 24 hour fast (or one meal a day) for the first time, despite basically I having achieved that milestone a few times already. Some of my 20 hour fasting days had only comprised one meal, but I was afraid to start my next fast early in case I felt that I really needed a banana or small snack before bedtime. 24 hours was a piece of cake. I felt so good, I decided to try it again on the day leading up to my next doctor’s appointment. That would be my first return since starting this experiment with intermittent fasting.
The Checkup, Pt. 2
In the days leading up to my appointment, I was nervous. During these few weeks, I had purposefully stayed away from the scale so as to not get discouraged by fluctuations of water weight from day to day. Reddit comments always hammered that on posts from people seeing little progress after only a few days of intermittent fasting.
Arriving at the doctor’s office, I walked into the exam room and he ushered me to the scale. I could feel my heart pounding and wondered if it would affect my resting heart rate results later. The doctor plopped the largest weight over to the 300 mark, where it had been from my previous visit, and immediately it fell to the right; too heavy! Success! I had at least dropped 10 pounds in 24 days. The doctor gave a small smirk, seemingly surprised and pleased. He kept adjusting the weights and my eyes kept getting wider and my heart kept pounding faster.
When he was finally finished, the scale reported 289. I had lost 21 pounds in 24 days. Nearly a pound a day on a diet of chicken wings, beans, brown rice, chicken thighs, fish, and a cheat meal of Domino’s pizza while babysitting. I was absolutely ecstatic. I should also mention that I didn’t exercise at all, only doing my normal routine.
The doctor finished taking some other measurements, noting that my heart rate and blood pressure had gone down significantly since my last visit. I honestly think he was probably a bit surprised as well. I’m sure it must be nice to have your patients listen to your advice once in a while.
Back in his office, we discussed the results of my blood work taken from the previous visit. 3 weeks prior, I technically met the definition of a type 2 diabetic. My cholesterol was also very high, a side effect I later learned was due to inflammation caused by my body’s resistance to insulin. I was dreading the news that I would need to start on some sort of diabetes medication, but because of my results that day, the doctor said he was not going to prescribe them yet, dependent on my continued improvement.
I left his office that day with a prescription for some cholesterol controlling medication and a recommendation to work my way up to 4000mg of fish oil tablets per day; a common suggestion for individuals with high cholesterol levels. I was a bit disappointed, but I was also hopeful that I may be able to wean myself off of this stuff with continued results.
Following my appointment, I was now more determined than ever to see things through. I now had the validation that what I had been doing was working. I also had more confidence in myself and my ability to control my cravings and impulses.
Peer Pressure & Progress
Shortly before my second appointment, I discovered the LIFE Intermittent Fasting app. I was initially drawn to it after seeing the progress bar in the app, showing progress points within each fast of when your body has started reacting in a new way.
Upon downloading the app, I also learned of it’s built in social features; encouraging you to connect with other people who are fasting and share your progress throughout your fasting period. I quickly got my wife and a coworker on board and watching each of our progress bars advance was a great motivator when I was feeling hungry before my it was time to eat again. Reading stories on /r/intermittentfasting was also a huge motivator.
A week or so after my second appointment, I decided to experiment with a longer fast of 48 hours. From the information I had consumed, there are a plethora of benefits from fasting more than 24 hours and I was excited to see what kind of results I could achieve and push my willpower even further. Worst comes to worst, I could back off and eat whenever, not feeling guilty at only making it 24+ hours.
The second half of my first 48 hour fast was brutal. The hunger pangs were intense when they arrived, not helped at all by my insistence to torture myself with cooking shows on YouTube. I discovered water was even more of a friend than I previously thought, filling my stomach with as much as I could when hunger reared it’s head. Eventually the rumblings would subside, usually within a half hour of drinking a lot of water and I was back to work or playing some video games to keep my mind occupied on something other than food.
At the end of the 48 hours, I was happy to eat again and proceeded to stuff my face with what was probably 3000+ calories in one meal. It’s important to note however, that my daily energy expenditure just from existing is around 3500 calories a day. So even gorging myself I was still at a deficit. I’m sure as I continue to lose weight that resting calorie burning rate will decrease, but whatever it is, I’m still far below that threshold on any normal eating day.
Feeling good about my progress, I decided to try couple more 48 hour fasts, sometimes coming up a couple hours short but not sweating it too much. 46 hours is still great and I would rather eat a nice dinner with my wife at her normal dinner time. I now have really come to internalize that intermittent fasting is about a lifestyle change that should work for you as an individual. I refuse to feel guilty breaking a fast early to socialize with friends or family, though I do admit I am now addicted to seeing the “Fast complete!” notification on my phone every night.
Every Friday I now weigh myself. I still don’t weigh daily due to water fluctuations and I know from previous diet attempts that seeing the scale bounce up and down every day isn’t good for my mental health. I figure a week is enough time to show a trend without worrying if I’m a pound or two heavier/lighter due to how much water I drank the day before.
As a side note, I’ve had a Fitbit Aria scale for a few years now and really enjoy it despite not owning an actual Fitbit anymore.
This Week in Fasting
After completing a few 48 hour fasts, I resolved myself this week to attempt a 72 hour fast. I started Sunday evening, made it through the obstacle course of snacks at my church small group meeting on Monday night, and was feeling good heading into Wednesday. I was already fantasizing about my dinner for that evening. As the time grew closer and closer though, I realized that I wasn’t really hungry. Sure, I could eat, but I had grown so used to the rumbling of my stomach and the mental feeling of hunger, that I started to wonder if I needed to eat at all? With another hour of contemplation, I decided not to break my fast, and instead continue for at least 24 more hours.
At the time of this writing, it’s now Friday. This evening I will break my fast seeing a movie at a dine-in theater with my wife after 120 hours of not eating anything and only drinking water, tea, black coffee, and a few carbonated waters (with only a small squeeze of lime for flavoring). I’ve made it 5 entire days without eating anything, all the while watching friends and family eat their meals while I gaze on, trying to keep up the conversation.
At my weigh-in this morning, I weighed 275 pounds. 35 pounds lost in 39 days. I know this kind of rapid progress won’t last forever, but I’m grateful for the results in the meantime. Overall, I feel better, more alert during the day, less tired when I should be focused, and look better to boot! I count all of that as a win.
I’m really proud to have completed a five day water fast. I’m not sure when I will do it again, but I can now picture a future where two day fasts are even more frequent. If my schedule with allow it, I would love to try an even longer extended fast in the coming months, perhaps 14, 30, or even 40 days! I realize that with extended fasting comes more variables to consider such as micro-nutrients and electrolytes, but I’m confident I can navigate those obstacles effectively.
If anyone is considering starting intermittent fasting, for weight loss reasons or otherwise, I would encourage you to at least give it a shot for a few weeks. You don’t need to drastically change your diet. Simply cut out all food for at least 16 hours a day and only drink water during that fasting time. For most people, this can mean an eating window of 12pm-8pm. Adjust that forward or back according to your personal schedule and needs.
If you have any questions at all, feel free to leave a comment, or reach out privately. My DMs on Twitter are open and I would love to chat about whatever you want, fasting or otherwise. If you want to join a circle with me on the LIFE app, you can click this link to be added instantly.
I look forward to meeting you soon and seeing how we all progress together!
Photo credit to Stas Knop and downloaded from Pexels.
Problem: Door Sensor won’t connect to Z-Wave Network
At our office, we have a small Z-Wave network setup running a Raspberry Pi and Home Assistant, specifically Hassbian because at the time of our purchase the newest Pi 3B+ was not supported for Hass.io.
On the Z-Wave network we have a single door sensor on the front door that theoretically notifies us when someone enters the office. Long story short, we had it setup remotely and after 3 days of shipping via USPS, it didn’t work at the physical office. Bummer!
Now, a few months later, I’m here to troubleshoot in person while in town helping out with other things. I set the thing up in the first place so it shouldn’t be too hard to fix right? Wrong again!
The EcoLink Door Sensor seems to be a decent product. It has pretty good range; ours is located about 30 feet away from the controller. The controller is inside a giant metal server rack and behind a solid wall. Not the best conditions for sure! The manual however is complete and total garbage. Below you will find the steps to completely remove the device and re-add it to your network.
Reset the Device
To properly “reset” the device you must first determine if it’s currently connected. In my case, the sensor actually thought it was still connected to something. Placing a magnet against it would cause the green LED to give one long flash. In this case here’s how you fix it.
Check that your battery is not dead. If the sensor has been unconnected from a Z-Wave network for a while, it’s likely tried to pair itself continuously and drained the battery.
Navigate to your Z-Wave controller software and initiate a node removal. In Home Assistant, there is a button called “Remove Node”. Press it.
Remove the cover and battery from the device for 5-8 seconds. Do not wait too long though or the node removal will time out. Within 20 seconds of initiating the node removal should be fine.
Plug the battery back in with the cover removed. The LED should flash continuously if it was successfully removed. (Note: these steps will remove the device from any Z-Wave network it was previously connected to)
Click the “Add Node” button on your Z-Wave control software while the LED is blinking.
Remove the battery for 5-8 seconds and then replace the battery. The LED blinking pattern should change and stop soon after pairing.
At this point, you should see confirmation of the added node in your controller software. To complete the process, run a network heal to make sure everything is communicating efficiently.
Now you should be able to monitor the state of your sensor in Home Assistant.
If you have any questions, leave a comment or shoot me a tweet @DaronSpence
I’ve been really getting in to Home Automation lately. I don’t own a home, but there is a surprisingly large pool of things you can implement when living in an apartment. Most recently I’ve been playing with automating lights, starting first with the humble bathroom! I’m one of those people who needs a light to use the bathroom. Even if it’s the middle of the day, the sun is shining, I have to turn on a light. This has been an experiment to relieve my brain of that pressure, as well as make any late night excursions a little more pleasant.
This whole project can be done for around $20 to just make the sensor. For a DIY approach, it’s not bad! The nice thing is that it’s also a great platform to add more sensors too down the line for a small investment.
Things you’ll need
Raspberry Pi Zero W (RPiZW for short)
8GB+ Class 10+ Micro SD Card
PIR Motion Sensor with headers
A few jumper wires (or loose wire to solder)
I decided to start with the hardware as this made the most sense. I picked up a RPiZW from my local Micro Center for $13 with header pins. I’m still relatively new to soldering, so it didn’t make sense to purchase the headers separately if I might screw it up. The price of headers with a bare computer also happened to be slightly more expensive. Win win for me! I also grabbed a cheap plastic case for around $5.
The next thing I needed was the motion sensor. I also picked this up from Micro Center, but at what I later found out was a steep premium. A 3 pack of these sensors can be found on Amazon for $5, whereas I paid $6 for one. If you want your homemade sensor to be multi-functional, a temperature/humidity sensor is a great addition for just a few more dollars.
Follow the directions to hook up your sensor to the Pi. In my case, the PIR needed 5V, a ground, and a data pin. I used GPIO 14, but feel free to use any open GPIO if you are adding this to an existing board. Using some extra female to female jumper wires I had laying around, it took all of 30 seconds to hook everything up. Now onto the software.
I used Etcher to mount Raspbian Stretch to the SD card. While I have the hardware necessary to setup the Pi using the GUI, it didn’t make sense considering I will likely never need to use it again, except to tweak a few values in a script file occasionally. I followed a setup guide for installing the OS headless, got it connected to my network and SSH’d in. Once logged in, I needed to install pip using the apt package manager then I needed to install paho-mqttusing the newly installed Python package manager. I did run into an issue here with the library being detected, so I recommend doing a reboot just to refresh everything. Since the computer is basically empty, it takes maybe 30 seconds even on the low spec hardware.
After that, I adapted a simple Python script I found online to access the GPIO pins, and constantly read the data for the motion sensor. When the pin is pulled high (1 in my case), then motion has been detected. Whenever motion is detected, I fire off a very simple MQTT event using paho.mqtt.publish. While it’s technically not the most efficient way to send data, it is much easier to read and the bathroom is such a low traffic area, the extra overhead to connect to the MQTT broker is not an issue. If you are potentially sending constant updates for temperature and humidity, it may be worth looking into the client method in paho.
To run the script on startup, I added a cron task on @reboot to start the Python script. I’m not an expert on the Linux startup processes enough to know when the network kicks in, so at the top of my Python script, it sleeps for a minute while the computer finishes booting and connects to my network. So far, this has worked fine and should continue to work even in the case of an ISP failure, since the Pi is connecting a MQTT broker on my local network.
With that working, I subscribe to the MQTT topic from within my Home Automation software, OpenHAB at the moment, and then everything else is connected there. For my own purposes I have a few simple rules. The bathroom light is controlled with wireless smart bulbs (IKEA Tradfri). Upon entering the bathroom, motion triggers the light to turn on. From there a timer starts for 2 minutes. If motion is sensed before that timer expires, it is reset back to 2 full minutes. This is fine for most bathroom tasks. Brushing your teeth or hair are very animated tasks that constantly trigger the sensor, which is positioned in the corner of the vanity, facing the door and whoever is standing in front of the sink. For other more, private rituals, two minutes can be a little too short if you like to read Reddit on your phone. Luckily a quick swipe of the arm or shake of the head will trigger the sensor again and turn on the lights.
For showering, I placed an IKEA Tradfri remote near the shower that can be used to manually turn on the light so poking an arm out is not required every few minutes. Upon exiting the shower, motion is sensed and the 2 minute timer is started. Unfortunately, there is no way to re-purpose the Tradfri remotes yet for custom events, otherwise I would have it be a manual override at all times. This way, one could press the button before getting in the shower and then press it again after they are done. Or perhaps manually overriding the timer for 45 minutes instead of 2. Plenty of time for a long shower or bath.
At Midnight, the bathroom light automatically changes to a very dim, but solid red. This is to help preserve night vision for those late night trips to the loo. At 6AM, the lights are changed back to a bright white, the preferred color of my wife and I for our lights.
Since it’s just the two of us, the 2 minute timer is fine to deal with. We’ve had it running successfully for 3 days now and haven’t minded the occasional shut-off. If anything it’s a reminder to hurry up since we only have one bathroom in our apartment! When guests come over, I plan to change the timer to a much more generous amount, most likely 10-15 minutes. I also plan to have the manually override ironed out by then.
In the future I may add a temp/humidity sensor to effect the timer, since even a moderately warm shower will raise the overall humidity in the bathroom. Adapting the script to read an extra GPIO pin or two should be straightforward as well.
Below is a short demo I recorded the night I got everything working. Over time I hope to add the script as well as some more in depth assembly photos. If that’s something that interests you, leave a comment or tweet me @DaronSpence and I’d love to hear your thoughts. I’m also happen to answer any questions about my setup.
Somedays are better than others. Somedays just suck. Somedays are pretty good. Lately, I’ve been on the lower end of the spectrum. I’m not sure what it is, but the past few weeks have been harder than usual. The mental breakdown between productivity and laying in bed all weekend is a finer line than I would like. This might just be a little rant, but as I was reading through Reddit, I got the urge to write down some thoughts so I’m going to vent. Hello stranger! I hope your stay here is fruitful.
Maybe this all started with the celebrity suicides? I have to admit, while I did know of both Chris Cornell and Chester Bennington, I never really knew much about them. Sure, I listened to Soundgarden and Lincoln Park, but I wouldn’t describe myself as anything more than an extremely casual “fan”. Seeing the interaction though, watching how one person’s decision had such a profound effect on someone else; it’s made me think.
Last summer, my father in law killed himself. I haven’t really talked to anyone about it. Not my wife, not my mother in law. Not my own friends or family. My wife found his legs sticking out from the closet in the master bedroom one morning. I rushed over to their house outside the city and waited in the front yard as the coroner arrived and cops continued to waltz in and out of the house. As they wheeled him out in a bodybag on a stretcher, I asked to see him. Call it morbid curiosity, but at the same time, I felt almost an obligation to him. I married his daughter and she would never see him again, so maybe it was up to me to carry on that final memory, for her sake? In case she ever wanted to know?
After they took his body away, I was left at the house to keep an eye on things. A relative had paid for a hazardous waste disposal company to come by and clean up the mess he left behind. Someone had to watch them right? What do you do in that situation? I sat on the edge of the bed for a few minutes, staring into the pool of blood in the closet where he shot himself. He put towels down. Despite being dramatically intoxicated, he took the time to make it “easier” for whoever was left to clean up the mess. There was something respectable about that.
The waste disposal team finally arrived. Not what I expected at all. It was an older couple in their late fifties, with a big pickup truck pulling a plain white enclosed trailer full of cleaning supplies, power tools, and even a few sheets of sheetrock. It makes sense when you think about it. Everything with blood on it has to be cleaned or removed. They were nice people. They’d obviously been doing it a long time. It took them a few hours to comb through the clothes in the closet, remove the ones with blood, and then rip up the carpet and the subfloor after soaking the blood with cat litter. Then they were gone. I was left alone in a dark house, with an few square feet of carpet missing in the master bedroom closet.
Again, I mentioned at the beginning I wasn’t sure where this was going. I live in that house now. My wife and I moved in to help her mom with the mortgage and the bills. Sometimes it’s weird to walk past that bedroom and think about what happened; about what I saw. It’s a small thought in the back of my mind at all times. An ever present darkness. I feel like that’s a book I read somewhere…
So maybe it’s just that? You see all the shit on the news about all the terrible things that happen in our world and they remind you of your own dark thoughts. But that’s part of being human right? Knowing that all of this is temporary; that it happens to everyone. I find comfort in that I think. That someone, somewhere is struggling to find meaning in the same things that I don’t understand. Maybe that person is you.
If you want to talk, reach out to me on Twitter, or a leave a comment if I still have those enabled. I honestly can’t be bothered to check right this second. I don’t think I’m in a “dark place” right now, just a difficult one, and maybe you are too. I think I’m gonna take a trip down to the coffeeshop and try to get some work done, drink some tea, try to find something useful in my own thoughts. Let me know if you find something useful in yours.
A few weeks ago, I was experimenting with https:// on the site for my plugin, ACF Widgets. I added the SSL cert for my domain using Let’s Encrypt and the requests were being handled fine, but I was only enforcing SSL on the checkout page. If you hit the ACF Widgets site with https:// initially, everything worked fine, but my login rules were causing some issues with people logging in to the support forums.
After 4 or 5 people contacted me through other channels telling me they couldn’t log in to get support, I decided to look into it a little more closely. As it turns out, the login pages were trying to work over SSL while people were trying to login with insecure http://POST requests. Whoops!
To fix this problem, I needed to convert the whole site to use https:// all of the time. This too worked out fine and wasn’t an issue. 3 lines in .htaccess that you can find on a million different blogs. Super easy stuff. What made things more difficult, was upgrading the URL for my plugin to check and receive automatic updates.
The problem with copying .htaccess rules
I think this goes back to a fundamental flaw with humans, in that we want results and we want them immediately. In 99% of the tutorials I found, most of them advocated for an .htaccess rule that looks something like this:
Generally, this will work, and it’s fine. Let’s go through it line by line.
Turn the Rewrite Engine on. This tells apache that we’re going to do a rewrite so it can load the required modules.
Set a condition. In this case, return true if the server is listening on port 80. (The standard port for HTTP)
Redirect the request to the given URL and pass in the URL query parameters.
Like I said, for most sites this works fine. However, when I pushed the next update to my plugin, I noticed I wasn’t getting any update notices. Why wasn’t it working?!
Now, in my most recent plugin update, I updated the store URL to my new https:// domain, so after everyone updated, I know whatever weird issue going on would probably go away. I did some tests and sure enough, requesting the update using the https:// store URL triggered an update. So why wasn’t it working with the http:// URL? What was happening during the redirect that broke things?
Since I have almost 500 customers, sending an email asking everyone to manually re-install this new version of my plugin was unacceptable. I knew I could do better. I decided to dig-in to the inner workings of APACHE and HTTP a little bit to understand what was going on behind the scenes.
A brief history of redirects in HTTP
So from my understanding of reading numerous blogs, is that the original intent of the HTTP/1.1 spec, was that if no redirect status code was specified (ie. 301, 302, etc) that the client was supposed to treat it as the same method as the original request. So if I send a POST request to /my-api-endpoint/ , the client should honor that POST request and it’s data if I do not specify a status code. In APACHE’s mod_rewrite this looks like:
RewriteRule ^(.*)$ https://example.com/$1 [R]
Using the [R] flag with no options.
Somewhere along the way (I’ve seen both IE and Netscape blamed) browsers and HTTP clients in popular languages begin to interpret any missing status code as a 302. In the HTTP spec, a 302 request is for GET requests only. Herein lies the problem with our updates.
EDD Software Licensing Update Process
To understand why updates are failing, I also needed to examine the source code for the update script I was using. At the time of this writing, ACF Widgets is build upon Easy Digital Downloads and the Software Licensing Add-On. It works great! Though in my case, updating the store to https:// was obviously causing issues. Digging in to the code, we find this:
And herein lies our problem. EDD SL uses wp_remote_post() to send API requests to the URL of our plugin store, which is fine, nothing wrong with that. However, when our POST request to our EDD store encounters a redirect without a specified status code, cURL redirects to a GET request for the homepage with no query parameters. Since that’s obviously not what we want, the EDD SL update script fails silently (like it should) so we don’t clutter the users dashboard with errors in case our store is down for any reason. In our case though, we want to preserve that POST request and any data we send. So how do we do that?
Enter the Magical Hero Extraordinaire Status Code™, 307
The requested resource resides temporarily under a different URI. Since the redirection MAY be altered on occasion, the client SHOULD continue to use the Request-URI for future requests. This response is only cacheable if indicated by a Cache-Control or Expires header field.
Perfect! That’s exactly what we want! In short, this will preserve our POST request and any data we send. So now we can use this in conjunction with a normal 301 request to route all of our traffic through our newly secured domain.
So line by line, let’s go through this new .htaccess.
Turn on Rewrite Engine
Check for a request on port 80
Check for the GET request method
Redirect (via a 301 for SEO purposes) and ignore all other rewrite rules ([L] flag).
Now if we don’t have a GET request (maybe we have an API that uses PUT, POST, or DELETE) it will get routed through the second rule.
Check for a request on port 80.
Perform a 307 redirect, thus preserving our request method and data. Also, ignore any more rewrite rules ([L] flag).
Now for those of you worried about SEO, don’t worry. Google only cares about your visible stuff, AKA GET requests. You shouldn’t get a penalty for other request types (because Google won’t even know to access them).
As you can see, 307 redirects can be extremely powerful. With the correct caching headers, you can even instruct clients to cache the results while you update your API or tools to use your new secured endpoints, without sacrificing security.
So what next?
Since we now have a our store properly configured to redirect requests from plugins out in the wild, there isn’t anything else to do except wait. Customers will update the plugin to the new version which uses the new https:// store endpoint. If you have detailed stats about version usage for your plugin, you could eventually remove the redirect, though I don’t see a reason to for the vast majority of plugin stores out there. If anything, it’s a good catch all for anything you may add in the future and forget about.
Questions? Comments? Leave ’em down below. I would love to hear from you!
Today, I was working on a client project and needed to add a little snippet underneath a hierarchical taxonomy form that was registered on a custom post type. Unfortunately, after spending about ten minutes digging through core and googling, I couldn’t find an action hook to use. Luckily, after tracing the output a little further back, I found what I was looking for.
So just this past week, I submitted my first plugin to the WordPress.org plugin repository. Needless to say, it was an exciting (yet dull) experience! Since I’m still fairly green to professional development as a whole, there were some aspects of the .org publishing process that were confusing, so I’m writing this post in hopes that someone will find it useful. 🙂 Continue reading “Publishing A WordPress Plugin without SVN, Utilizing Ship”