Welcome to the new design! Please report any bugs or issues, thanks :)
Web Dev + WordPress + Security

How to Modify GET and POST Requests with WordPress

[ POST Requests ] I’ve written before about protecting against malicious POST requests using Apache/.htaccess. In this tutorial, we’ll look at how to modify GET and POST requests using PHP and some core WordPress functionality (with no .htaccess required).

Normally you would want to manipulate URI requests at the server level, but that’s not always possible (like on shared hosting). So in those cases where you want to modify GET, POST, or other types of requests on a WordPress site, check out the following technique.

Modify POST Requests with WordPress

Here is an example showing how to modify POST requests using PHP and some built-in WordPress functionality. This code could be added via theme template functions.php, or added via plugin.

/*
	Modify POST Requests
	@ https://m0n.co/wp-requests
*/
function shapeSpace_modify_requests() {
	
	if (isset($_SERVER['REQUEST_METHOD'])) {
		
		$method = $_SERVER['REQUEST_METHOD'];
		
		// GET requests
		if (strtoupper($method) === 'GET') {
			
			if (isset($_GET)) {
				
				// modify GET request
				
			}
			
		} 
		
		// POST requests
		elseif (strtoupper($method) === 'POST') {
			
			if (isset($_POST)) {
				
				// modify POST request
				
			}
			
		}
		
	}
	
}
add_action('parse_request', 'shapeSpace_modify_requests', 1);

The main thing to understand about this technique, is that we are using the parse_request action hook. As explained in the WP Codex, parse_request is ideal for modifying URI requests because it:

Allows manipulation of HTTP request handling

By hooking our function shapeSpace_modify_requests() into parse_request, we have full access to all GET and POST variables, plus all server information, IP address, referrer, user agent, and anything else that you may want to utilize or modify.

Inside of the shapeSpace_modify_requests() function, we are using basic PHP functions to check the request method and the $_GET and $_POST variables. As you can see by looking at the code, it is all pretty much self-explanatory. To get a better idea, check out the examples below.

Tip: If the above technique is not working for your requests, try increasing the priority of the parse_request hook by lowering it from 1 to 0.

Examples

Here are a couple of examples to give you a better idea of how it works. The first shows how you would go about securing POST requests on your site. The second example shows how to send an email alert for each POST request. Of course, these examples are easily modified to target GET requests instead.

Example: Secure POST requests

In this example, we restrict POST requests so they only are allowed from the site itself. So example.com can submit POST requests for comments, contact forms, or whatever. But any POST requests from other locations will be denied.

/*
	Secure POST Requests
	@ https://m0n.co/wp-requests
*/
function shapeSpace_secure_post_requests() {
	
	if (isset($_SERVER['REQUEST_METHOD'])) {
		
		$method = $_SERVER['REQUEST_METHOD'];
		
		if (strtoupper($method) === 'POST') {
			
			$host = @gethostbyaddr($address);
			
			if ($host !== 'example.com') {
				
				status_header(403);
				exit;
				
			}
			
		}
		
	}
	
}
add_action('parse_request', 'shapeSpace_secure_post_requests', 1);

Again, this should be mostly self-explanatory by examining the code should say better than my sloppy English. But in a nutshell, the code checks if the request method is POST. If so, it checks if the host name matches the name of your site. If it does not match, a 403 “Forbidden” status is sent in response.

Related: To modify POST requests using Apache/.htaccess, check out my tutorial on securing POST requests for WordPress.

Example: Send POST Alerts

For this example, we hook into parse_request with a function that sends an email alert for each POST request. This technique demonstrates how to get other $_SERVER variables, like IP Address, Request URI, and Referrer.

/*
	Send POST Alerts
	@ https://m0n.co/wp-requests
*/
function shapeSpace_send_post_alerts() {
	
	if (isset($_SERVER['REQUEST_METHOD'])) {
		
		$method = $_SERVER['REQUEST_METHOD'];
		
		if (strtoupper($method) === 'POST') {
			
			$email = get_bloginfo('admin_email');
			
			$request  = isset($_SERVER['REQUEST_URI'])  ? $_SERVER['REQUEST_URI']  : '';
			$address  = isset($_SERVER['REMOTE_ADDR'])  ? $_SERVER['REMOTE_ADDR']  : '';
			$referrer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
			
			$message = esc_html($address) . "\n" . esc_html($request) . "\n" . esc_html($referrer);
			
			mail($email, 'POST Alert', $message);
			
		}
		
	}
	
}
add_action('parse_request', 'shapeSpace_send_post_alerts', 1);

