Boilerplate for a basic PHP cURL POST or GET request with parameters on Apache

cURL is a library for transferring data using various protocols – in this case most importantly HTTP POST and GET. PHP installed on a Linux distribution or as part of XAMPP uses libcurl. If you haven’t enabled cURL yet, open your php.ini and remove the semicolon at the beginning of this line:

;extension=php_curl.dll
^--- remove this semicolon

You will find the location of your php.ini in the output’s first line when running

php --ini

on the command line or by using the XAMPP control panel on a Windows machine. Click the ‘Config’ button next to the Apache module and select ‘PHP (php.ini)’ from the context menu. Save the changes and restart Apache – either by pressing ‘Stop’ & ‘Start’ on the XAMPP control panel or by using the Linux command line:

sudo service apache2 restart

If cURL for PHP isn’t installed, run

sudo apt-get install php-curl

 prior to the step above.

You’ll find further information on how to use cURL here: http://php.net/manual/en/book.curl.php

This boilerplate wraps cURL in a simple function with four parameters: request type, url, parameters and headers. The first snippet contains comments for every step. The second snippet is exactly the same code but without any comments.

Commented boilerplate:

<?php
 
$url = 'http://httpbin.org/post';
 
$parameters = array(
      'firstKey' => 'firstValue',
      'secondKey' => 'secondValue',
      'thirdKey' => 'thirdValue'
);
 
$headers = array(
      'X-Custom: 123',
      'X-Api-Key: ABC123'
);
 
// fire the request. Access the response object with $response->success and $response->body
$response = request('POST', $url, $parameters, $headers);

     
/**
 * cURL a resource with parameters
 *
 * @param string $requestType The request type POST or GET  
 * @param string $url The request URL
 * @param array|null $parameters An array of request parameters
 * 
 * @return object Response object with $success (bool) and $body (string) property.
 */ 
function request($requestType, $url, $parameters = null, $headers = null){
 
      // instantiate the response object
      $response = new stdClass();

      // check if cURL is enabled
      if(!function_exists('curl_init')){

            $response->success = false;
            $response->body = 'cURL is not enabled.';

            return $response;
      }
 
      // instantiate a cURL instance and set the handle
      $ch = curl_init();
 
      // build http query if $parameters is not null. Parameters with null as value will be removed from query.
      ($parameters !== null) ? $query = http_build_query($parameters) : $query = '';
 
      // POST:
      if($requestType === 'POST'){
 
            // 1 tells libcurl to do a regular HTTP post and sets a "Content-Type: application/www-form-urlencoded" header by default
            curl_setopt($ch,CURLOPT_POST, 1);                
            // add the query as POST body
            curl_setopt($ch,CURLOPT_POSTFIELDS, $query);     
            
      // GET:
      }elseif ($requestType === 'GET') {
      
            // if not empty, add parameters to URL
            if($query) $url = $url . '?' . $query;                
               
      // ELSE: 
      }else{
 
            $response->success = false;
            $response->body = 'request type GET or POST is missing.';

            return $response;
      }
      
      // set the URL
      curl_setopt($ch, CURLOPT_URL, $url);                  
      // tell cURL to return the response body. A successful request will return true if not set.
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);       
      // disable ssl certificate checks. Dirty, insecure workaround for common error "SSL Error: unable to get local issuer certificate". Fix it the correct way and remove the line!
      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);      
      // more options here: http://php.net/manual/en/function.curl-setopt.php
 
      // add headers if present
      if ($headers !== null) curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

      // execute and store the result
      $result = curl_exec($ch);                             
 
      // check if request was successful. If yes, return result. If not, return error and its code.
      if($result !== false){

            $response->success = true;
            $response->body = $result;

      }else{

            $response->success = false;
            $response->body = curl_error($ch);
            $response->error = curl_errno($ch);
      }                  
      
      // close session and delete handle
      curl_close($ch);                                      

      // return response object
      return $response;                                       
}
 
 
 
?>

 

And the raw template without comments:

<?php
 
$url = 'http://httpbin.org/post';
 
$parameters = array(
      'firstKey' => 'firstValue',
      'secondKey' => 'secondValue',
      'thirdKey' => 'thirdValue'
);
 
$headers = array(
      'X-Custom: 123',
      'X-Api-Key: ABC123'
);
 

$response = request('POST', $url, $parameters, $headers);


function request($requestType, $url, $parameters = null, $headers = null){
 
      $response = new stdClass();

      if(!function_exists('curl_init')){

            $response->success = false;
            $response->body = 'cURL is not enabled.';

            return $response;
      }
 
      $ch = curl_init();
 
      ($parameters !== null) ? $query = http_build_query($parameters) : $query = '';
 
      if($requestType === 'POST'){
 
            curl_setopt($ch,CURLOPT_POST, 1);                
            curl_setopt($ch,CURLOPT_POSTFIELDS, $query);  

      }elseif ($requestType === 'GET') {

            if($query) $url = $url . '?' . $query;

      }else{
 
            $response->success = false;
            $response->body = 'request type GET or POST is missing.';

            return $response;
      }
      
      curl_setopt($ch, CURLOPT_URL, $url);                  
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);       
      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);      
 
      if ($headers !== null) curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

      $result = curl_exec($ch);                             

      if($result !== false){

            $response->success = true;
            $response->body = $result;

      }else{

            $response->success = false;
            $response->body = curl_error($ch);
            $response->error = curl_errno($ch);
      }                  
      
      curl_close($ch);                                      

      return $response;                                       
}
 
 
 
