How to Fix Common WooCommerce REST API Issues

If you’ve ever been stuck trying to figure out API issues when working with WooCommerce, you’ve come to the right place.

WooCommerce has had its own API since February 2014 with the release of Version 2.1 “Peppy Penguin”, later switching to the core WordPress REST API in 2015 with release WordPress 4.4 and WooCommerce Version 2.6.

But despite almost 4 years in the wild, it’s not uncommon to run into “gotcha!” moments when attempting to make use of the REST API. It’s a frustration that leaves many a developer scratching their head and wondering why things aren’t working.

Even after a quick google or search of Stack Exchange, it’s not often immediately apparent what the issue is or how to solve.

So in this post, I’ll round up some of the common issues we’ve faced whilst attempting to connect to a customer’s store via their API endpoints and how we’ve solved them. Hopefully it will save you time chasing your tail searching for solutions.

WooCommerce and the WP REST API: Where It Tends to Go Wrong

This won’t come as a surprise but two areas that we’ve had the most trouble with are discovery and authentication.

1. Discovery

Unlike other REST APIs, the WordPress REST API is distributed and available individually on each site that supports it. This means there is no singular API root or base to contact.

To help identify what the root is you can use a discovery process. The REST API Handbook provides some good information about some of the methods and techniques you can use to do this.

The handbook recommends the “link header” method as the preferred way to handle discovery. When enabled, the REST API automatically adds a Link header to all front-end pages that looks like the following:

Link: <http://example.com/wp-json/>; rel="https://api.w.org/">

By sending a HEAD request to any of your sites’ front-end pages, you can then retrieve the Link header and parse it for the root URL. Easy.

There are also other methods that can be used, such as checking for a link meta element in the page source (and parsing it for the root URL similar to the header method above), but they are slightly more complicated to implement.

Even though there are a few different methods available sometimes some (or all of them) are just not available.

2. Authentication

Not all the information available via the API is publicly accessible. To ensure that only those authorized to access said information can do so, there are a number of different methods available to authenticate users.

The default methods used by the WooCommerce API are HTTP Basic Authentication (which can only be performed over HTTPS) and OAuth 1.0a “one-legged” authentication.

OAuth 1.0a is a pain to set up so the most common method we’ve found is Basic Authentication. The trouble is, many hosts and/or managed services don’t work out of the box with basic authentication authorization header and require some adjustments to their configuration to correctly handle it.

Issue #1: Caching Plugins Removing Headers

We’ve found that many caching plugins will remove headers when serving up cached content. In certain configurations, both W3 Total Cache and WP Supercache will remove them.

For example:

✅ With caching disabled in WP Supercache the Link header is present:

With caching disabled
With caching disabled.

💥 But when you enable caching in the default configuration it gets stripped out:

With caching enabled
With caching enabled.

The easiest method we’ve found to get the header back in this scenario is to enable the “Cache HTTP headers with page content” option:

Caching options
Enabling “Cache HTT headers with page content” options in caching.

Similarly, with W3 Total Cache, if you simply use Enhanced Disk Page caching and do a head request on a cached page you will not see any Link header. Alternatively, if you instead enable Disk Caching the Link header comes back.

W3TC is extremely configurable and there are options for “Disable caching of HEAD HTTP requests” and “Specify Additional Page Headers to Cache”.

We recommend consulting with a developer to ensure there are no unwanted side effects for your specific caching situation when adjusting the cache handling of your headers.

It’s only a little more work, but we recommend falling back to checking for the link element meta if the link header isn’t available – especially if you know you have to deal with sites using caching plugins – as the caching plugins don’t appear to mess with meta elements nearly as much.

Issue #2: User Agent Blocking

If you are using a WordPress site to make requests to another site via the API and you’re using the core HTTP request methods such as wp_remote_request() or wp_remote_get(), the default User Agent used is in the following format:

WordPress/<<WP VERSION>>; <<HOME_URL>>

Sometimes, hosts, security services and/or security plugins may be configured to block requests that reference the WordPress user agent. This can obviously affect both discovery and authentication aspects of using the API in certain scenarios.

The primary reason for blocking based on the User Agent is to protect against malicious requests from WordPress sites – such as those caused in the (old) WordPress Pingback DDos Attacks.

Services such as Cloudflare have Web Application Firewall rulesets that may block the requests, or your Apache configuration may set up to do this either by your host or friendly neighborhood web designer. If you encounter weird behavior when attempting to access an API it’s worth checking for any User Agent blocking.

Issue #3: WordPress Login Page Doesn’t Display Link Headers (or Element)