Again the code in this example is kept super simple, so reading the code probably will explain everything clearly. In plain English, we hook into parse_request and check the request method. If it is a POST request, then we grab server variables for the Request URI, IP Address, and Referrer URL. We then send the variable information as email alert message.

Related: For more ideas about sending email alerts with WordPress, check out my recent tutorial, How to Monitor the WordPress Login Page.

Notes for Example #2

In the previous example, we use the $_SERVER['REMOTE_ADDR'] variable to get the IP Address for the request. While this works fine most of the time, there are cases where it may be inaccurate (like when the request is made via proxy server or similar). So for more accurate results, here is a tutorial at WP-Mix that explains how to get the actual IP address.

Another note: If you want to add more request details to the alert, like for Host Name, User Agent, and so forth, check out my post on WordPress 404 email alerts. There you can find numerous variables that may be included.

Take-Home Message

To modify GET and POST requests with WordPress, hook your function into the parse_request action hook. Then use $_SERVER['REQUEST_METHOD'] to check the type of request, as well as other variables like $_GET, $_POST, $_SERVER, and so forth. The old cliche applies here: the possibilities are endless :)

Jeff Starr
About the Author
Jeff Starr = Designer. Developer. Producer. Writer. Editor. Etc.
Blackhole Pro: Trap bad bots in a virtual black hole.

3 responses to “How to Modify GET and POST Requests with WordPress”

  1. Very nice little tutorial!

    Also could a be a great way to catch those miscreants in the act with some of their tricks.

    One thing that has been bothering me for sometime in concerns with one of WordPress’s latest little “changes”:

    It seems they insist on adding the header field called “Link:” and populating it with a “Link rel”-like value, which includes the “angle-brackets” into the response header. I have tried a multitude of ways to simply delete it from the response headers before sending the final output to the user agent. – This worked well when I was still using “mod_php” in my development machine by simply “unsetting” it within the .htaccess file.

    However,

    I am switching my servers over to using PHP-FPM, instead of MOD_PHP, to add some more security to my sites, and the .htaccess trick, as well as any PHP tricks are failing miserably to remove the unwanted response header ( “Link: . . . “).

    So, I do not know if you have ever played with PHP-FPM (on Apache2 OR Nginx) yet. I do know that using the MOD-PROXY-FCGI is necessary to use PHP-FPM. Therefore, I am at my wit’s end on this little problem?

    Anyway,

    Again, a great and informative article, and thanks for the great “how-to’s”.

    – Jim S.

    • Jeff Starr
      Jeff Starr 2020/01/16 1:51 pm

      Thanks Jim! Always good to hear from you :)

      • I realize this is a bit off the current subject, but I believe I have found my needed solution.

        It seems that starting with WordPress 5.2 +, I have to use TWO (2) “remove_action()” statements in my theme’s “functions” file.

        remove_action( 'template_redirect', 'rest_output_link_header', 11, 0 );
        remove_action( 'template_redirect', 'wp_shortlink_header', 11, 0 );

        In order to remove the "Link: . . ." header field completely. It took me a while to find the declarations for adding them in the "default-filters.php" file within ./wp-includes .

        So,

        I hope this helps others, who may have been looking for, into solving this issue! I never was big on "bloat" (in HTML, nor the Headers), as this was why I moved all my computing to Linux and other open-source.

        - Jim S.

Comments are closed for this post. Something to add? Let me know.
Welcome
Perishable Press is operated by Jeff Starr, a professional web developer and book author with two decades of experience. Here you will find posts about web development, WordPress, security, and more »
BBQ Pro: The fastest firewall to protect your WordPress.
Thoughts
Playing the long game.
They have weaponized the idiots.
Good software never steals focus from the user. Even during startup.
After 10 years running my own business, I still manage schedules and tasks using old school post-it notes, sometimes simple sometimes very elaborate.
You know those sites, where you're trying to just grab a quick bit of information but the page is shifting all over the place as it loads up 3 million advertisements.
Selling two of my top WordPress domains, wp-zen.com & zen-wp.com $300 for both. Aged 9 years. Drop a line if interested.
Never force your users to type out a password (or any long string of characters) by blocking the paste function. Typing long strings leads to MORE errors than simple copy/paste.