?>

 

 

Disable autoplay on Youtube’s new 2017 material design release

I happened to receive Youtube’s new 2017 desktop material design when I was watching videos the other day. All in all a great redesign which closes the gap to their other channels. You can force the new design by running the command below in your Firefox’s console’s command line (press [CMD] + [SHIFT] + [K]). Reload the page when done.

document.cookie="PREF=f6=4;path=/;domain=.youtube.com";

Unfortunately, the Firefox Greasemonkey script I used to disable Youtube’s autoplay feature does not work with their new site. Just removing the autoplay toggle’s node from the DOM does not do the trick anymore. My investigations brought to light that the f5 property of the PREF cookie is used to toggle the autoplay feature under the hood. f5=30000 is the default value to disable autoplay and f5=20000 the default to enable it. So I built a new Greasemonkey script which reads the existing PREF cookie, looks for the f5-property and sets it accordingly (or adds it if not present). At the same time all existing values are preserved. Additionally, the autonav_disable cookie is set. It was the first thing I found during my investigations which made me think “easy….”. Anyways, it turned out this cookie is not used to control autoplay. Not sure what it does, but I set it just to play safe. Finally a MutationObserver is used to wait for the autoplay toggle and remove it once it is loaded. DOMContentLoaded did not help as it seems like the node is added afterwards. To install the script, first get Greasemonkey for Firefox here . Once Greasemonkey is installed, click here to install the Userscript or paste the code below into your own script. Force reload Youtube by pressing [CMD] + [F5] after successfully installing the script.

// ==UserScript==
// @name        Disable Youtube Autoplay Material Design
// @namespace   https://kubath.com
// @include     *youtube.com/*
// @version     1
// @grant       none
// @run-at      document-start
// ==/UserScript==

/*
 * This script disables Youtube's autoplay feature on the new 2017 material design page. 
 * The new design is currently in test and will not be shown to every user. 
 * To enforce Youtube's new material design run the command below in the console and reload the page.
 * document.cookie="PREF=f6=4;path=/;domain=.youtube.com";
 * 
 * This script will also disable autoplay on Youtube's previous page (prior to 2017).
 *
 * Bonus: To hide the cookie consent header uncomment setCookieConsentHideCookie(); below.
*/


var cookieDomainValue = '.youtube.com';
var prefCookieKey = 'PREF';
var prefCookieAutoplayToggleKey = 'f5';
var prefCookieAutoplayToggleValueAutonavDisabled = 30000;


setAutonavDisabledCookie(); // set autonav_disable cookie
setAutonavDisabledPrefCookie(); // set autoplay pref cookie (f5 = 30000)
// setCookieConsentHideCookie(); // uncomment to hide cookie consent bar
removeAutonavElement(); // remove autoplay element


// get cookies
function getCookie(name) {
  var value = '; ' + document.cookie;
  var parts = value.split('; ' + name + '=');
  if (parts.length == 2) return parts.pop().split(';').shift();
}


// wait for the autoplay bar to appear and remove it
function removeAutonavElement() {
  var mutationObserver = new MutationObserver(function (mutations, mutationObserverInstance) {
    var element = document.getElementById('head');
   
    if (element) {
      element.remove();
      mutationObserverInstance.disconnect();
      return;
    }
  });
  
  mutationObserver.observe(document, {
    childList: true,
    subtree: true
  });
}


// set the autonav_disabled cookie (which appears sometimes but does not seem to have any effect)
function setAutonavDisabledCookie() {
 
  document.cookie = 'autonav_disabled=true; path=/; domain=' + cookieDomainValue;
}


// get the PREF cookie, search for the f5 key and set the required value to disable Youtube autoplay
function setAutonavDisabledPrefCookie() {
 
  var input = getCookie(prefCookieKey);
  var output = '';
  
  if (input && input.indexOf('=') !== -1) {
    var inputArray = input.split('&');
    var outputArray = {};

    var found = false;
    
    for (var i = 0; i < inputArray.length; i++) {
      
      var temp = inputArray[i].split('=');
      
      if(!temp[1]){
        
        temp[1] = '';
      }
      
      outputArray[temp[0]] = temp[1];
    }
    
    for (var key in outputArray) {
      
      if (key == prefCookieAutoplayToggleKey) {
        
        found = true;
        outputArray[key] = prefCookieAutoplayToggleValueAutonavDisabled;
      }
      
      if (output == '') {
        
        output = key + '=' + outputArray[key];
      } else {
        
        output = output + '&' + key + '=' + outputArray[key];
      }
    }
  }
  
  if (!found) {
    
    if(output == ''){
      
      output = 'f5=30000';
    }else{
      
      output = output + '&f5=30000';
    }
  }
  
  document.cookie = prefCookieKey + '=' + output + ';  path=/; domain=' + cookieDomainValue;
}


// bonus: set the "remind me later" cookie for the cookie consent bar
function setCookieConsentHideCookie(){
  
  document.cookie = 'HideTicker=true; path=/; domain=' + cookieDomainValue;
}

Bonus: To hide Youtube’s cookie consent bar, uncomment the first occurrence of setCookieConsentHideCookie(); in the script.