If you are trying to perform discovery on a site that is members-only, which redirects straight away to wp-login.php (perhaps using a plugin like Force Login) then you won’t be able to use the link header or link element discovery process.

Even though the API Handbook specifies that…

“The REST API automatically adds a Link header to all front-end pages.”

…and…

“This auto-discovery can be applied to any URL served by a WordPress installation.”

…the default WordPress login page does not display the API link headers or the link element meta. This kind of makes sense as it is typically not a front-end page BUT it can definitely catch you out.

Depending on how much control you have over the sites you want to use, the discovery process on the link header and link element can be added to wp-login.php easily enough through the use of actions.

A simple plugin that demonstrates how to add them in is:

Note: The site that you are performing discovery on in this process will likely have its API restricted to authenticated users only as well, in which case you will need to authenticate in order to be able to view the API root/index information anyway. If you have credentials already you’ve probably recorded the root URL location as well and don’t need to do discovery.

Issue #4: Basic Authentication Headers Are Not Passed Through with PHP in CGI Mode

Another common issue we’ve come across is where the web server hosting a WooCommerce site does not pass the Basic Authentication header information through to PHP in CGI mode by default.

More technically put, what happens is the http Authorization header that your web server (e.g. Apache) receives in the request doesn’t end up populating the PHP $_SERVER['HTTP_AUTHORIZATION'] variable that PHP uses to populate the $_SERVER['PHP_AUTH_USER'] and $_SERVER['PHP_AUTH_PW'] variables. These are what WooCommerce uses for basic authentication.

When the variables are missing, this results in a 401 error with “Consumer secret is invalid” or “Unauthorized” even though the credentials sent are correct.

You could look at using OAuth 1.0a but as above it really can be very painful to set up. The next most obvious way around this is to perform basic authentication by including the credentials in the URL using query/get parameters, but that just isn’t very secure even if it is via HTTPS and I wouldn’t recommend it.

So how do we solve the issue using headers? Unfortunately there doesn’t appear to be an all-in-one solution that solves it for everyone. But here are some things to try if you are using apache.

Solution #1

The solution we’ve found that works the majority of times is to use a simple WordPress .htaccess modification.

Specifically include E=HTTP_AUTHORIZATION:%{HTTP:Authorization}, in the first [L].

For reference, the default WordPress .htaccess files can be found here.

Solution #2

In some situations the above solution will result in apache populating the $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] variable only. Apache prepends `REDIRECT_` to the variable). This alone isn’t used by WooCommerce.

The next approach we’ve seen work well is to instead add the following to your apache configuration:

SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1

For best results it can go in your main/global apache configuration file (e.g. `apache2.conf` or `httpd.conf` or individual site config).

It can also be placed in your `.htaccess` file above the WordPress rules. Like with Solution 1 this will sometimes only result in the `$_SERVER[‘REDIRECT_HTTP_AUTHORIZATION’]` variable being populated.

Solution #3

If you are using mod_proxy or  mod_proxycgi and Apache 2.4.13+ there is also a CGIPassAuth directive that can be used within your main apache config file or .htaccess CGIPassAuth on.

Check out the comments on “All authentication methods use “Authorization” header, which is unreliable” over at GitHub for more.

For Apache versions prior to 2.4.13, Solution #2 will probably be your go-to.

Solution #4

If you use mod_fastcgi another approach we’ve seen work is to make sure your virtual host fastcgi configuration uses the -pass-header Authorization option/flag.

For example within your <VirtualHost></VirtualHost> you’ll want to have something that looks like (including the -pass-header Authorization):

Alternatively, the following may work for you depending on your set up:

FastCgiConfig -pass-header Authorization

Conclusion

Hopefully, I’ve saved you some time running around in circles trying to figure out these API issues.

These are issues we’ve experienced first-hand and worked through to solve whilst attempting to connect to customer stores via their API endpoints.

Each of these issues isn’t all that hard to solve on its own, when you combine a few on the one site – e.g. user agent blocking, caching stripping out link headers and then authentication headers not being pass through – it can get extremely complicated to try and figure things out.

Have you worked with WooCommerce REST API before? Have you run into the issues we covered in this post? Are there other API issues you’ve come across or have you used a different solution? Let us know in the comments.

One Comment

  1. After troubleshooting the issue for most of the afternoon and reading a ton of Github posts, your post seems to be the one with the fix for me.

    I’ve implemented ‘Issue #4, Solution #1’ and I seem to be able to connect to the API again with Postman.

    Next is checking if the system of the fulfilment center can do the same. But I don’t expect any issues there.

    Thanks!

Comments are closed.